REPORT zabapgit_standalone LINE-SIZE 100. * See http://www.abapgit.org ******************************************************************************** * The MIT License (MIT) * * Copyright (c) 2014 abapGit Contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ******************************************************************************** INTERFACE zif_abapgit_version DEFERRED. INTERFACE zif_abapgit_definitions DEFERRED. INTERFACE zif_abapgit_xml_output DEFERRED. INTERFACE zif_abapgit_xml_input DEFERRED. INTERFACE zif_abapgit_log DEFERRED. INTERFACE zif_abapgit_popups DEFERRED. INTERFACE zif_abapgit_frontend_services DEFERRED. INTERFACE zif_abapgit_services_repo DEFERRED. INTERFACE zif_abapgit_services_git DEFERRED. INTERFACE zif_abapgit_progress DEFERRED. INTERFACE zif_abapgit_html_table DEFERRED. INTERFACE zif_abapgit_html_popup DEFERRED. INTERFACE zif_abapgit_html_form DEFERRED. INTERFACE zif_abapgit_gui_render_item DEFERRED. INTERFACE zif_abapgit_gui_page_title DEFERRED. INTERFACE zif_abapgit_gui_menu_provider DEFERRED. INTERFACE zif_abapgit_gui_page_flow DEFERRED. INTERFACE zif_abapgit_flow_exit DEFERRED. INTERFACE zif_abapgit_html_viewer DEFERRED. INTERFACE zif_abapgit_html DEFERRED. INTERFACE zif_abapgit_gui_services DEFERRED. INTERFACE zif_abapgit_gui_renderable DEFERRED. INTERFACE zif_abapgit_gui_modal DEFERRED. INTERFACE zif_abapgit_gui_html_processor DEFERRED. INTERFACE zif_abapgit_gui_hotkeys DEFERRED. INTERFACE zif_abapgit_gui_hotkey_ctl DEFERRED. INTERFACE zif_abapgit_gui_event_handler DEFERRED. INTERFACE zif_abapgit_gui_event DEFERRED. INTERFACE zif_abapgit_gui_error_handler DEFERRED. INTERFACE zif_abapgit_gui_asset_manager DEFERRED. INTERFACE zif_abapgit_repo_srv DEFERRED. INTERFACE zif_abapgit_repo_online DEFERRED. INTERFACE zif_abapgit_repo_listener DEFERRED. INTERFACE zif_abapgit_repo_checksums DEFERRED. INTERFACE zif_abapgit_repo DEFERRED. INTERFACE zif_abapgit_dot_abapgit DEFERRED. INTERFACE zif_abapgit_stage_logic DEFERRED. INTERFACE zif_abapgit_merge DEFERRED. INTERFACE zif_abapgit_object_filter DEFERRED. INTERFACE zif_abapgit_persistence DEFERRED. INTERFACE zif_abapgit_persist_user DEFERRED. INTERFACE zif_abapgit_persist_settings DEFERRED. INTERFACE zif_abapgit_persist_repo_cs DEFERRED. INTERFACE zif_abapgit_persist_repo DEFERRED. INTERFACE zif_abapgit_objects DEFERRED. INTERFACE zif_abapgit_object DEFERRED. INTERFACE zif_abapgit_comparator DEFERRED. INTERFACE zif_abapgit_lxe_texts DEFERRED. INTERFACE zif_abapgit_longtexts DEFERRED. INTERFACE zif_abapgit_lang_definitions DEFERRED. INTERFACE zif_abapgit_i18n_file DEFERRED. INTERFACE zif_abapgit_object_tabl DEFERRED. INTERFACE zif_abapgit_sap_report DEFERRED. INTERFACE zif_abapgit_sap_package DEFERRED. INTERFACE zif_abapgit_sap_namespace DEFERRED. INTERFACE zif_abapgit_function_module DEFERRED. INTERFACE zif_abapgit_field_rules DEFERRED. INTERFACE zif_abapgit_oo_object_fnc DEFERRED. INTERFACE zif_abapgit_gui_jumper DEFERRED. INTERFACE zif_abapgit_object_enhs DEFERRED. INTERFACE zif_abapgit_object_enho DEFERRED. INTERFACE zif_abapgit_ecatt_upload DEFERRED. INTERFACE zif_abapgit_ecatt_download DEFERRED. INTERFACE zif_abapgit_ecatt DEFERRED. INTERFACE zif_abapgit_tadir DEFERRED. INTERFACE zif_abapgit_aff_types_v1 DEFERRED. INTERFACE zif_abapgit_aff_oo_types_v1 DEFERRED. INTERFACE zif_abapgit_aff_intf_v1 DEFERRED. INTERFACE zif_abapgit_aff_type_mapping DEFERRED. INTERFACE zif_abapgit_aff_registry DEFERRED. INTERFACE zif_abapgit_ajson_types DEFERRED. INTERFACE zif_abapgit_ajson_mapping DEFERRED. INTERFACE zif_abapgit_ajson_filter DEFERRED. INTERFACE zif_abapgit_ajson DEFERRED. INTERFACE zif_abapgit_code_inspector DEFERRED. INTERFACE zif_abapgit_http_response DEFERRED. INTERFACE zif_abapgit_http_agent DEFERRED. INTERFACE zif_abapgit_pr_enum_provider DEFERRED. INTERFACE zif_abapgit_git_transport DEFERRED. INTERFACE zif_abapgit_git_definitions DEFERRED. INTERFACE zif_abapgit_gitv2_porcelain DEFERRED. INTERFACE zif_abapgit_exit DEFERRED. INTERFACE zif_abapgit_auth DEFERRED. INTERFACE zif_abapgit_environment DEFERRED. INTERFACE zif_abapgit_data_supporter DEFERRED. INTERFACE zif_abapgit_data_serializer DEFERRED. INTERFACE zif_abapgit_data_deserializer DEFERRED. INTERFACE zif_abapgit_data_config DEFERRED. INTERFACE zif_abapgit_default_transport DEFERRED. INTERFACE zif_abapgit_cts_api DEFERRED. INTERFACE zif_abapgit_background DEFERRED. INTERFACE zif_abapgit_apack_definitions DEFERRED. CLASS zcl_abapgit_factory DEFINITION DEFERRED. CLASS zcl_abapgit_xml_pretty DEFINITION DEFERRED. CLASS zcl_abapgit_xml_output DEFINITION DEFERRED. CLASS zcl_abapgit_xml_input DEFINITION DEFERRED. CLASS zcl_abapgit_xml DEFINITION DEFERRED. CLASS zcl_abapgit_utils DEFINITION DEFERRED. CLASS zcl_abapgit_timer DEFINITION DEFERRED. CLASS zcl_abapgit_string_map DEFINITION DEFERRED. CLASS zcl_abapgit_string_buffer DEFINITION DEFERRED. CLASS zcl_abapgit_path DEFINITION DEFERRED. CLASS zcl_abapgit_log DEFINITION DEFERRED. CLASS zcl_abapgit_diff DEFINITION DEFERRED. CLASS zcl_abapgit_convert DEFINITION DEFERRED. CLASS zcl_abapgit_ui_factory DEFINITION DEFERRED. CLASS zcl_abapgit_popups DEFINITION DEFERRED. CLASS zcl_abapgit_password_dialog DEFINITION DEFERRED. CLASS zcl_abapgit_frontend_services DEFINITION DEFERRED. CLASS zcl_abapgit_frontend_no_gui DEFINITION DEFERRED. CLASS zcl_abapgit_services_repo DEFINITION DEFERRED. CLASS zcl_abapgit_services_git DEFINITION DEFERRED. CLASS zcl_abapgit_services_abapgit DEFINITION DEFERRED. CLASS zcl_abapgit_gui_router DEFINITION DEFERRED. CLASS zcl_abapgit_progress DEFINITION DEFERRED. CLASS zcl_abapgit_popup_tag_list DEFINITION DEFERRED. CLASS zcl_abapgit_popup_pull_request DEFINITION DEFERRED. CLASS zcl_abapgit_popup_code_insp DEFINITION DEFERRED. CLASS zcl_abapgit_popup_branch_list DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_tutorial DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_tags DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_stage DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_run_bckg DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_repo_view DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_repo_over DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_pull DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_patch DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_merge_sel DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_merge_res DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_merge DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_ex_pckage DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_ex_object DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_diff_base DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_diff DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_debuginfo DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_data DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_commit DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_sett_repo DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_sett_remo DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_sett_pers DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_sett_locl DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_sett_info DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_sett_glob DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_sett_bckg DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_addonline DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_addofflin DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_db_entry DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_db DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_whereused DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_syntax DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_runit DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_codi_base DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_code_insp DEFINITION DEFERRED. CLASS zcl_abapgit_log_viewer DEFINITION DEFERRED. CLASS zcl_abapgit_html_toolbar DEFINITION DEFERRED. CLASS zcl_abapgit_html_table DEFINITION DEFERRED. CLASS zcl_abapgit_html_form_utils DEFINITION DEFERRED. CLASS zcl_abapgit_html_form DEFINITION DEFERRED. CLASS zcl_abapgit_html_action_utils DEFINITION DEFERRED. CLASS zcl_abapgit_gui_picklist DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_hoc DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page DEFINITION DEFERRED. CLASS zcl_abapgit_gui_menus DEFINITION DEFERRED. CLASS zcl_abapgit_gui_in_page_modal DEFINITION DEFERRED. CLASS zcl_abapgit_gui_component DEFINITION DEFERRED. CLASS zcl_abapgit_gui_chunk_lib DEFINITION DEFERRED. CLASS zcl_abapgit_gui_buttons DEFINITION DEFERRED. CLASS zcl_abapgit_exception_viewer DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_flow DEFINITION DEFERRED. CLASS zcl_abapgit_flow_exit DEFINITION DEFERRED. CLASS zcl_abapgit_html_viewer_gui DEFINITION DEFERRED. CLASS zcl_abapgit_html_parts DEFINITION DEFERRED. CLASS zcl_abapgit_html DEFINITION DEFERRED. CLASS zcl_abapgit_gui_utils DEFINITION DEFERRED. CLASS zcl_abapgit_gui_html_processor DEFINITION DEFERRED. CLASS zcl_abapgit_gui_hotkey_ctl DEFINITION DEFERRED. CLASS zcl_abapgit_gui_event DEFINITION DEFERRED. CLASS zcl_abapgit_gui_css_processor DEFINITION DEFERRED. CLASS zcl_abapgit_gui_asset_manager DEFINITION DEFERRED. CLASS zcl_abapgit_gui DEFINITION DEFERRED. CLASS zcl_abapgit_gui_page_template DEFINITION DEFERRED. CLASS zcl_abapgit_syntax_xml DEFINITION DEFERRED. CLASS zcl_abapgit_syntax_txt DEFINITION DEFERRED. CLASS zcl_abapgit_syntax_json DEFINITION DEFERRED. CLASS zcl_abapgit_syntax_js DEFINITION DEFERRED. CLASS zcl_abapgit_syntax_highlighter DEFINITION DEFERRED. CLASS zcl_abapgit_syntax_factory DEFINITION DEFERRED. CLASS zcl_abapgit_syntax_css DEFINITION DEFERRED. CLASS zcl_abapgit_syntax_abap DEFINITION DEFERRED. CLASS zcl_abapgit_repo_status DEFINITION DEFERRED. CLASS zcl_abapgit_repo_srv DEFINITION DEFERRED. CLASS zcl_abapgit_repo_online DEFINITION DEFERRED. CLASS zcl_abapgit_repo_offline DEFINITION DEFERRED. CLASS zcl_abapgit_repo_cs_migration DEFINITION DEFERRED. CLASS zcl_abapgit_repo_content_list DEFINITION DEFERRED. CLASS zcl_abapgit_repo_checksums DEFINITION DEFERRED. CLASS zcl_abapgit_repo DEFINITION DEFERRED. CLASS zcl_abapgit_dot_abapgit DEFINITION DEFERRED. CLASS zcl_abapgit_zip DEFINITION DEFERRED. CLASS zcl_abapgit_version DEFINITION DEFERRED. CLASS zcl_abapgit_repo_requirements DEFINITION DEFERRED. CLASS zcl_abapgit_repo_news DEFINITION DEFERRED. CLASS zcl_abapgit_repo_labels DEFINITION DEFERRED. CLASS zcl_abapgit_repo_item_state DEFINITION DEFERRED. CLASS zcl_abapgit_stage_logic DEFINITION DEFERRED. CLASS zcl_abapgit_stage DEFINITION DEFERRED. CLASS zcl_abapgit_merge DEFINITION DEFERRED. CLASS zcl_abapgit_repo_filter DEFINITION DEFERRED. CLASS zcl_abapgit_object_filter_tran DEFINITION DEFERRED. CLASS zcl_abapgit_persistence_user DEFINITION DEFERRED. CLASS zcl_abapgit_persistence_repo DEFINITION DEFERRED. CLASS zcl_abapgit_persistence_db DEFINITION DEFERRED. CLASS zcl_abapgit_persist_settings DEFINITION DEFERRED. CLASS zcl_abapgit_persist_packages DEFINITION DEFERRED. CLASS zcl_abapgit_persist_migrate DEFINITION DEFERRED. CLASS zcl_abapgit_persist_factory DEFINITION DEFERRED. CLASS zcl_abapgit_persist_background DEFINITION DEFERRED. CLASS zcl_abapgit_migrations DEFINITION DEFERRED. CLASS zcl_abapgit_objects_super DEFINITION DEFERRED. CLASS zcl_abapgit_objects_program DEFINITION DEFERRED. CLASS zcl_abapgit_objects_generic DEFINITION DEFERRED. CLASS zcl_abapgit_objects_factory DEFINITION DEFERRED. CLASS zcl_abapgit_objects_bridge DEFINITION DEFERRED. CLASS zcl_abapgit_objects DEFINITION DEFERRED. CLASS zcl_abapgit_object_xslt DEFINITION DEFERRED. CLASS zcl_abapgit_object_xinx DEFINITION DEFERRED. CLASS zcl_abapgit_object_webi DEFINITION DEFERRED. CLASS zcl_abapgit_object_wdyn DEFINITION DEFERRED. CLASS zcl_abapgit_object_wdya DEFINITION DEFERRED. CLASS zcl_abapgit_object_wdcc DEFINITION DEFERRED. CLASS zcl_abapgit_object_wdca DEFINITION DEFERRED. CLASS zcl_abapgit_object_wapa DEFINITION DEFERRED. CLASS zcl_abapgit_object_w3xx_super DEFINITION DEFERRED. CLASS zcl_abapgit_object_w3mi DEFINITION DEFERRED. CLASS zcl_abapgit_object_w3ht DEFINITION DEFERRED. CLASS zcl_abapgit_object_view DEFINITION DEFERRED. CLASS zcl_abapgit_object_vcls DEFINITION DEFERRED. CLASS zcl_abapgit_object_ueno DEFINITION DEFERRED. CLASS zcl_abapgit_object_udmo DEFINITION DEFERRED. CLASS zcl_abapgit_object_ucsa DEFINITION DEFERRED. CLASS zcl_abapgit_object_type DEFINITION DEFERRED. CLASS zcl_abapgit_object_ttyp DEFINITION DEFERRED. CLASS zcl_abapgit_object_tran DEFINITION DEFERRED. CLASS zcl_abapgit_object_tobj DEFINITION DEFERRED. CLASS zcl_abapgit_object_sxci DEFINITION DEFERRED. CLASS zcl_abapgit_object_suso DEFINITION DEFERRED. CLASS zcl_abapgit_object_sush DEFINITION DEFERRED. CLASS zcl_abapgit_object_susc DEFINITION DEFERRED. CLASS zcl_abapgit_object_sucu DEFINITION DEFERRED. CLASS zcl_abapgit_object_styl DEFINITION DEFERRED. CLASS zcl_abapgit_object_stvi DEFINITION DEFERRED. CLASS zcl_abapgit_object_ssst DEFINITION DEFERRED. CLASS zcl_abapgit_object_ssfo DEFINITION DEFERRED. CLASS zcl_abapgit_object_srvd DEFINITION DEFERRED. CLASS zcl_abapgit_object_srvb DEFINITION DEFERRED. CLASS zcl_abapgit_object_srfc DEFINITION DEFERRED. CLASS zcl_abapgit_object_sqsc DEFINITION DEFERRED. CLASS zcl_abapgit_object_sprx DEFINITION DEFERRED. CLASS zcl_abapgit_object_sppf DEFINITION DEFERRED. CLASS zcl_abapgit_object_splo DEFINITION DEFERRED. CLASS zcl_abapgit_object_sots DEFINITION DEFERRED. CLASS zcl_abapgit_object_sod2 DEFINITION DEFERRED. CLASS zcl_abapgit_object_sod1 DEFINITION DEFERRED. CLASS zcl_abapgit_object_sobj DEFINITION DEFERRED. CLASS zcl_abapgit_object_smtg DEFINITION DEFERRED. CLASS zcl_abapgit_object_smim DEFINITION DEFERRED. CLASS zcl_abapgit_object_sktd DEFINITION DEFERRED. CLASS zcl_abapgit_object_sicf DEFINITION DEFERRED. CLASS zcl_abapgit_object_shma DEFINITION DEFERRED. CLASS zcl_abapgit_object_shlp DEFINITION DEFERRED. CLASS zcl_abapgit_object_shi8 DEFINITION DEFERRED. CLASS zcl_abapgit_object_shi5 DEFINITION DEFERRED. CLASS zcl_abapgit_object_shi3 DEFINITION DEFERRED. CLASS zcl_abapgit_object_sfsw DEFINITION DEFERRED. CLASS zcl_abapgit_object_sfpi DEFINITION DEFERRED. CLASS zcl_abapgit_object_sfpf DEFINITION DEFERRED. CLASS zcl_abapgit_object_sfbs DEFINITION DEFERRED. CLASS zcl_abapgit_object_sfbf DEFINITION DEFERRED. CLASS zcl_abapgit_object_scvi DEFINITION DEFERRED. CLASS zcl_abapgit_object_scp1 DEFINITION DEFERRED. CLASS zcl_abapgit_object_saxx_super DEFINITION DEFERRED. CLASS zcl_abapgit_object_sapc DEFINITION DEFERRED. CLASS zcl_abapgit_object_samc DEFINITION DEFERRED. CLASS zcl_abapgit_object_prog DEFINITION DEFERRED. CLASS zcl_abapgit_object_prag DEFINITION DEFERRED. CLASS zcl_abapgit_object_pinf DEFINITION DEFERRED. CLASS zcl_abapgit_object_pers DEFINITION DEFERRED. CLASS zcl_abapgit_object_pdxx_super DEFINITION DEFERRED. CLASS zcl_abapgit_object_pdts DEFINITION DEFERRED. CLASS zcl_abapgit_object_para DEFINITION DEFERRED. CLASS zcl_abapgit_object_otgr DEFINITION DEFERRED. CLASS zcl_abapgit_object_odso DEFINITION DEFERRED. CLASS zcl_abapgit_object_oa2p DEFINITION DEFERRED. CLASS zcl_abapgit_object_nspc DEFINITION DEFERRED. CLASS zcl_abapgit_object_nrob DEFINITION DEFERRED. CLASS zcl_abapgit_object_msag DEFINITION DEFERRED. CLASS zcl_abapgit_object_jobd DEFINITION DEFERRED. CLASS zcl_abapgit_object_iwvb DEFINITION DEFERRED. CLASS zcl_abapgit_object_iwsv DEFINITION DEFERRED. CLASS zcl_abapgit_object_iwsg DEFINITION DEFERRED. CLASS zcl_abapgit_object_iwpr DEFINITION DEFERRED. CLASS zcl_abapgit_object_iwom DEFINITION DEFERRED. CLASS zcl_abapgit_object_iwmo DEFINITION DEFERRED. CLASS zcl_abapgit_object_iobj DEFINITION DEFERRED. CLASS zcl_abapgit_object_intf DEFINITION DEFERRED. CLASS zcl_abapgit_object_iext DEFINITION DEFERRED. CLASS zcl_abapgit_object_idoc DEFINITION DEFERRED. CLASS zcl_abapgit_object_iaxu DEFINITION DEFERRED. CLASS zcl_abapgit_object_iatu DEFINITION DEFERRED. CLASS zcl_abapgit_object_iasp DEFINITION DEFERRED. CLASS zcl_abapgit_object_iarp DEFINITION DEFERRED. CLASS zcl_abapgit_object_iamu DEFINITION DEFERRED. CLASS zcl_abapgit_object_g4bs DEFINITION DEFERRED. CLASS zcl_abapgit_object_g4ba DEFINITION DEFERRED. CLASS zcl_abapgit_object_fugr DEFINITION DEFERRED. CLASS zcl_abapgit_object_ftgl DEFINITION DEFERRED. CLASS zcl_abapgit_object_form DEFINITION DEFERRED. CLASS zcl_abapgit_object_fdt0 DEFINITION DEFERRED. CLASS zcl_abapgit_object_ensc DEFINITION DEFERRED. CLASS zcl_abapgit_object_enqu DEFINITION DEFERRED. CLASS zcl_abapgit_object_enhs DEFINITION DEFERRED. CLASS zcl_abapgit_object_enho DEFINITION DEFERRED. CLASS zcl_abapgit_object_enhc DEFINITION DEFERRED. CLASS zcl_abapgit_object_ecvo DEFINITION DEFERRED. CLASS zcl_abapgit_object_ectd DEFINITION DEFERRED. CLASS zcl_abapgit_object_ectc DEFINITION DEFERRED. CLASS zcl_abapgit_object_ecsp DEFINITION DEFERRED. CLASS zcl_abapgit_object_ecsd DEFINITION DEFERRED. CLASS zcl_abapgit_object_ecatt_super DEFINITION DEFERRED. CLASS zcl_abapgit_object_ecat DEFINITION DEFERRED. CLASS zcl_abapgit_object_dtel DEFINITION DEFERRED. CLASS zcl_abapgit_object_dtdc DEFINITION DEFERRED. CLASS zcl_abapgit_object_dsys DEFINITION DEFERRED. CLASS zcl_abapgit_object_drul DEFINITION DEFERRED. CLASS zcl_abapgit_object_doma DEFINITION DEFERRED. CLASS zcl_abapgit_object_docv DEFINITION DEFERRED. CLASS zcl_abapgit_object_doct DEFINITION DEFERRED. CLASS zcl_abapgit_object_dial DEFINITION DEFERRED. CLASS zcl_abapgit_object_devc DEFINITION DEFERRED. CLASS zcl_abapgit_object_ddlx DEFINITION DEFERRED. CLASS zcl_abapgit_object_ddls DEFINITION DEFERRED. CLASS zcl_abapgit_object_dcls DEFINITION DEFERRED. CLASS zcl_abapgit_object_cus2 DEFINITION DEFERRED. CLASS zcl_abapgit_object_cus1 DEFINITION DEFERRED. CLASS zcl_abapgit_object_cus0 DEFINITION DEFERRED. CLASS zcl_abapgit_object_cmpt DEFINITION DEFERRED. CLASS zcl_abapgit_object_cmod DEFINITION DEFERRED. CLASS zcl_abapgit_object_clas DEFINITION DEFERRED. CLASS zcl_abapgit_object_chdo DEFINITION DEFERRED. CLASS zcl_abapgit_object_char DEFINITION DEFERRED. CLASS zcl_abapgit_object_bdef DEFINITION DEFERRED. CLASS zcl_abapgit_object_avas DEFINITION DEFERRED. CLASS zcl_abapgit_object_avar DEFINITION DEFERRED. CLASS zcl_abapgit_object_auth DEFINITION DEFERRED. CLASS zcl_abapgit_object_asfc DEFINITION DEFERRED. CLASS zcl_abapgit_object_area DEFINITION DEFERRED. CLASS zcl_abapgit_object_aqsg DEFINITION DEFERRED. CLASS zcl_abapgit_object_aqqu DEFINITION DEFERRED. CLASS zcl_abapgit_object_aqbg DEFINITION DEFERRED. CLASS zcl_abapgit_object_apis DEFINITION DEFERRED. CLASS zcl_abapgit_object_amsd DEFINITION DEFERRED. CLASS zcl_abapgit_object_aifc DEFINITION DEFERRED. CLASS zcl_abapgit_object_acid DEFINITION DEFERRED. CLASS zcl_abapgit_sots_handler DEFINITION DEFERRED. CLASS zcl_abapgit_sotr_handler DEFINITION DEFERRED. CLASS zcl_abapgit_properties_file DEFINITION DEFERRED. CLASS zcl_abapgit_po_file DEFINITION DEFERRED. CLASS zcl_abapgit_lxe_texts DEFINITION DEFERRED. CLASS zcl_abapgit_longtexts DEFINITION DEFERRED. CLASS zcl_abapgit_i18n_params DEFINITION DEFERRED. CLASS zcl_abapgit_object_tabl_ddl DEFINITION DEFERRED. CLASS zcl_abapgit_object_tabl_compar DEFINITION DEFERRED. CLASS zcl_abapgit_object_tabl DEFINITION DEFERRED. CLASS zcl_abapgit_sap_report DEFINITION DEFERRED. CLASS zcl_abapgit_sap_package DEFINITION DEFERRED. CLASS zcl_abapgit_sap_namespace DEFINITION DEFERRED. CLASS zcl_abapgit_function_module DEFINITION DEFERRED. CLASS zcl_abapgit_field_rules DEFINITION DEFERRED. CLASS zcl_abapgit_oo_serializer DEFINITION DEFERRED. CLASS zcl_abapgit_oo_interface DEFINITION DEFERRED. CLASS zcl_abapgit_oo_factory DEFINITION DEFERRED. CLASS zcl_abapgit_oo_class DEFINITION DEFERRED. CLASS zcl_abapgit_oo_base DEFINITION DEFERRED. CLASS zcl_abapgit_gui_jumper DEFINITION DEFERRED. CLASS zcl_abapgit_adt_link DEFINITION DEFERRED. CLASS zcl_abapgit_object_enhs_hook_d DEFINITION DEFERRED. CLASS zcl_abapgit_object_enhs_badi_d DEFINITION DEFERRED. CLASS zcl_abapgit_object_enho_wdyn DEFINITION DEFERRED. CLASS zcl_abapgit_object_enho_wdyc DEFINITION DEFERRED. CLASS zcl_abapgit_object_enho_intf DEFINITION DEFERRED. CLASS zcl_abapgit_object_enho_hook DEFINITION DEFERRED. CLASS zcl_abapgit_object_enho_fugr DEFINITION DEFERRED. CLASS zcl_abapgit_object_enho_clif DEFINITION DEFERRED. CLASS zcl_abapgit_object_enho_class DEFINITION DEFERRED. CLASS zcl_abapgit_object_enho_badi DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_val_obj_upl DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_val_obj_down DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_system_upl DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_system_downl DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_sp_upload DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_sp_download DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_script_upl DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_script_downl DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_helper DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_data_upload DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_data_downl DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_config_upl DEFINITION DEFERRED. CLASS zcl_abapgit_ecatt_config_downl DEFINITION DEFERRED. CLASS zcl_abapgit_tadir DEFINITION DEFERRED. CLASS zcl_abapgit_serialize DEFINITION DEFERRED. CLASS zcl_abapgit_objects_files DEFINITION DEFERRED. CLASS zcl_abapgit_objects_check DEFINITION DEFERRED. CLASS zcl_abapgit_objects_activation DEFINITION DEFERRED. CLASS zcl_abapgit_item_graph DEFINITION DEFERRED. CLASS zcl_abapgit_folder_logic DEFINITION DEFERRED. CLASS zcl_abapgit_filename_logic DEFINITION DEFERRED. CLASS zcl_abapgit_file_deserialize DEFINITION DEFERRED. CLASS zcl_abapgit_dependencies DEFINITION DEFERRED. CLASS zcl_abapgit_object_uist DEFINITION DEFERRED. CLASS zcl_abapgit_object_uipg DEFINITION DEFERRED. CLASS zcl_abapgit_object_smbc DEFINITION DEFERRED. CLASS zcl_abapgit_object_ront DEFINITION DEFERRED. CLASS zcl_abapgit_object_nont DEFINITION DEFERRED. CLASS zcl_abapgit_object_gsmp DEFINITION DEFERRED. CLASS zcl_abapgit_object_evtb DEFINITION DEFERRED. CLASS zcl_abapgit_object_eeec DEFINITION DEFERRED. CLASS zcl_abapgit_object_dteb DEFINITION DEFERRED. CLASS zcl_abapgit_object_drty DEFINITION DEFERRED. CLASS zcl_abapgit_object_common_aff DEFINITION DEFERRED. CLASS zcl_abapgit_object_chkv DEFINITION DEFERRED. CLASS zcl_abapgit_object_chko DEFINITION DEFERRED. CLASS zcl_abapgit_object_chkc DEFINITION DEFERRED. CLASS zcl_abapgit_json_path DEFINITION DEFERRED. CLASS zcl_abapgit_json_handler DEFINITION DEFERRED. CLASS zcl_abapgit_aff_registry DEFINITION DEFERRED. CLASS zcl_abapgit_ajson_utilities DEFINITION DEFERRED. CLASS zcl_abapgit_ajson_mapping DEFINITION DEFERRED. CLASS zcl_abapgit_ajson_filter_lib DEFINITION DEFERRED. CLASS zcl_abapgit_ajson DEFINITION DEFERRED. CLASS zcl_abapgit_where_used_tools DEFINITION DEFERRED. CLASS zcl_abapgit_code_inspector DEFINITION DEFERRED. CLASS zcl_abapgit_url DEFINITION DEFERRED. CLASS zcl_abapgit_proxy_config DEFINITION DEFERRED. CLASS zcl_abapgit_proxy_auth DEFINITION DEFERRED. CLASS zcl_abapgit_login_manager DEFINITION DEFERRED. CLASS zcl_abapgit_http_digest DEFINITION DEFERRED. CLASS zcl_abapgit_http_client DEFINITION DEFERRED. CLASS zcl_abapgit_http_agent DEFINITION DEFERRED. CLASS zcl_abapgit_http DEFINITION DEFERRED. CLASS zcl_abapgit_pr_enumerator DEFINITION DEFERRED. CLASS zcl_abapgit_pr_enum_github DEFINITION DEFERRED. CLASS zcl_abapgit_git_url DEFINITION DEFERRED. CLASS zcl_abapgit_zlib_stream DEFINITION DEFERRED. CLASS zcl_abapgit_zlib_huffman DEFINITION DEFERRED. CLASS zcl_abapgit_zlib_convert DEFINITION DEFERRED. CLASS zcl_abapgit_zlib DEFINITION DEFERRED. CLASS zcl_abapgit_hash DEFINITION DEFERRED. CLASS zcl_abapgit_git_utils DEFINITION DEFERRED. CLASS zcl_abapgit_git_transport DEFINITION DEFERRED. CLASS zcl_abapgit_git_time DEFINITION DEFERRED. CLASS zcl_abapgit_git_tag DEFINITION DEFERRED. CLASS zcl_abapgit_git_porcelain DEFINITION DEFERRED. CLASS zcl_abapgit_git_pack DEFINITION DEFERRED. CLASS zcl_abapgit_git_factory DEFINITION DEFERRED. CLASS zcl_abapgit_git_commit DEFINITION DEFERRED. CLASS zcl_abapgit_git_branch_list DEFINITION DEFERRED. CLASS zcl_abapgit_git_add_patch DEFINITION DEFERRED. CLASS zcl_abapgit_gitv2_porcelain DEFINITION DEFERRED. CLASS zcl_abapgit_exit DEFINITION DEFERRED. CLASS zcl_abapgit_auth DEFINITION DEFERRED. CLASS zcl_abapgit_user_record DEFINITION DEFERRED. CLASS zcl_abapgit_settings DEFINITION DEFERRED. CLASS zcl_abapgit_language DEFINITION DEFERRED. CLASS zcl_abapgit_feature DEFINITION DEFERRED. CLASS zcl_abapgit_environment DEFINITION DEFERRED. CLASS zcl_abapgit_abap_language_vers DEFINITION DEFERRED. CLASS zcl_abapgit_data_utils DEFINITION DEFERRED. CLASS zcl_abapgit_data_supporter DEFINITION DEFERRED. CLASS zcl_abapgit_data_serializer DEFINITION DEFERRED. CLASS zcl_abapgit_data_factory DEFINITION DEFERRED. CLASS zcl_abapgit_data_deserializer DEFINITION DEFERRED. CLASS zcl_abapgit_data_config DEFINITION DEFERRED. CLASS zcl_abapgit_transport_objects DEFINITION DEFERRED. CLASS zcl_abapgit_transport_mass DEFINITION DEFERRED. CLASS zcl_abapgit_transport_2_branch DEFINITION DEFERRED. CLASS zcl_abapgit_transport DEFINITION DEFERRED. CLASS zcl_abapgit_default_transport DEFINITION DEFERRED. CLASS zcl_abapgit_cts_api DEFINITION DEFERRED. CLASS zcl_abapgit_background_push_fi DEFINITION DEFERRED. CLASS zcl_abapgit_background_push_au DEFINITION DEFERRED. CLASS zcl_abapgit_background_pull DEFINITION DEFERRED. CLASS zcl_abapgit_background DEFINITION DEFERRED. CLASS zcl_abapgit_apack_writer DEFINITION DEFERRED. CLASS zcl_abapgit_apack_reader DEFINITION DEFERRED. CLASS zcl_abapgit_apack_migration DEFINITION DEFERRED. CLASS zcl_abapgit_apack_helper DEFINITION DEFERRED. CLASS zcx_abapgit_ajson_error DEFINITION inheriting from CX_STATIC_CHECK final create public . public section. interfaces IF_T100_MESSAGE . types: ty_rc type c length 4 . constants: begin of ZCX_AJSON_ERROR, msgid type symsgid value '00', msgno type symsgno value '001', attr1 type scx_attrname value 'A1', attr2 type scx_attrname value 'A2', attr3 type scx_attrname value 'A3', attr4 type scx_attrname value 'A4', end of ZCX_AJSON_ERROR . data RC type TY_RC read-only . data MESSAGE type STRING read-only . data LOCATION type STRING read-only . data A1 type SYMSGV read-only . data A2 type SYMSGV read-only . data A3 type SYMSGV read-only . data A4 type SYMSGV read-only . methods CONSTRUCTOR importing !TEXTID like IF_T100_MESSAGE=>T100KEY optional !PREVIOUS like PREVIOUS optional !RC type TY_RC optional !MESSAGE type STRING optional !LOCATION type STRING optional !A1 type SYMSGV optional !A2 type SYMSGV optional !A3 type SYMSGV optional !A4 type SYMSGV optional . class-methods RAISE importing !IV_MSG type STRING !IV_LOCATION type STRING optional !IS_NODE type ANY optional raising zcx_abapgit_ajson_error . methods SET_LOCATION importing !IV_LOCATION type STRING optional !IS_NODE type ANY optional preferred parameter IV_LOCATION . protected section. private section. types: begin of ty_message_parts, a1 like a1, a2 like a1, a3 like a1, a4 like a1, end of ty_message_parts. ENDCLASS. CLASS zcx_abapgit_ajson_error IMPLEMENTATION. method CONSTRUCTOR. CALL METHOD SUPER->CONSTRUCTOR EXPORTING PREVIOUS = PREVIOUS . me->RC = RC . me->MESSAGE = MESSAGE . me->LOCATION = LOCATION . me->A1 = A1 . me->A2 = A2 . me->A3 = A3 . me->A4 = A4 . clear me->textid. if textid is initial. IF_T100_MESSAGE~T100KEY = ZCX_AJSON_ERROR . else. IF_T100_MESSAGE~T100KEY = TEXTID. endif. endmethod. method raise. data lx type ref to zcx_abapgit_ajson_error. create object lx exporting message = iv_msg. lx->set_location( iv_location = iv_location is_node = is_node ). raise exception lx. endmethod. method set_location. data ls_msg type ty_message_parts. data lv_location type string. data lv_tmp type string. field-symbols type string. field-symbols type string. if iv_location is not initial. lv_location = iv_location. elseif is_node is not initial. assign component 'PATH' of structure is_node to . assign component 'NAME' of structure is_node to . if is assigned and is assigned. lv_location = && . endif. endif. if lv_location is not initial. lv_tmp = message && | @{ lv_location }|. else. lv_tmp = message. endif. ls_msg = lv_tmp. location = lv_location. a1 = ls_msg-a1. a2 = ls_msg-a2. a3 = ls_msg-a3. a4 = ls_msg-a4. endmethod. ENDCLASS. "! abapGit general error CLASS zcx_abapgit_exception DEFINITION INHERITING FROM cx_static_check CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_t100_message . CONSTANTS: BEGIN OF c_section_text, cause TYPE string VALUE `Cause`, system_response TYPE string VALUE `System response`, what_to_do TYPE string VALUE `Procedure`, sys_admin TYPE string VALUE `System administration`, END OF c_section_text . CONSTANTS: BEGIN OF c_section_token, cause TYPE string VALUE `&CAUSE&`, system_response TYPE string VALUE `&SYSTEM_RESPONSE&`, what_to_do TYPE string VALUE `&WHAT_TO_DO&`, sys_admin TYPE string VALUE `&SYS_ADMIN&`, END OF c_section_token . CLASS-DATA null TYPE string. DATA msgv1 TYPE symsgv READ-ONLY . DATA msgv2 TYPE symsgv READ-ONLY . DATA msgv3 TYPE symsgv READ-ONLY . DATA msgv4 TYPE symsgv READ-ONLY . DATA mv_longtext TYPE string READ-ONLY. DATA mt_callstack TYPE abap_callstack READ-ONLY. DATA mi_log TYPE REF TO zif_abapgit_log READ-ONLY. "! Raise exception with text "! @parameter iv_text | Text "! @parameter ix_previous | Previous exception "! @parameter ii_log | Log "! @parameter iv_longtext | Longtext "! @raising zcx_abapgit_exception | Exception CLASS-METHODS raise IMPORTING !iv_text TYPE clike !ix_previous TYPE REF TO cx_root OPTIONAL !ii_log TYPE REF TO zif_abapgit_log OPTIONAL !iv_longtext TYPE csequence OPTIONAL RAISING zcx_abapgit_exception . "! Raise exception with T100 message "!

"! Will default to sy-msg* variables. These need to be set right before calling this method. "!

"! @parameter iv_msgid | Message ID "! @parameter iv_msgno | Message number "! @parameter iv_msgv1 | Message variable 1 "! @parameter iv_msgv2 | Message variable 2 "! @parameter iv_msgv3 | Message variable 3 "! @parameter iv_msgv4 | Message variable 4 "! @parameter ii_log | Log "! @parameter ix_previous | Previous exception "! @parameter iv_longtext | Longtext "! @raising zcx_abapgit_exception | Exception CLASS-METHODS raise_t100 IMPORTING !iv_msgid TYPE symsgid DEFAULT sy-msgid !iv_msgno TYPE symsgno DEFAULT sy-msgno !iv_msgv1 TYPE symsgv DEFAULT sy-msgv1 !iv_msgv2 TYPE symsgv DEFAULT sy-msgv2 !iv_msgv3 TYPE symsgv DEFAULT sy-msgv3 !iv_msgv4 TYPE symsgv DEFAULT sy-msgv4 !ii_log TYPE REF TO zif_abapgit_log OPTIONAL !ix_previous TYPE REF TO cx_root OPTIONAL !iv_longtext TYPE csequence OPTIONAL RAISING zcx_abapgit_exception . "! Raise with text from previous exception "! @parameter ix_previous | Previous exception "! @parameter iv_longtext | Longtext "! @raising zcx_abapgit_exception | Exception CLASS-METHODS raise_with_text IMPORTING !ix_previous TYPE REF TO cx_root !iv_longtext TYPE csequence OPTIONAL RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !textid LIKE if_t100_message=>t100key OPTIONAL !previous LIKE previous OPTIONAL !log TYPE REF TO zif_abapgit_log OPTIONAL !msgv1 TYPE symsgv OPTIONAL !msgv2 TYPE symsgv OPTIONAL !msgv3 TYPE symsgv OPTIONAL !msgv4 TYPE symsgv OPTIONAL !longtext TYPE csequence OPTIONAL . METHODS get_source_position REDEFINITION . METHODS if_message~get_longtext REDEFINITION . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_generic_error_msg TYPE string VALUE `An error occurred (ZCX_ABAPGIT_EXCEPTION)`. CLASS-METHODS split_text_to_symsg IMPORTING !iv_text TYPE string RETURNING VALUE(rs_msg) TYPE symsg . METHODS save_callstack . METHODS itf_to_string IMPORTING !it_itf TYPE tline_tab RETURNING VALUE(rv_result) TYPE string . METHODS get_t100_longtext_itf RETURNING VALUE(rt_itf) TYPE tline_tab . METHODS remove_empty_section IMPORTING !iv_tabix_from TYPE i !iv_tabix_to TYPE i CHANGING !ct_itf TYPE tline_tab . METHODS replace_section_head_with_text CHANGING !cs_itf TYPE tline . CLASS-METHODS remove_newlines_from_string IMPORTING iv_string TYPE string RETURNING VALUE(rv_result) TYPE string. ENDCLASS. CLASS zcx_abapgit_exception IMPLEMENTATION. METHOD constructor ##ADT_SUPPRESS_GENERATION. super->constructor( previous = previous ). me->msgv1 = msgv1. me->msgv2 = msgv2. me->msgv3 = msgv3. me->msgv4 = msgv4. mi_log = log. mv_longtext = longtext. CLEAR me->textid. IF textid IS INITIAL. if_t100_message~t100key = if_t100_message=>default_textid. ELSE. if_t100_message~t100key = textid. ENDIF. save_callstack( ). ENDMETHOD. METHOD get_source_position. FIELD-SYMBOLS: LIKE LINE OF mt_callstack. READ TABLE mt_callstack ASSIGNING INDEX 1. IF sy-subrc = 0. program_name = -mainprogram. include_name = -include. source_line = -line. ELSE. super->get_source_position( IMPORTING program_name = program_name include_name = include_name source_line = source_line ). ENDIF. ENDMETHOD. METHOD get_t100_longtext_itf. DATA: lv_docu_key TYPE doku_obj. FIELD-SYMBOLS TYPE any. lv_docu_key = if_t100_message~t100key-msgid && if_t100_message~t100key-msgno. CALL FUNCTION 'DOCU_GET' EXPORTING id = 'NA' langu = sy-langu object = lv_docu_key typ = 'E' TABLES line = rt_itf EXCEPTIONS OTHERS = 1. IF sy-subrc = 0. ASSIGN me->(if_t100_message~t100key-attr1) TO . IF sy-subrc = 0. REPLACE ALL OCCURRENCES OF '&V1&' IN TABLE rt_itf WITH . ENDIF. ASSIGN me->(if_t100_message~t100key-attr2) TO . IF sy-subrc = 0. REPLACE ALL OCCURRENCES OF '&V2&' IN TABLE rt_itf WITH . ENDIF. ASSIGN me->(if_t100_message~t100key-attr3) TO . IF sy-subrc = 0. REPLACE ALL OCCURRENCES OF '&V3&' IN TABLE rt_itf WITH . ENDIF. ASSIGN me->(if_t100_message~t100key-attr4) TO . IF sy-subrc = 0. REPLACE ALL OCCURRENCES OF '&V4&' IN TABLE rt_itf WITH . ENDIF. ENDIF. ENDMETHOD. METHOD if_message~get_longtext. DATA: lv_preserve_newlines_handled TYPE abap_bool VALUE abap_false. IF mv_longtext IS NOT INITIAL. result = mv_longtext. ELSEIF if_t100_message~t100key IS NOT INITIAL. result = itf_to_string( get_t100_longtext_itf( ) ). ELSE. result = super->get_longtext( preserve_newlines ). lv_preserve_newlines_handled = abap_true. ENDIF. IF lv_preserve_newlines_handled = abap_false AND preserve_newlines = abap_false. result = remove_newlines_from_string( result ). ENDIF. ENDMETHOD. METHOD itf_to_string. CONSTANTS: lc_format_section TYPE string VALUE 'U1'. DATA: lt_stream TYPE TABLE OF tdline, lt_string TYPE TABLE OF string, lv_string LIKE LINE OF lt_string, lt_itf TYPE tline_tab, lv_has_content TYPE abap_bool, lv_tabix_from TYPE syst-tabix, lv_tabix_to TYPE syst-tabix. FIELD-SYMBOLS: TYPE tline, TYPE tline. lt_itf = it_itf. " You should remember that we replace the U1 format because " that preserves the section header of longtexts. LOOP AT lt_itf ASSIGNING WHERE tdformat = lc_format_section. CLEAR: lv_has_content, lv_tabix_to. lv_tabix_from = sy-tabix. LOOP AT lt_itf ASSIGNING FROM sy-tabix + 1. IF -tdformat = lc_format_section. lv_tabix_to = sy-tabix. EXIT. ELSEIF -tdline IS NOT INITIAL. lv_has_content = abap_true. ENDIF. ENDLOOP. IF lv_has_content = abap_false. remove_empty_section( EXPORTING iv_tabix_from = lv_tabix_from iv_tabix_to = lv_tabix_to CHANGING ct_itf = lt_itf ). CONTINUE. ENDIF. replace_section_head_with_text( CHANGING cs_itf = ). ENDLOOP. CALL FUNCTION 'CONVERT_ITF_TO_STREAM_TEXT' EXPORTING lf = 'X' IMPORTING stream_lines = lt_string TABLES itf_text = lt_itf text_stream = lt_stream. LOOP AT lt_string INTO lv_string. IF sy-tabix = 1. rv_result = lv_string. ELSE. CONCATENATE rv_result lv_string INTO rv_result SEPARATED BY cl_abap_char_utilities=>newline. ENDIF. ENDLOOP. ENDMETHOD. METHOD raise. DATA lv_text TYPE string. IF iv_text IS INITIAL. lv_text = c_generic_error_msg. ELSE. lv_text = iv_text. ENDIF. split_text_to_symsg( lv_text ). raise_t100( ii_log = ii_log ix_previous = ix_previous iv_longtext = iv_longtext ). ENDMETHOD. METHOD raise_t100. DATA: ls_t100_key TYPE scx_t100key. ls_t100_key-msgid = iv_msgid. ls_t100_key-msgno = iv_msgno. ls_t100_key-attr1 = 'MSGV1'. ls_t100_key-attr2 = 'MSGV2'. ls_t100_key-attr3 = 'MSGV3'. ls_t100_key-attr4 = 'MSGV4'. IF iv_msgid IS INITIAL. CLEAR ls_t100_key. ENDIF. RAISE EXCEPTION TYPE zcx_abapgit_exception EXPORTING textid = ls_t100_key log = ii_log msgv1 = iv_msgv1 msgv2 = iv_msgv2 msgv3 = iv_msgv3 msgv4 = iv_msgv4 previous = ix_previous longtext = iv_longtext. ENDMETHOD. METHOD raise_with_text. raise( iv_text = ix_previous->get_text( ) ix_previous = ix_previous iv_longtext = iv_longtext ). ENDMETHOD. METHOD remove_empty_section. IF iv_tabix_to BETWEEN iv_tabix_from AND lines( ct_itf ). DELETE ct_itf FROM iv_tabix_from TO iv_tabix_to. ELSE. DELETE ct_itf FROM iv_tabix_from. ENDIF. ENDMETHOD. METHOD remove_newlines_from_string. rv_result = iv_string. REPLACE ALL OCCURRENCES OF ` ` && cl_abap_char_utilities=>cr_lf IN rv_result WITH ` `. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN rv_result WITH ` `. REPLACE ALL OCCURRENCES OF ` ` && cl_abap_char_utilities=>newline IN rv_result WITH ` `. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN rv_result WITH ` `. ENDMETHOD. METHOD replace_section_head_with_text. CASE cs_itf-tdline. WHEN c_section_token-cause. cs_itf-tdline = c_section_text-cause. WHEN c_section_token-system_response. cs_itf-tdline = c_section_text-system_response. WHEN c_section_token-what_to_do. cs_itf-tdline = c_section_text-what_to_do. WHEN c_section_token-sys_admin. cs_itf-tdline = c_section_text-sys_admin. ENDCASE. ENDMETHOD. METHOD save_callstack. FIELD-SYMBOLS: LIKE LINE OF mt_callstack. CALL FUNCTION 'SYSTEM_CALLSTACK' IMPORTING callstack = mt_callstack. " You should remember that the first lines are from zcx_abapgit_exception " and are removed so that highest level in the callstack is the position where " the exception is raised. " " For the merged report it's hard to do that, because zcx_abapgit_exception " isn't visible in the callstack. Therefore we have to check the Events. LOOP AT mt_callstack ASSIGNING . IF -mainprogram CP |ZCX_ABAPGIT_EXCEPTION*| " full OR -blockname = `SAVE_CALLSTACK` " merged OR -blockname = `CONSTRUCTOR` " merged OR -blockname CP `RAISE*`. "merged DELETE TABLE mt_callstack FROM . ELSE. EXIT. ENDIF. ENDLOOP. ENDMETHOD. METHOD split_text_to_symsg. DATA ls_msg TYPE symsg. cl_message_helper=>set_msg_vars_for_clike( iv_text ). ls_msg-msgv1 = sy-msgv1. ls_msg-msgv2 = sy-msgv2. ls_msg-msgv3 = sy-msgv3. ls_msg-msgv4 = sy-msgv4. " Set syst using generic error message MESSAGE e001(00) WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO null. rs_msg = ls_msg. ENDMETHOD. ENDCLASS. CLASS zcx_abapgit_cancel DEFINITION INHERITING FROM zcx_abapgit_exception FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS constructor IMPORTING !textid LIKE if_t100_message=>t100key OPTIONAL !previous LIKE previous OPTIONAL !log TYPE REF TO zif_abapgit_log OPTIONAL !msgv1 TYPE symsgv OPTIONAL !msgv2 TYPE symsgv OPTIONAL !msgv3 TYPE symsgv OPTIONAL !msgv4 TYPE symsgv OPTIONAL !longtext TYPE csequence OPTIONAL. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcx_abapgit_cancel IMPLEMENTATION. METHOD constructor ##ADT_SUPPRESS_GENERATION. super->constructor( previous = previous log = log msgv1 = msgv1 msgv2 = msgv2 msgv3 = msgv3 msgv4 = msgv4 longtext = longtext ). CLEAR me->textid. IF textid IS INITIAL. if_t100_message~t100key = if_t100_message=>default_textid. ELSE. if_t100_message~t100key = textid. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcx_abapgit_not_found DEFINITION INHERITING FROM cx_static_check FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS constructor IMPORTING !textid LIKE textid OPTIONAL !previous LIKE previous OPTIONAL. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcx_abapgit_not_found IMPLEMENTATION. METHOD constructor ##ADT_SUPPRESS_GENERATION. super->constructor( textid = textid previous = previous ). ENDMETHOD. ENDCLASS. INTERFACE zif_abapgit_background . TYPES: BEGIN OF ty_settings, key TYPE string, value TYPE string, END OF ty_settings . TYPES: ty_settings_tt TYPE STANDARD TABLE OF ty_settings WITH DEFAULT KEY . CLASS-METHODS get_description RETURNING VALUE(rv_description) TYPE string . CLASS-METHODS get_settings CHANGING ct_settings TYPE ty_settings_tt . METHODS run IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online !ii_log TYPE REF TO zif_abapgit_log !it_settings TYPE ty_settings_tt OPTIONAL RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_default_transport. TYPES: BEGIN OF ty_get, trfunction TYPE c LENGTH 1, ordernum TYPE trkorr, END OF ty_get. METHODS set IMPORTING iv_transport TYPE trkorr RAISING zcx_abapgit_exception. METHODS reset RAISING zcx_abapgit_exception. METHODS get RETURNING VALUE(rs_default_task) TYPE ty_get RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_environment. TYPES: BEGIN OF ty_release_sp, release TYPE c LENGTH 10, sp TYPE c LENGTH 10, END OF ty_release_sp, ty_system_language_filter TYPE RANGE OF spras. METHODS is_sap_cloud_platform RETURNING VALUE(rv_result) TYPE abap_bool. METHODS is_merged RETURNING VALUE(rv_result) TYPE abap_bool. METHODS is_repo_object_changes_allowed RETURNING VALUE(rv_result) TYPE abap_bool. METHODS compare_with_inactive RETURNING VALUE(rv_result) TYPE abap_bool. METHODS is_restart_required RETURNING VALUE(rv_result) TYPE abap_bool. METHODS is_sap_object_allowed RETURNING VALUE(rv_allowed) TYPE abap_bool. METHODS get_basis_release RETURNING VALUE(rs_result) TYPE ty_release_sp. METHODS get_system_language_filter RETURNING VALUE(rt_system_language_filter) TYPE ty_system_language_filter. METHODS is_variant_maintenance RETURNING VALUE(rv_is_variant_maintenance) TYPE abap_bool. METHODS init_parallel_processing IMPORTING iv_group TYPE clike RETURNING VALUE(rv_free_work_processes) TYPE i. ENDINTERFACE. INTERFACE zif_abapgit_auth. TYPES: ty_authorization TYPE string. CONSTANTS: BEGIN OF c_authorization, startup TYPE ty_authorization VALUE 'STARTUP', uninstall TYPE ty_authorization VALUE 'UNINSTALL', create_repo TYPE ty_authorization VALUE 'CREATE_REPO', transport_to_branch TYPE ty_authorization VALUE 'TRANSPORT_TO_BRANCH', update_local_checksum TYPE ty_authorization VALUE 'UPDATE_LOCAL_CHECKSUM', END OF c_authorization. METHODS: is_allowed IMPORTING iv_authorization TYPE ty_authorization iv_param TYPE string OPTIONAL RETURNING VALUE(rv_allowed) TYPE abap_bool. ENDINTERFACE. INTERFACE zif_abapgit_git_definitions . * this interface is self contained * only references to built in types * git does not know the concept of TADIR objects, only knows files TYPES: ty_type TYPE c LENGTH 6 . TYPES: ty_bitbyte TYPE c LENGTH 8 . TYPES: ty_sha1 TYPE c LENGTH 40 . TYPES: ty_sha1_tt TYPE STANDARD TABLE OF ty_sha1 WITH DEFAULT KEY . TYPES: ty_adler32 TYPE x LENGTH 4 . TYPES ty_item_state TYPE c LENGTH 1. TYPES: BEGIN OF ty_file_signature, path TYPE string, filename TYPE string, sha1 TYPE ty_sha1, END OF ty_file_signature . TYPES: ty_file_signatures_tt TYPE STANDARD TABLE OF ty_file_signature WITH DEFAULT KEY . TYPES: ty_file_signatures_ts TYPE SORTED TABLE OF ty_file_signature WITH UNIQUE KEY path filename . TYPES: BEGIN OF ty_file. INCLUDE TYPE ty_file_signature. TYPES: data TYPE xstring, END OF ty_file . TYPES: ty_files_tt TYPE STANDARD TABLE OF ty_file WITH DEFAULT KEY WITH UNIQUE SORTED KEY file_path COMPONENTS path filename WITH NON-UNIQUE SORTED KEY file COMPONENTS filename. TYPES ty_git_branch_type TYPE c LENGTH 2 . TYPES: BEGIN OF ty_git_branch, sha1 TYPE ty_sha1, name TYPE string, type TYPE ty_git_branch_type, is_head TYPE abap_bool, display_name TYPE string, END OF ty_git_branch . TYPES: ty_git_branch_list_tt TYPE STANDARD TABLE OF ty_git_branch WITH DEFAULT KEY WITH NON-UNIQUE SORTED KEY name_key COMPONENTS name. TYPES: BEGIN OF ty_git_tag, sha1 TYPE ty_sha1, object TYPE ty_sha1, name TYPE string, type TYPE ty_git_branch_type, display_name TYPE string, tagger_name TYPE string, tagger_email TYPE string, message TYPE string, body TYPE string, END OF ty_git_tag . TYPES: BEGIN OF ty_git_user, name TYPE string, email TYPE string, END OF ty_git_user . TYPES: BEGIN OF ty_comment, committer TYPE ty_git_user, author TYPE ty_git_user, comment TYPE string, END OF ty_comment . TYPES: ty_chmod TYPE c LENGTH 6 . CONSTANTS: BEGIN OF c_chmod, file TYPE ty_chmod VALUE '100644', executable TYPE ty_chmod VALUE '100755', dir TYPE ty_chmod VALUE '40000 ', submodule TYPE ty_chmod VALUE '160000', END OF c_chmod . TYPES: BEGIN OF ty_expanded, path TYPE string, name TYPE string, sha1 TYPE ty_sha1, chmod TYPE ty_chmod, END OF ty_expanded . TYPES: ty_expanded_tt TYPE STANDARD TABLE OF ty_expanded WITH DEFAULT KEY WITH NON-UNIQUE SORTED KEY path_name COMPONENTS path name. TYPES: BEGIN OF ty_create, name TYPE string, parent TYPE string, END OF ty_create . TYPES: BEGIN OF ty_commit, sha1 TYPE ty_sha1, parent1 TYPE ty_sha1, parent2 TYPE ty_sha1, author TYPE string, email TYPE string, time TYPE string, message TYPE string, body TYPE STANDARD TABLE OF string WITH DEFAULT KEY, branch TYPE string, merge TYPE string, tags TYPE STANDARD TABLE OF string WITH DEFAULT KEY, create TYPE STANDARD TABLE OF ty_create WITH DEFAULT KEY, compressed TYPE abap_bool, END OF ty_commit . TYPES: ty_commit_tt TYPE STANDARD TABLE OF ty_commit WITH DEFAULT KEY . CONSTANTS: BEGIN OF c_type, commit TYPE ty_type VALUE 'commit', "#EC NOTEXT tree TYPE ty_type VALUE 'tree', "#EC NOTEXT ref_d TYPE ty_type VALUE 'ref_d', "#EC NOTEXT tag TYPE ty_type VALUE 'tag', "#EC NOTEXT blob TYPE ty_type VALUE 'blob', "#EC NOTEXT END OF c_type . CONSTANTS: BEGIN OF c_git_branch_type, branch TYPE ty_git_branch_type VALUE 'HD', lightweight_tag TYPE ty_git_branch_type VALUE 'TG', annotated_tag TYPE ty_git_branch_type VALUE 'AT', other TYPE ty_git_branch_type VALUE 'ZZ', END OF c_git_branch_type . CONSTANTS c_head_name TYPE string VALUE 'HEAD' ##NO_TEXT. CONSTANTS: BEGIN OF c_git_branch, main TYPE string VALUE 'refs/heads/main', prefix TYPE string VALUE 'refs/', heads_prefix TYPE string VALUE 'refs/heads/', heads TYPE string VALUE 'refs/heads/*', tags_prefix TYPE string VALUE 'refs/tags/', tags TYPE string VALUE 'refs/tags/*', peel TYPE string VALUE '^{}', END OF c_git_branch. ENDINTERFACE. INTERFACE zif_abapgit_data_config . TYPES: ty_data_type TYPE c LENGTH 4 . TYPES: BEGIN OF ty_config, type TYPE ty_data_type, name TYPE tadir-obj_name, skip_initial TYPE abap_bool, where TYPE string_table, END OF ty_config . TYPES: ty_config_tt TYPE SORTED TABLE OF ty_config WITH UNIQUE KEY type name . CONSTANTS c_default_path TYPE string VALUE '/data/' ##NO_TEXT. CONSTANTS c_default_format TYPE string VALUE 'json' ##NO_TEXT. CONSTANTS c_config TYPE string VALUE 'conf' ##NO_TEXT. CONSTANTS: BEGIN OF c_data_type, tabu TYPE ty_data_type VALUE 'TABU', vdat TYPE ty_data_type VALUE 'VDAT', cdat TYPE ty_data_type VALUE 'CDAT', tdat TYPE ty_data_type VALUE 'TDAT', END OF c_data_type . METHODS add_config IMPORTING !is_config TYPE ty_config RAISING zcx_abapgit_exception . METHODS from_json IMPORTING !it_files TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . METHODS get_configs RETURNING VALUE(rt_configs) TYPE ty_config_tt . METHODS remove_config IMPORTING !is_config TYPE ty_config RAISING zcx_abapgit_exception . METHODS to_json RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . METHODS update_config IMPORTING !is_config TYPE ty_config RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_data_serializer . METHODS serialize IMPORTING !ii_config TYPE REF TO zif_abapgit_data_config RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_data_supporter. TYPES: BEGIN OF ty_object, type TYPE zif_abapgit_data_config=>ty_config-type, name TYPE zif_abapgit_data_config=>ty_config-name, END OF ty_object. TYPES: ty_objects TYPE SORTED TABLE OF ty_object WITH UNIQUE KEY type name. METHODS is_object_supported IMPORTING !iv_type TYPE ty_object-type !iv_name TYPE ty_object-name RETURNING VALUE(rv_supported) TYPE abap_bool. ENDINTERFACE. INTERFACE zif_abapgit_git_transport . METHODS branches IMPORTING iv_url TYPE string RETURNING VALUE(ro_branch_list) TYPE REF TO zcl_abapgit_git_branch_list RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_pr_enum_provider . TYPES: BEGIN OF ty_pull_request, base_url TYPE string, number TYPE string, title TYPE string, user TYPE string, head_url TYPE string, head_branch TYPE string, created_at TYPE string, " TODO change to D after date parsing fixed is_for_upstream TYPE abap_bool, draft TYPE abap_bool, html_url TYPE string, END OF ty_pull_request. TYPES: ty_pull_requests TYPE STANDARD TABLE OF ty_pull_request WITH KEY base_url number. METHODS list_pull_requests RETURNING VALUE(rt_pulls) TYPE ty_pull_requests RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_http_agent . CONSTANTS: BEGIN OF c_methods, get TYPE string VALUE 'GET', post TYPE string VALUE 'POST', put TYPE string VALUE 'PUT', delete TYPE string VALUE 'DELETE', patch TYPE string VALUE 'PATCH', END OF c_methods. METHODS global_headers RETURNING VALUE(ro_global_headers) TYPE REF TO zcl_abapgit_string_map. METHODS request IMPORTING !iv_url TYPE string !iv_method TYPE string DEFAULT c_methods-get !io_query TYPE REF TO zcl_abapgit_string_map OPTIONAL !io_headers TYPE REF TO zcl_abapgit_string_map OPTIONAL !iv_payload TYPE any OPTIONAL " can be string, xstring RETURNING VALUE(ri_response) TYPE REF TO zif_abapgit_http_response RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_http_response . METHODS data RETURNING VALUE(rv_data) TYPE xstring . METHODS cdata RETURNING VALUE(rv_data) TYPE string . METHODS json RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error . METHODS is_ok RETURNING VALUE(rv_yes) TYPE abap_bool . METHODS code RETURNING VALUE(rv_code) TYPE i . METHODS error RETURNING VALUE(rv_message) TYPE string . METHODS headers RETURNING VALUE(ro_headers) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS close . ENDINTERFACE. INTERFACE zif_abapgit_code_inspector . TYPES: BEGIN OF ty_result, objtype TYPE tadir-object, objname TYPE tadir-obj_name, sobjtype TYPE c LENGTH 4, sobjname TYPE c LENGTH 40, kind TYPE c LENGTH 1, line TYPE n LENGTH 6, col TYPE n LENGTH 4, code TYPE c LENGTH 10, test TYPE c LENGTH 30, text TYPE string, param1 TYPE c LENGTH 80, END OF ty_result. TYPES ty_results TYPE STANDARD TABLE OF ty_result WITH DEFAULT KEY. TYPES: BEGIN OF ty_variant, name TYPE sci_chkv, description TYPE string, END OF ty_variant. TYPES ty_variants TYPE STANDARD TABLE OF ty_variant WITH DEFAULT KEY. METHODS run IMPORTING !iv_variant TYPE sci_chkv !iv_save TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rt_list) TYPE ty_results RAISING zcx_abapgit_exception . METHODS is_successful RETURNING VALUE(rv_success) TYPE abap_bool . METHODS get_summary RETURNING VALUE(rv_summary) TYPE string. METHODS validate_check_variant IMPORTING !iv_check_variant_name TYPE sci_chkv RAISING zcx_abapgit_exception. METHODS list_global_variants RETURNING VALUE(rt_list) TYPE ty_variants. ENDINTERFACE. INTERFACE zif_abapgit_ajson_types. TYPES: ty_node_type TYPE string. CONSTANTS: BEGIN OF node_type, boolean TYPE ty_node_type VALUE 'bool', string TYPE ty_node_type VALUE 'str', number TYPE ty_node_type VALUE 'num', null TYPE ty_node_type VALUE 'null', array TYPE ty_node_type VALUE 'array', object TYPE ty_node_type VALUE 'object', END OF node_type. TYPES: BEGIN OF ty_node, path TYPE string, name TYPE string, type TYPE ty_node_type, value TYPE string, index TYPE i, order TYPE i, children TYPE i, END OF ty_node. TYPES: ty_nodes_tt TYPE STANDARD TABLE OF ty_node WITH KEY path name. TYPES: ty_nodes_ts TYPE SORTED TABLE OF ty_node WITH UNIQUE KEY path name WITH NON-UNIQUE SORTED KEY array_index COMPONENTS path index WITH NON-UNIQUE SORTED KEY item_order COMPONENTS path order. TYPES: BEGIN OF ty_path_name, path TYPE string, name TYPE string, END OF ty_path_name. ENDINTERFACE. INTERFACE zif_abapgit_ajson. CONSTANTS version TYPE string VALUE 'v1.1.10'. "#EC NOTEXT CONSTANTS origin TYPE string VALUE 'https://github.com/sbcgua/ajson'. "#EC NOTEXT CONSTANTS license TYPE string VALUE 'MIT'. "#EC NOTEXT TYPES: BEGIN OF ty_opts, read_only TYPE abap_bool, keep_item_order TYPE abap_bool, format_datetime TYPE abap_bool, to_abap_corresponding_only TYPE abap_bool, END OF ty_opts. " DATA DATA mt_json_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts READ-ONLY. " CLONING METHODS clone RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS filter IMPORTING ii_filter TYPE REF TO zif_abapgit_ajson_filter RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS map IMPORTING ii_mapper TYPE REF TO zif_abapgit_ajson_mapping RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. " METHODS METHODS freeze. METHODS keep_item_order RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. METHODS format_datetime IMPORTING iv_use_iso TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. METHODS to_abap_corresponding_only IMPORTING iv_enable TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. METHODS opts RETURNING VALUE(rs_opts) TYPE ty_opts. " METHODS ex.reader METHODS is_empty RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS exists IMPORTING iv_path TYPE string RETURNING VALUE(rv_exists) TYPE abap_bool. METHODS members IMPORTING iv_path TYPE string RETURNING VALUE(rt_members) TYPE string_table. METHODS get IMPORTING iv_path TYPE string RETURNING VALUE(rv_value) TYPE string. METHODS get_node_type IMPORTING iv_path TYPE string RETURNING VALUE(rv_node_type) TYPE zif_abapgit_ajson_types=>ty_node_type. METHODS get_boolean IMPORTING iv_path TYPE string RETURNING VALUE(rv_value) TYPE abap_bool. METHODS get_integer IMPORTING iv_path TYPE string RETURNING VALUE(rv_value) TYPE i. METHODS get_number IMPORTING iv_path TYPE string RETURNING VALUE(rv_value) TYPE f. METHODS get_date IMPORTING iv_path TYPE string RETURNING VALUE(rv_value) TYPE d. METHODS get_timestamp IMPORTING iv_path TYPE string RETURNING VALUE(rv_value) TYPE timestamp. METHODS get_string IMPORTING iv_path TYPE string RETURNING VALUE(rv_value) TYPE string. METHODS slice IMPORTING iv_path TYPE string RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. METHODS to_abap IMPORTING iv_corresponding TYPE abap_bool DEFAULT abap_false EXPORTING ev_container TYPE any RAISING zcx_abapgit_ajson_error. METHODS array_to_string_table IMPORTING iv_path TYPE string RETURNING VALUE(rt_string_table) TYPE string_table RAISING zcx_abapgit_ajson_error. " METHODS ex.writer METHODS clear RAISING zcx_abapgit_ajson_error. METHODS set IMPORTING iv_path TYPE string iv_val TYPE any iv_ignore_empty TYPE abap_bool DEFAULT abap_true iv_node_type TYPE zif_abapgit_ajson_types=>ty_node_type OPTIONAL RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS setx IMPORTING iv_param TYPE string RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS set_boolean IMPORTING iv_path TYPE string iv_val TYPE any RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS set_string IMPORTING iv_path TYPE string iv_val TYPE clike RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS set_integer IMPORTING iv_path TYPE string iv_val TYPE i RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS set_date IMPORTING iv_path TYPE string iv_val TYPE d RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS set_timestamp IMPORTING iv_path TYPE string iv_val TYPE timestamp RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS set_null IMPORTING iv_path TYPE string RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS delete IMPORTING iv_path TYPE string RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS touch_array IMPORTING iv_path TYPE string iv_clear TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS push IMPORTING iv_path TYPE string iv_val TYPE any RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. METHODS stringify IMPORTING iv_indent TYPE i DEFAULT 0 RETURNING VALUE(rv_json) TYPE string RAISING zcx_abapgit_ajson_error. ENDINTERFACE. INTERFACE zif_abapgit_ajson_filter. TYPES ty_filter_tab TYPE STANDARD TABLE OF REF TO zif_abapgit_ajson_filter WITH KEY table_line. TYPES ty_visit_type TYPE i. CONSTANTS: BEGIN OF visit_type, value TYPE ty_visit_type VALUE 0, open TYPE ty_visit_type VALUE 1, close TYPE ty_visit_type VALUE 2, END OF visit_type. METHODS keep_node IMPORTING is_node TYPE zif_abapgit_ajson_types=>ty_node iv_visit TYPE ty_visit_type DEFAULT visit_type-value RETURNING VALUE(rv_keep) TYPE abap_bool RAISING zcx_abapgit_ajson_error. ENDINTERFACE. INTERFACE zif_abapgit_ajson_mapping. TYPES: BEGIN OF ty_mapping_field, " deprecated, will be removed abap TYPE string, json TYPE string, END OF ty_mapping_field, ty_mapping_fields TYPE STANDARD TABLE OF ty_mapping_field WITH UNIQUE SORTED KEY abap COMPONENTS abap WITH UNIQUE SORTED KEY json COMPONENTS json. TYPES: BEGIN OF ty_rename, from TYPE string, to TYPE string, END OF ty_rename, tty_rename_map TYPE STANDARD TABLE OF ty_rename WITH UNIQUE SORTED KEY by_name COMPONENTS from. TYPES: ty_table_of TYPE STANDARD TABLE OF REF TO zif_abapgit_ajson_mapping. METHODS to_abap " deprecated, will be removed IMPORTING !iv_path TYPE string !iv_name TYPE string RETURNING VALUE(rv_result) TYPE string. METHODS to_json " deprecated, will be removed IMPORTING !iv_path TYPE string !iv_name TYPE string RETURNING VALUE(rv_result) TYPE string. METHODS rename_node IMPORTING !is_node TYPE zif_abapgit_ajson_types=>ty_node CHANGING !cv_name TYPE zif_abapgit_ajson_types=>ty_node-name. ENDINTERFACE. INTERFACE zif_abapgit_aff_registry . METHODS: "! Returns TRUE if the object type is supported by ABAP file formats (AFF) in abapGit.
"! Either there is a (standalone AFF capable) object handler, "! or object handler calls the AFF framework in newer ABAP systems. is_supported_object_type IMPORTING iv_obj_type TYPE tadir-object RETURNING VALUE(rv_result) TYPE abap_bool. ENDINTERFACE. INTERFACE zif_abapgit_aff_type_mapping . METHODS: "! Convert from AFF to abapGit data "! "! @parameter iv_data | ABAP data as AFF type "! @parameter iv_object_name | Name of object "! @parameter es_data | ABAP data as abapGit type to_abapgit IMPORTING iv_data TYPE data iv_object_name TYPE sobj_name EXPORTING es_data TYPE data, "! Converts to AFF specific meta data "! "! @parameter iv_data | (meta-)data of the object "! @parameter es_data | aff data of the object, e.g. zif_abapgit_aff_intf_v1=>ty_main to_aff IMPORTING iv_data TYPE data EXPORTING es_data TYPE data. ENDINTERFACE. INTERFACE zif_abapgit_aff_types_v1. TYPES ty_format_version TYPE string. TYPES ty_abap_language_version TYPE c LENGTH 1. TYPES ty_abap_language_version_cloud TYPE c LENGTH 1. TYPES ty_abap_language_version_src TYPE c LENGTH 1. CONSTANTS: BEGIN OF co_abap_language_version_src, standard TYPE ty_abap_language_version_src VALUE 'X', key_user TYPE ty_abap_language_version_src VALUE '2', cloud_development TYPE ty_abap_language_version_src VALUE '5', END OF co_abap_language_version_src. CONSTANTS: BEGIN OF co_abap_language_version, standard TYPE ty_abap_language_version VALUE space, key_user TYPE ty_abap_language_version VALUE '2', cloud_development TYPE ty_abap_language_version VALUE '5', END OF co_abap_language_version. CONSTANTS: BEGIN OF co_abap_language_version_cloud, standard TYPE ty_abap_language_version_cloud VALUE space, cloud_development TYPE ty_abap_language_version_cloud VALUE '5', END OF co_abap_language_version_cloud. TYPES ty_description_60 TYPE c LENGTH 60. TYPES ty_description_100 TYPE c LENGTH 100. TYPES ty_object_name_30 TYPE c LENGTH 30. TYPES ty_original_language TYPE sy-langu. TYPES: BEGIN OF ty_header_60_src, description TYPE ty_description_60, original_language TYPE ty_original_language, abap_language_version TYPE ty_abap_language_version_src, END OF ty_header_60_src. TYPES: BEGIN OF ty_header_60_cloud, description TYPE ty_description_60, original_language TYPE ty_original_language, abap_language_version TYPE ty_abap_language_version_cloud, END OF ty_header_60_cloud. TYPES: BEGIN OF ty_header_60, description TYPE ty_description_60, original_language TYPE ty_original_language, abap_language_version TYPE ty_abap_language_version, END OF ty_header_60. TYPES: BEGIN OF ty_header_60_no_abap_lv, description TYPE ty_description_60, original_language TYPE ty_original_language, END OF ty_header_60_no_abap_lv. TYPES: BEGIN OF ty_header_100, description TYPE ty_description_100, original_language TYPE ty_original_language, abap_language_version TYPE ty_abap_language_version, END OF ty_header_100. TYPES: BEGIN OF ty_header_only_description, description TYPE ty_description_60, END OF ty_header_only_description. TYPES ty_option TYPE c LENGTH 2. CONSTANTS: BEGIN OF co_option, equals TYPE ty_option VALUE 'EQ', between TYPE ty_option VALUE 'BT', greater_than TYPE ty_option VALUE 'GT', contains_pattern TYPE ty_option VALUE 'CP', not_equal TYPE ty_option VALUE 'NE', not_between TYPE ty_option VALUE 'NB', not_contains_pattern TYPE ty_option VALUE 'NP', greater_equal TYPE ty_option VALUE 'GE', less_than TYPE ty_option VALUE 'LT', less_equal TYPE ty_option VALUE 'LE', END OF co_option. TYPES ty_sign TYPE c LENGTH 1. CONSTANTS: BEGIN OF co_sign, include TYPE ty_sign VALUE 'I', exclude TYPE ty_sign VALUE 'E', END OF co_sign. ENDINTERFACE. INTERFACE zif_abapgit_aff_oo_types_v1. TYPES: BEGIN OF ty_component_description, name TYPE zif_abapgit_aff_types_v1=>ty_object_name_30, description TYPE zif_abapgit_aff_types_v1=>ty_description_60, END OF ty_component_description, ty_component_descriptions TYPE SORTED TABLE OF ty_component_description WITH UNIQUE KEY name. TYPES: BEGIN OF ty_method, name TYPE zif_abapgit_aff_types_v1=>ty_object_name_30, description TYPE zif_abapgit_aff_types_v1=>ty_description_60, parameters TYPE ty_component_descriptions, exceptions TYPE ty_component_descriptions, END OF ty_method, ty_methods TYPE SORTED TABLE OF ty_method WITH UNIQUE KEY name. TYPES: BEGIN OF ty_event, name TYPE zif_abapgit_aff_types_v1=>ty_object_name_30, description TYPE zif_abapgit_aff_types_v1=>ty_description_60, parameters TYPE ty_component_descriptions, END OF ty_event, ty_events TYPE SORTED TABLE OF ty_event WITH UNIQUE KEY name. TYPES: BEGIN OF ty_descriptions, types TYPE ty_component_descriptions, attributes TYPE ty_component_descriptions, events TYPE ty_events, methods TYPE ty_methods, END OF ty_descriptions. ENDINTERFACE. INTERFACE zif_abapgit_aff_intf_v1. TYPES ty_category TYPE n LENGTH 2. CONSTANTS: BEGIN OF co_category, general TYPE ty_category VALUE '00', classic_badi TYPE ty_category VALUE '01', business_static_components TYPE ty_category VALUE '51', business_instance_components TYPE ty_category VALUE '52', db_procedure_proxy TYPE ty_category VALUE '65', web_dynpro_runtime TYPE ty_category VALUE '80', enterprise_service TYPE ty_category VALUE '90', END OF co_category. TYPES: BEGIN OF ty_main, format_version TYPE zif_abapgit_aff_types_v1=>ty_format_version, header TYPE zif_abapgit_aff_types_v1=>ty_header_60_src, category TYPE ty_category, proxy TYPE abap_bool, descriptions TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions, END OF ty_main. ENDINTERFACE. INTERFACE zif_abapgit_ecatt . " downport missing types TYPES: ty_invert_validation TYPE c LENGTH 1, ty_error_prio TYPE n LENGTH 1, ty_impl_name TYPE c LENGTH 30, ty_impl_type TYPE c LENGTH 1, ty_impl_subtype TYPE c LENGTH 4, ty_package TYPE c LENGTH 255, BEGIN OF ty_impl_det, impl_name TYPE ty_impl_name, impl_type TYPE ty_impl_type, impl_subtype TYPE ty_impl_subtype, impl_package TYPE ty_package, END OF ty_impl_det. TYPES: BEGIN OF ty_bus_msg. INCLUDE TYPE etobj_key. TYPES: bus_msg_no TYPE c LENGTH 1, " ty_msg_no arbgb TYPE arbgb, msgnr TYPE msgnr, bus_msg_text TYPE string, "ty_bus_msg_text otr_key TYPE sotr_conc, msg_type TYPE c LENGTH 4, "ty_msg_type END OF ty_bus_msg, ty_bus_msgs TYPE STANDARD TABLE OF ty_bus_msg. ENDINTERFACE. INTERFACE zif_abapgit_ecatt_download . METHODS: get_xml_stream RETURNING VALUE(rv_xml_stream) TYPE xstring. ENDINTERFACE. INTERFACE zif_abapgit_ecatt_upload . METHODS: set_stream_for_upload IMPORTING iv_xml TYPE xstring. ENDINTERFACE. INTERFACE zif_abapgit_object_enho. METHODS: deserialize IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input iv_package TYPE devclass RAISING zcx_abapgit_exception, serialize IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_output ii_enh_tool TYPE REF TO if_enh_tool RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_object_enhs. METHODS: deserialize IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input iv_package TYPE devclass ii_enh_spot_tool TYPE REF TO if_enh_spot_tool RAISING zcx_abapgit_exception, serialize IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_output ii_enh_spot_tool TYPE REF TO if_enh_spot_tool RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_field_rules . TYPES ty_fill_rule TYPE c LENGTH 2. CONSTANTS: BEGIN OF c_fill_rule, date TYPE ty_fill_rule VALUE 'DT', time TYPE ty_fill_rule VALUE 'TM', timestamp TYPE ty_fill_rule VALUE 'TS', user TYPE ty_fill_rule VALUE 'UR', client TYPE ty_fill_rule VALUE 'CT', package TYPE ty_fill_rule VALUE 'PK', END OF c_fill_rule. METHODS add IMPORTING iv_table TYPE tabname iv_field TYPE fieldname iv_fill_rule TYPE ty_fill_rule RETURNING VALUE(ro_self) TYPE REF TO zif_abapgit_field_rules. METHODS apply_clear_logic IMPORTING iv_table TYPE tabname CHANGING ct_data TYPE STANDARD TABLE. METHODS apply_fill_logic IMPORTING iv_table TYPE tabname iv_package TYPE devclass CHANGING ct_data TYPE STANDARD TABLE. ENDINTERFACE. INTERFACE zif_abapgit_function_module. METHODS: function_exists IMPORTING iv_function_module_name TYPE clike RETURNING VALUE(rv_exists) TYPE abap_bool. ENDINTERFACE. INTERFACE zif_abapgit_lxe_texts . * type LXE_PCX_S1 inlined to be compatible with open-abap and ABAP Cloud TYPES: BEGIN OF ty_text_pair, textkey TYPE c LENGTH 32, s_text TYPE c LENGTH 255, t_text TYPE c LENGTH 255, unitmlt TYPE i, uppcase TYPE c LENGTH 4, texttype TYPE c LENGTH 1, END OF ty_text_pair. TYPES ty_text_pairs TYPE STANDARD TABLE OF ty_text_pair WITH DEFAULT KEY. METHODS serialize IMPORTING !iv_object_type TYPE tadir-object !iv_object_name TYPE tadir-obj_name !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params !ii_xml TYPE REF TO zif_abapgit_xml_output !io_files TYPE REF TO zcl_abapgit_objects_files RAISING zcx_abapgit_exception . METHODS deserialize IMPORTING !iv_object_type TYPE tadir-object OPTIONAL !iv_object_name TYPE tadir-obj_name OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params !ii_xml TYPE REF TO zif_abapgit_xml_input !io_files TYPE REF TO zcl_abapgit_objects_files RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_i18n_file. TYPES ty_table_of TYPE STANDARD TABLE OF REF TO zif_abapgit_i18n_file WITH DEFAULT KEY. METHODS render RETURNING VALUE(rv_data) TYPE xstring RAISING zcx_abapgit_exception. METHODS translate CHANGING ct_text_pairs TYPE zif_abapgit_lxe_texts=>ty_text_pairs RAISING zcx_abapgit_exception. METHODS ext RETURNING VALUE(rv_ext) TYPE string. METHODS lang RETURNING VALUE(rv_lang) TYPE laiso. ENDINTERFACE. INTERFACE zif_abapgit_comparator . TYPES: BEGIN OF ty_result, text TYPE string, END OF ty_result . METHODS compare IMPORTING !ii_remote TYPE REF TO zif_abapgit_xml_input !ii_log TYPE REF TO zif_abapgit_log RETURNING VALUE(rs_result) TYPE ty_result RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_persist_settings. METHODS modify IMPORTING !io_settings TYPE REF TO zcl_abapgit_settings RAISING zcx_abapgit_exception . METHODS read RETURNING VALUE(ro_settings) TYPE REF TO zcl_abapgit_settings . ENDINTERFACE. INTERFACE zif_abapgit_gui_asset_manager . TYPES: BEGIN OF ty_web_asset, url TYPE string, type TYPE c LENGTH 50, subtype TYPE c LENGTH 50, content TYPE xstring, is_cacheable TYPE abap_bool, END OF ty_web_asset . TYPES: ty_web_assets TYPE STANDARD TABLE OF ty_web_asset WITH DEFAULT KEY . METHODS get_all_assets RETURNING VALUE(rt_assets) TYPE ty_web_assets RAISING zcx_abapgit_exception. METHODS get_asset IMPORTING iv_url TYPE string RETURNING VALUE(rs_asset) TYPE ty_web_asset RAISING zcx_abapgit_exception. METHODS get_text_asset IMPORTING iv_url TYPE string iv_assert_subtype TYPE string OPTIONAL RETURNING VALUE(rv_asset) TYPE string RAISING zcx_abapgit_exception. METHODS register_asset IMPORTING !iv_url TYPE string !iv_type TYPE string !iv_cacheable TYPE abap_bool DEFAULT abap_true !iv_mime_name TYPE wwwdatatab-objid OPTIONAL !iv_base64 TYPE string OPTIONAL !iv_inline TYPE string OPTIONAL RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_gui_error_handler . METHODS handle_error IMPORTING ix_error TYPE REF TO zcx_abapgit_exception RETURNING VALUE(rv_handled) TYPE abap_bool. ENDINTERFACE. INTERFACE zif_abapgit_gui_event_handler . TYPES: BEGIN OF ty_handling_result, page TYPE REF TO zif_abapgit_gui_renderable, state TYPE i, END OF ty_handling_result. METHODS on_event IMPORTING ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE ty_handling_result RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_gui_hotkeys . TYPES: BEGIN OF ty_hotkey_with_descr, ui_component TYPE string, action TYPE string, hotkey TYPE string, description TYPE string, END OF ty_hotkey_with_descr . TYPES: ty_hotkeys_with_descr TYPE STANDARD TABLE OF ty_hotkey_with_descr WITH DEFAULT KEY WITH UNIQUE SORTED KEY action COMPONENTS ui_component action . METHODS get_hotkey_actions RETURNING VALUE(rt_hotkey_actions) TYPE ty_hotkeys_with_descr RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_gui_hotkey_ctl. METHODS register_hotkeys IMPORTING !it_hotkeys TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr. METHODS reset. METHODS get_registered_hotkeys RETURNING VALUE(rt_registered_hotkeys) TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr RAISING zcx_abapgit_exception. METHODS set_visible IMPORTING iv_visible TYPE abap_bool. ENDINTERFACE. INTERFACE zif_abapgit_gui_html_processor . METHODS process IMPORTING !iv_html TYPE string !ii_gui_services TYPE REF TO zif_abapgit_gui_services RETURNING VALUE(rv_html) TYPE string RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_gui_modal . METHODS is_modal RETURNING VALUE(rv_yes) TYPE abap_bool. ENDINTERFACE. INTERFACE zif_abapgit_gui_renderable . METHODS render RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_gui_services . METHODS cache_asset IMPORTING !iv_text TYPE string OPTIONAL !iv_xdata TYPE xstring OPTIONAL !iv_url TYPE string OPTIONAL !iv_type TYPE c !iv_subtype TYPE c RETURNING VALUE(rv_url) TYPE string RAISING zcx_abapgit_exception . " Notes: " - page_asset is supposed to be not cacheable " - add mime64 if needed (supposedly won't be needed) METHODS register_page_asset IMPORTING !iv_url TYPE string !iv_type TYPE string !iv_mime_name TYPE wwwdatatab-objid OPTIONAL !iv_inline TYPE string OPTIONAL RAISING zcx_abapgit_exception . METHODS register_event_handler IMPORTING !ii_event_handler TYPE REF TO zif_abapgit_gui_event_handler . METHODS get_current_page_name RETURNING VALUE(rv_page_name) TYPE string . METHODS get_hotkeys_ctl RETURNING VALUE(ri_hotkey_ctl) TYPE REF TO zif_abapgit_gui_hotkey_ctl . METHODS get_html_parts RETURNING VALUE(ro_parts) TYPE REF TO zcl_abapgit_html_parts . METHODS get_log IMPORTING !iv_create_new TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log . ENDINTERFACE. INTERFACE zif_abapgit_html. TYPES: BEGIN OF ty_data_attr, name TYPE string, value TYPE string, END OF ty_data_attr, ty_data_attrs TYPE STANDARD TABLE OF ty_data_attr WITH KEY name. CONSTANTS: BEGIN OF c_action_type, sapevent TYPE c VALUE 'E', url TYPE c VALUE 'U', onclick TYPE c VALUE 'C', separator TYPE c VALUE 'S', dummy TYPE c VALUE '_', END OF c_action_type . CONSTANTS: BEGIN OF c_html_opt, strong TYPE c VALUE 'E', cancel TYPE c VALUE 'C', crossout TYPE c VALUE 'X', END OF c_html_opt . TYPES: ty_table_of TYPE STANDARD TABLE OF REF TO zif_abapgit_html WITH DEFAULT KEY. DATA mv_chunk_title TYPE string READ-ONLY. " Primarily for debug of postponed html parts METHODS set_title IMPORTING iv_title TYPE string RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. METHODS add IMPORTING !ig_chunk TYPE any RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. METHODS render IMPORTING !iv_no_indent_jscss TYPE abap_bool DEFAULT abap_false !iv_no_line_breaks TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_html) TYPE string . METHODS is_empty RETURNING VALUE(rv_yes) TYPE abap_bool . METHODS add_a IMPORTING !iv_txt TYPE string !iv_act TYPE string !iv_query TYPE string OPTIONAL !iv_typ TYPE c DEFAULT c_action_type-sapevent !iv_opt TYPE clike OPTIONAL !iv_class TYPE string OPTIONAL !iv_id TYPE string OPTIONAL !iv_style TYPE string OPTIONAL !iv_title TYPE string OPTIONAL RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. METHODS add_checkbox IMPORTING iv_id TYPE string iv_checked TYPE abap_bool OPTIONAL RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. METHODS a IMPORTING !iv_txt TYPE string !iv_act TYPE string !iv_query TYPE string OPTIONAL !iv_typ TYPE c DEFAULT zif_abapgit_html=>c_action_type-sapevent !iv_opt TYPE clike OPTIONAL !iv_class TYPE string OPTIONAL !iv_id TYPE string OPTIONAL !iv_style TYPE string OPTIONAL !iv_title TYPE string OPTIONAL RETURNING VALUE(rv_str) TYPE string . METHODS icon IMPORTING !iv_name TYPE string !iv_hint TYPE string OPTIONAL !iv_class TYPE string OPTIONAL !iv_onclick TYPE string OPTIONAL RETURNING VALUE(rv_str) TYPE string . METHODS add_icon IMPORTING !iv_name TYPE string !iv_hint TYPE string OPTIONAL !iv_class TYPE string OPTIONAL !iv_onclick TYPE string OPTIONAL RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. METHODS wrap IMPORTING !iv_tag TYPE string !iv_content TYPE string OPTIONAL !ii_content TYPE REF TO zif_abapgit_html OPTIONAL !iv_id TYPE string OPTIONAL !iv_class TYPE string OPTIONAL !iv_hint TYPE string OPTIONAL !iv_format_single_line TYPE abap_bool DEFAULT abap_false !is_data_attr TYPE ty_data_attr OPTIONAL !it_data_attrs TYPE ty_data_attrs OPTIONAL RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. METHODS td IMPORTING !iv_content TYPE string OPTIONAL !ii_content TYPE REF TO zif_abapgit_html OPTIONAL !iv_id TYPE string OPTIONAL !iv_class TYPE string OPTIONAL !iv_hint TYPE string OPTIONAL !iv_format_single_line TYPE abap_bool DEFAULT abap_true !is_data_attr TYPE ty_data_attr OPTIONAL !it_data_attrs TYPE ty_data_attrs OPTIONAL PREFERRED PARAMETER iv_content RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. METHODS th IMPORTING !iv_content TYPE string OPTIONAL !ii_content TYPE REF TO zif_abapgit_html OPTIONAL !iv_id TYPE string OPTIONAL !iv_class TYPE string OPTIONAL !iv_hint TYPE string OPTIONAL !iv_format_single_line TYPE abap_bool DEFAULT abap_true !is_data_attr TYPE ty_data_attr OPTIONAL !it_data_attrs TYPE ty_data_attrs OPTIONAL PREFERRED PARAMETER iv_content RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. METHODS div IMPORTING !iv_content TYPE string OPTIONAL !ii_content TYPE REF TO zif_abapgit_html OPTIONAL !iv_id TYPE string OPTIONAL !iv_class TYPE string OPTIONAL !is_data_attr TYPE ty_data_attr OPTIONAL !it_data_attrs TYPE ty_data_attrs OPTIONAL PREFERRED PARAMETER iv_content RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. ENDINTERFACE. INTERFACE zif_abapgit_html_viewer . TYPES: ty_char256 TYPE c LENGTH 256 . TYPES: ty_post_data TYPE STANDARD TABLE OF ty_char256 WITH DEFAULT KEY . TYPES: BEGIN OF ty_name_value, name TYPE c LENGTH 30, value TYPE c LENGTH 250, END OF ty_name_value . TYPES: ty_query_table TYPE STANDARD TABLE OF ty_name_value WITH DEFAULT KEY . CONSTANTS c_id_sapevent TYPE i VALUE 1 ##NO_TEXT. EVENTS sapevent EXPORTING VALUE(action) TYPE c OPTIONAL VALUE(frame) TYPE c OPTIONAL VALUE(getdata) TYPE c OPTIONAL VALUE(postdata) TYPE ty_post_data OPTIONAL VALUE(query_table) TYPE ty_query_table OPTIONAL . METHODS load_data IMPORTING !iv_url TYPE string OPTIONAL !iv_type TYPE c DEFAULT 'text' !iv_subtype TYPE c DEFAULT 'html' !iv_size TYPE i DEFAULT 0 EXPORTING !ev_assigned_url TYPE string CHANGING !ct_data_table TYPE STANDARD TABLE RAISING zcx_abapgit_exception . METHODS set_registered_events IMPORTING !it_events TYPE cntl_simple_events RAISING zcx_abapgit_exception . METHODS show_url IMPORTING !iv_url TYPE string RAISING zcx_abapgit_exception . METHODS free . METHODS close_document . METHODS get_url RETURNING VALUE(rv_url) TYPE string . METHODS back . METHODS set_visiblity IMPORTING !iv_visible TYPE abap_bool . METHODS set_focus RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_gui_event . DATA mv_action TYPE string READ-ONLY. DATA mv_getdata TYPE string READ-ONLY. DATA mt_postdata TYPE zif_abapgit_html_viewer=>ty_post_data READ-ONLY. DATA mi_gui_services TYPE REF TO zif_abapgit_gui_services READ-ONLY. DATA mv_current_page_name TYPE string. METHODS query RETURNING VALUE(ro_string_map) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS form_data RETURNING VALUE(ro_string_map) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_gui_menu_provider . METHODS get_menu RETURNING VALUE(ro_toolbar) TYPE REF TO zcl_abapgit_html_toolbar RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_gui_page_title . METHODS get_page_title RETURNING VALUE(rv_title) TYPE string. ENDINTERFACE. INTERFACE zif_abapgit_gui_render_item . METHODS render IMPORTING iv_item TYPE any iv_index TYPE i RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_html_form . TYPES: BEGIN OF ty_subitem, label TYPE string, value TYPE string, readonly TYPE abap_bool, END OF ty_subitem . TYPES: ty_subitems TYPE STANDARD TABLE OF ty_subitem WITH DEFAULT KEY . TYPES: BEGIN OF ty_field, type TYPE i, name TYPE string, label TYPE string, hint TYPE string, dblclick TYPE string, click TYPE string, placeholder TYPE string, required TYPE string, upper_case TYPE abap_bool, item_class TYPE string, error TYPE string, default_value TYPE string, side_action TYPE string, subitems TYPE ty_subitems, readonly TYPE abap_bool, password TYPE abap_bool, condense TYPE abap_bool, min TYPE i, max TYPE i, rows TYPE i, cols TYPE i, END OF ty_field . TYPES: ty_fields TYPE STANDARD TABLE OF ty_field WITH DEFAULT KEY WITH UNIQUE SORTED KEY by_name COMPONENTS name . TYPES: BEGIN OF ty_command, label TYPE string, action TYPE string, cmd_type TYPE i, END OF ty_command . CONSTANTS c_rows TYPE string VALUE 'rows'. CONSTANTS: BEGIN OF c_cmd_type, input TYPE i VALUE 1, input_main TYPE i VALUE 2, link TYPE i VALUE 3, button TYPE i VALUE 4, END OF c_cmd_type . CONSTANTS: BEGIN OF c_field_type, text TYPE i VALUE 1, radio TYPE i VALUE 2, checkbox TYPE i VALUE 3, field_group TYPE i VALUE 4, number TYPE i VALUE 5, textarea TYPE i VALUE 6, table TYPE i VALUE 7, hidden TYPE i VALUE 8, END OF c_field_type . ENDINTERFACE. INTERFACE zif_abapgit_html_popup . METHODS create_picklist RETURNING VALUE(ro_picklist) TYPE REF TO zcl_abapgit_gui_picklist RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_html_table . TYPES: BEGIN OF ty_row_attrs, css_class TYPE string, data TYPE zif_abapgit_html=>ty_data_attr, END OF ty_row_attrs. TYPES: BEGIN OF ty_cell_render, css_class TYPE string, content TYPE string, html TYPE REF TO zif_abapgit_html, END OF ty_cell_render. TYPES: BEGIN OF ty_sorting_state, column_id TYPE string, descending TYPE abap_bool, END OF ty_sorting_state. METHODS get_row_attrs IMPORTING iv_table_id TYPE string iv_row_index TYPE i is_row TYPE any RETURNING VALUE(rs_attrs) TYPE ty_row_attrs RAISING zcx_abapgit_exception. METHODS render_cell IMPORTING iv_table_id TYPE string iv_row_index TYPE i is_row TYPE any iv_column_id TYPE string iv_value TYPE any RETURNING VALUE(rs_render) TYPE ty_cell_render RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_progress . METHODS show IMPORTING !iv_current TYPE i !iv_text TYPE csequence . METHODS set_total IMPORTING !iv_total TYPE i . METHODS off . ENDINTERFACE. INTERFACE zif_abapgit_services_repo . TYPES: BEGIN OF ty_repo_params, name TYPE string, url TYPE string, package TYPE devclass, branch_name TYPE string, display_name TYPE string, folder_logic TYPE string, labels TYPE string, ignore_subpackages TYPE abap_bool, main_lang_only TYPE abap_bool, abap_lang_vers TYPE string, END OF ty_repo_params . ENDINTERFACE. INTERFACE zif_abapgit_frontend_services. TYPES: ty_char1 TYPE c LENGTH 1, ty_gui_release TYPE n LENGTH 4, ty_gui_sp TYPE n LENGTH 2, ty_gui_patch TYPE n LENGTH 2. METHODS file_upload IMPORTING !iv_path TYPE string RETURNING VALUE(rv_xstr) TYPE xstring RAISING zcx_abapgit_exception. METHODS file_download IMPORTING !iv_path TYPE string !iv_xstr TYPE xstring RAISING zcx_abapgit_exception . METHODS show_file_save_dialog IMPORTING !iv_title TYPE string !iv_extension TYPE string !iv_default_filename TYPE string RETURNING VALUE(rv_path) TYPE string RAISING zcx_abapgit_exception. METHODS show_file_open_dialog IMPORTING !iv_title TYPE string !iv_extension TYPE string !iv_default_filename TYPE string RETURNING VALUE(rv_path) TYPE string RAISING zcx_abapgit_exception. METHODS clipboard_export IMPORTING iv_no_auth_check TYPE abap_bool DEFAULT abap_false VALUE(it_data) TYPE STANDARD TABLE RAISING zcx_abapgit_exception. METHODS execute IMPORTING !iv_document TYPE string OPTIONAL !iv_application TYPE string OPTIONAL !iv_parameter TYPE string OPTIONAL !iv_default_directory TYPE string OPTIONAL !iv_maximized TYPE string OPTIONAL !iv_minimized TYPE string OPTIONAL !iv_synchronous TYPE string OPTIONAL !iv_operation TYPE string DEFAULT 'OPEN' RAISING zcx_abapgit_exception. METHODS get_system_directory CHANGING !cv_system_directory TYPE string RAISING zcx_abapgit_exception. METHODS directory_browse IMPORTING iv_window_title TYPE string OPTIONAL iv_initial_folder TYPE string OPTIONAL CHANGING cv_selected_folder TYPE string RAISING zcx_abapgit_exception. METHODS get_file_separator CHANGING cv_file_separator TYPE ty_char1 RAISING zcx_abapgit_exception. METHODS get_gui_version EXPORTING ev_gui_release TYPE ty_gui_release ev_gui_sp TYPE ty_gui_sp ev_gui_patch TYPE ty_gui_patch ev_gui_version_string TYPE string RAISING zcx_abapgit_exception. METHODS directory_exist IMPORTING iv_directory TYPE string RETURNING VALUE(rv_exists) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS directory_create IMPORTING iv_directory TYPE string CHANGING cv_rc TYPE i RAISING zcx_abapgit_exception. METHODS gui_is_available RETURNING VALUE(rv_gui_is_available) TYPE abap_bool. METHODS is_sapgui_for_java RETURNING VALUE(rv_result) TYPE abap_bool. METHODS is_sapgui_for_windows RETURNING VALUE(rv_result) TYPE abap_bool. METHODS is_webgui RETURNING VALUE(rv_is_webgui) TYPE abap_bool. METHODS open_ie_devtools RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_definitions . TYPES: ty_string_tt TYPE STANDARD TABLE OF string WITH DEFAULT KEY . TYPES: BEGIN OF ty_item_signature, obj_type TYPE tadir-object, obj_name TYPE tadir-obj_name, devclass TYPE devclass, END OF ty_item_signature . TYPES: BEGIN OF ty_obj_namespace, namespace TYPE trnspace-namespace, obj_without_namespace TYPE tadir-obj_name, END OF ty_obj_namespace. TYPES: BEGIN OF ty_item. INCLUDE TYPE ty_item_signature. TYPES: srcsystem TYPE tadir-srcsystem, origlang TYPE tadir-masterlang, inactive TYPE abap_bool, abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version, END OF ty_item . TYPES: ty_items_tt TYPE STANDARD TABLE OF ty_item WITH DEFAULT KEY . TYPES: ty_items_ts TYPE SORTED TABLE OF ty_item WITH UNIQUE KEY obj_type obj_name . TYPES: BEGIN OF ty_file_item, file TYPE zif_abapgit_git_definitions=>ty_file, item TYPE ty_item, END OF ty_file_item . TYPES: ty_files_item_tt TYPE STANDARD TABLE OF ty_file_item WITH DEFAULT KEY . TYPES: ty_files_item_by_file_tt TYPE SORTED TABLE OF ty_file_item WITH UNIQUE KEY file-path file-filename. TYPES: ty_yes_no TYPE c LENGTH 1, ty_yes_no_partial TYPE c LENGTH 1. TYPES: BEGIN OF ty_overwrite. INCLUDE TYPE ty_item. TYPES: state TYPE c LENGTH 2, action TYPE i, icon TYPE icon_d, text TYPE string, decision TYPE ty_yes_no, END OF ty_overwrite . TYPES: ty_overwrite_tt TYPE STANDARD TABLE OF ty_overwrite WITH DEFAULT KEY WITH UNIQUE HASHED KEY object_type_and_name COMPONENTS obj_type obj_name . TYPES: BEGIN OF ty_requirements, met TYPE ty_yes_no, decision TYPE ty_yes_no, END OF ty_requirements . TYPES: BEGIN OF ty_dependencies, met TYPE ty_yes_no, decision TYPE ty_yes_no, END OF ty_dependencies . TYPES: BEGIN OF ty_transport_type, request TYPE trfunction, task TYPE trfunction, END OF ty_transport_type . TYPES: BEGIN OF ty_transport, required TYPE abap_bool, transport TYPE trkorr, type TYPE ty_transport_type, END OF ty_transport . TYPES: BEGIN OF ty_deserialize_checks, overwrite TYPE ty_overwrite_tt, warning_package TYPE ty_overwrite_tt, requirements TYPE ty_requirements, dependencies TYPE ty_dependencies, transport TYPE ty_transport, customizing TYPE ty_transport, END OF ty_deserialize_checks . TYPES: BEGIN OF ty_delete_checks, transport TYPE ty_transport, END OF ty_delete_checks . TYPES: BEGIN OF ty_metadata, class TYPE string, version TYPE string, END OF ty_metadata . TYPES: BEGIN OF ty_repo_file, path TYPE string, filename TYPE string, is_changed TYPE abap_bool, rstate TYPE zif_abapgit_git_definitions=>ty_item_state, lstate TYPE zif_abapgit_git_definitions=>ty_item_state, END OF ty_repo_file . TYPES: ty_repo_file_tt TYPE STANDARD TABLE OF ty_repo_file WITH DEFAULT KEY . TYPES: BEGIN OF ty_object, sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, type TYPE zif_abapgit_git_definitions=>ty_type, data TYPE xstring, adler32 TYPE zif_abapgit_git_definitions=>ty_adler32, index TYPE i, END OF ty_object . TYPES: ty_objects_tt TYPE STANDARD TABLE OF ty_object WITH DEFAULT KEY WITH NON-UNIQUE SORTED KEY sha COMPONENTS sha1 WITH NON-UNIQUE SORTED KEY type COMPONENTS type sha1 . TYPES: BEGIN OF ty_tadir, pgmid TYPE tadir-pgmid, object TYPE tadir-object, obj_name TYPE tadir-obj_name, devclass TYPE tadir-devclass, korrnum TYPE tadir-korrnum, " used by ZCL_ABAPGIT_DEPENDENCIES->RESOLVE delflag TYPE tadir-delflag, genflag TYPE tadir-genflag, path TYPE string, srcsystem TYPE tadir-srcsystem, masterlang TYPE tadir-masterlang, END OF ty_tadir . TYPES: ty_tadir_tt TYPE STANDARD TABLE OF ty_tadir WITH DEFAULT KEY . TYPES: BEGIN OF ty_result, obj_type TYPE tadir-object, obj_name TYPE tadir-obj_name, inactive TYPE abap_bool, path TYPE string, filename TYPE string, package TYPE devclass, match TYPE abap_bool, lstate TYPE zif_abapgit_git_definitions=>ty_item_state, rstate TYPE zif_abapgit_git_definitions=>ty_item_state, packmove TYPE abap_bool, srcsystem TYPE tadir-srcsystem, origlang TYPE tadir-masterlang, END OF ty_result . TYPES: ty_results_tt TYPE STANDARD TABLE OF ty_result WITH DEFAULT KEY WITH NON-UNIQUE SORTED KEY sec_key COMPONENTS obj_type obj_name. TYPES: ty_results_ts_path TYPE HASHED TABLE OF ty_result WITH UNIQUE KEY path filename . TYPES: BEGIN OF ty_stage_files, local TYPE ty_files_item_tt, remote TYPE zif_abapgit_git_definitions=>ty_files_tt, status TYPE ty_results_ts_path, END OF ty_stage_files . TYPES: BEGIN OF ty_tpool. INCLUDE TYPE textpool. TYPES: split TYPE c LENGTH 8. TYPES: END OF ty_tpool . TYPES: ty_tpool_tt TYPE STANDARD TABLE OF ty_tpool WITH DEFAULT KEY . TYPES: BEGIN OF ty_transport_to_branch, branch_name TYPE string, commit_text TYPE string, END OF ty_transport_to_branch . TYPES: BEGIN OF ty_diff, patch_flag TYPE abap_bool, new_num TYPE c LENGTH 6, new TYPE string, result TYPE c LENGTH 1, old_num TYPE c LENGTH 6, old TYPE string, short TYPE abap_bool, beacon TYPE i, END OF ty_diff . TYPES: ty_diffs_tt TYPE STANDARD TABLE OF ty_diff WITH DEFAULT KEY WITH NON-UNIQUE SORTED KEY new_num COMPONENTS new_num WITH NON-UNIQUE SORTED KEY old_num COMPONENTS old_num. TYPES: BEGIN OF ty_count, insert TYPE i, delete TYPE i, update TYPE i, END OF ty_count . TYPES: BEGIN OF ty_ancestor, commit TYPE zif_abapgit_git_definitions=>ty_sha1, tree TYPE zif_abapgit_git_definitions=>ty_sha1, time TYPE string, body TYPE string, END OF ty_ancestor . TYPES: BEGIN OF ty_repo_item, obj_type TYPE tadir-object, obj_name TYPE tadir-obj_name, inactive TYPE abap_bool, sortkey TYPE i, path TYPE string, is_dir TYPE abap_bool, changes TYPE i, lstate TYPE zif_abapgit_git_definitions=>ty_item_state, rstate TYPE zif_abapgit_git_definitions=>ty_item_state, files TYPE ty_repo_file_tt, changed_by TYPE syuname, transport TYPE trkorr, packmove TYPE abap_bool, srcsystem TYPE tadir-srcsystem, origlang TYPE tadir-masterlang, END OF ty_repo_item . TYPES: ty_repo_item_tt TYPE STANDARD TABLE OF ty_repo_item WITH DEFAULT KEY . TYPES: BEGIN OF ty_s_user_settings, max_lines TYPE i, adt_jump_enabled TYPE abap_bool, show_default_repo TYPE abap_bool, link_hints_enabled TYPE abap_bool, link_hint_key TYPE c LENGTH 1, parallel_proc_disabled TYPE abap_bool, icon_scaling TYPE c LENGTH 1, ui_theme TYPE string, hide_sapgui_hint TYPE abap_bool, activate_wo_popup TYPE abap_bool, label_colors TYPE string, END OF ty_s_user_settings . TYPES: BEGIN OF ty_list_settings, filter TYPE string, only_favorites TYPE abap_bool, show_details TYPE abap_bool, order_by TYPE string, order_descending TYPE abap_bool, END OF ty_list_settings. TYPES: ty_dokil_tt TYPE STANDARD TABLE OF dokil WITH NON-UNIQUE DEFAULT KEY . TYPES: BEGIN OF ty_col_spec, tech_name TYPE string, display_name TYPE string, css_class TYPE string, add_tz TYPE abap_bool, title TYPE string, allow_order_by TYPE abap_bool, END OF ty_col_spec, ty_col_spec_tt TYPE STANDARD TABLE OF ty_col_spec WITH NON-UNIQUE KEY tech_name. TYPES: ty_proxy_bypass_url TYPE c LENGTH 255, ty_range_proxy_bypass_url TYPE RANGE OF ty_proxy_bypass_url. TYPES: BEGIN OF ty_version, major TYPE i, minor TYPE i, patch TYPE i, prerelase TYPE string, prerelase_patch TYPE i, END OF ty_version. TYPES: ty_deserialization_step TYPE string. TYPES: ty_deserialization_step_tt TYPE STANDARD TABLE OF ty_deserialization_step WITH DEFAULT KEY . TYPES ty_sci_result TYPE c LENGTH 1. CONSTANTS: BEGIN OF c_sci_result, no_run TYPE ty_sci_result VALUE '', failed TYPE ty_sci_result VALUE 'F', warning TYPE ty_sci_result VALUE 'W', passed TYPE ty_sci_result VALUE 'P', END OF c_sci_result. CONSTANTS: BEGIN OF c_diff, unchanged TYPE c LENGTH 1 VALUE ' ', insert TYPE c LENGTH 1 VALUE 'I', delete TYPE c LENGTH 1 VALUE 'D', update TYPE c LENGTH 1 VALUE 'U', END OF c_diff . CONSTANTS: BEGIN OF c_state, " https://git-scm.com/docs/git-status unchanged TYPE zif_abapgit_git_definitions=>ty_item_state VALUE '', added TYPE zif_abapgit_git_definitions=>ty_item_state VALUE 'A', modified TYPE zif_abapgit_git_definitions=>ty_item_state VALUE 'M', deleted TYPE zif_abapgit_git_definitions=>ty_item_state VALUE 'D', mixed TYPE zif_abapgit_git_definitions=>ty_item_state VALUE '*', END OF c_state . CONSTANTS c_english TYPE spras VALUE 'E' ##NO_TEXT. CONSTANTS c_root_dir TYPE string VALUE '/' ##NO_TEXT. CONSTANTS c_dot_abapgit TYPE string VALUE '.abapgit.xml' ##NO_TEXT. CONSTANTS c_author_regex TYPE string VALUE '^(.+) <(.*)> (\d{10})\s?.\d{4}$' ##NO_TEXT. CONSTANTS: BEGIN OF c_action, abapgit_home TYPE string VALUE 'abapgit_home', bg_update TYPE string VALUE 'bg_update', change_order_by TYPE string VALUE 'change_order_by', changelog TYPE string VALUE 'changelog', clipboard TYPE string VALUE 'clipboard', db_display TYPE string VALUE 'db_display', db_edit TYPE string VALUE 'db_edit', direction TYPE string VALUE 'direction', documentation TYPE string VALUE 'documentation', flow TYPE string VALUE 'flow', git_branch_create TYPE string VALUE 'git_branch_create', git_branch_delete TYPE string VALUE 'git_branch_delete', git_branch_merge TYPE string VALUE 'git_branch_merge', git_branch_switch TYPE string VALUE 'git_branch_switch', git_commit TYPE string VALUE 'git_commit', git_pull TYPE string VALUE 'git_pull', git_tag_create TYPE string VALUE 'git_tag_create', git_tag_delete TYPE string VALUE 'git_tag_delete', git_tag_switch TYPE string VALUE 'git_tag_switch', go_back TYPE string VALUE 'go_back', go_background TYPE string VALUE 'go_background', go_background_run TYPE string VALUE 'go_background_run', go_commit TYPE string VALUE 'go_commit', go_db TYPE string VALUE 'go_db', go_debuginfo TYPE string VALUE 'go_debuginfo', go_explore TYPE string VALUE 'go_explore', go_file_diff TYPE string VALUE 'go_file_diff', go_home TYPE string VALUE 'go_home', go_patch TYPE string VALUE 'go_patch', go_repo TYPE string VALUE 'go_repo', go_repo_diff TYPE string VALUE 'go_repo_diff', go_settings TYPE string VALUE 'go_settings', go_settings_personal TYPE string VALUE 'go_settings_personal', go_stage TYPE string VALUE 'go_stage', go_stage_transport TYPE string VALUE 'go_stage_transport', go_tutorial TYPE string VALUE 'go_tutorial', goto_message TYPE string VALUE 'goto_message', goto_source TYPE string VALUE 'goto_source', homepage TYPE string VALUE 'homepage', ie_devtools TYPE string VALUE 'ie_devtools', jump TYPE string VALUE 'jump', jump_transaction TYPE string VALUE 'jump_transaction', jump_transport TYPE string VALUE 'jump_transport', jump_user TYPE string VALUE 'jump_user', performance_test TYPE string VALUE 'performance_test', repo_activate_objects TYPE string VALUE 'repo_activate_objects', repo_add_all_obj_to_trans_req TYPE string VALUE 'repo_add_all_obj_to_trans_req', repo_background TYPE string VALUE 'repo_background', repo_code_inspector TYPE string VALUE 'repo_code_inspector', repo_delete_objects TYPE string VALUE 'repo_delete_objects', repo_infos TYPE string VALUE 'repo_infos', repo_local_settings TYPE string VALUE 'repo_local_settings', repo_log TYPE string VALUE 'repo_log', repo_newoffline TYPE string VALUE 'repo_newoffline', repo_newonline TYPE string VALUE 'repo_newonline', repo_open_in_master_lang TYPE string VALUE 'repo_open_in_master_lang', repo_purge TYPE string VALUE 'repo_purge', repo_refresh TYPE string VALUE 'repo_refresh', repo_refresh_checksums TYPE string VALUE 'repo_refresh_checksums', repo_remote_settings TYPE string VALUE 'repo_remote_settings', repo_remove TYPE string VALUE 'repo_remove', repo_settings TYPE string VALUE 'repo_settings', repo_syntax_check TYPE string VALUE 'repo_syntax_check', repo_toggle_fav TYPE string VALUE 'repo_toggle_fav', repo_transport_to_branch TYPE string VALUE 'repo_transport_to_branch', rfc_compare TYPE string VALUE 'rfc_compare', show_callstack TYPE string VALUE 'show_callstack', show_hotkeys TYPE string VALUE 'show_hotkeys', sponsor TYPE string VALUE 'sponsor', toggle_favorites TYPE string VALUE 'toggle_favorites', url TYPE string VALUE 'url', where_used TYPE string VALUE 'where_used', yank_to_clipboard TYPE string VALUE 'yank_to_clipboard', zip_export TYPE string VALUE 'zip_export', zip_export_transport TYPE string VALUE 'zip_export_transport', zip_import TYPE string VALUE 'zip_import', zip_object TYPE string VALUE 'zip_object', zip_package TYPE string VALUE 'zip_package', zip_transport TYPE string VALUE 'zip_transport', END OF c_action. CONSTANTS c_spagpa_param_repo_key TYPE c LENGTH 20 VALUE 'REPO_KEY' ##NO_TEXT. CONSTANTS c_spagpa_param_package TYPE c LENGTH 20 VALUE 'PACKAGE' ##NO_TEXT. CONSTANTS c_yes TYPE ty_yes_no VALUE 'Y'. CONSTANTS c_no TYPE ty_yes_no VALUE 'N'. CONSTANTS c_partial TYPE ty_yes_no_partial VALUE 'P'. TYPES: ty_method TYPE c LENGTH 1 . TYPES: BEGIN OF ty_stage, file TYPE zif_abapgit_git_definitions=>ty_file, method TYPE ty_method, status TYPE ty_result, END OF ty_stage . TYPES: ty_stage_tt TYPE SORTED TABLE OF ty_stage WITH UNIQUE KEY file-path file-filename . CONSTANTS: BEGIN OF c_method, add TYPE ty_method VALUE 'A', rm TYPE ty_method VALUE 'R', ignore TYPE ty_method VALUE 'I', skip TYPE ty_method VALUE '?', END OF c_method . TYPES: ty_sap_langu_tab TYPE STANDARD TABLE OF langu WITH DEFAULT KEY. TYPES: ty_languages TYPE STANDARD TABLE OF laiso WITH DEFAULT KEY. TYPES: BEGIN OF ty_i18n_params, main_language TYPE sy-langu, main_language_only TYPE abap_bool, translation_languages TYPE ty_languages, use_lxe TYPE abap_bool, END OF ty_i18n_params . TYPES ty_trrngtrkor_tt TYPE RANGE OF trkorr. ENDINTERFACE. INTERFACE zif_abapgit_apack_definitions . TYPES: BEGIN OF ty_dependency, group_id TYPE string, artifact_id TYPE string, version TYPE string, sem_version TYPE zif_abapgit_definitions=>ty_version, git_url TYPE string, target_package TYPE devclass, END OF ty_dependency, ty_dependencies TYPE STANDARD TABLE OF ty_dependency WITH NON-UNIQUE DEFAULT KEY, ty_repository_type TYPE string, BEGIN OF ty_descriptor_wo_dependencies, group_id TYPE string, artifact_id TYPE string, version TYPE string, sem_version TYPE zif_abapgit_definitions=>ty_version, repository_type TYPE ty_repository_type, git_url TYPE string, END OF ty_descriptor_wo_dependencies, BEGIN OF ty_descriptor. INCLUDE TYPE ty_descriptor_wo_dependencies. TYPES: dependencies TYPE ty_dependencies, END OF ty_descriptor, ty_descriptors TYPE STANDARD TABLE OF ty_descriptor WITH NON-UNIQUE DEFAULT KEY. TYPES: BEGIN OF ty_manifest_declaration, clsname TYPE seoclsname, devclass TYPE devclass, END OF ty_manifest_declaration, ty_manifest_declarations TYPE STANDARD TABLE OF ty_manifest_declaration WITH DEFAULT KEY. CONSTANTS c_dot_apack_manifest TYPE string VALUE '.apack-manifest.xml' ##NO_TEXT. CONSTANTS c_repository_type_abapgit TYPE ty_repository_type VALUE 'abapGit' ##NO_TEXT. CONSTANTS c_apack_interface_sap TYPE seoclsname VALUE 'IF_APACK_MANIFEST' ##NO_TEXT. CONSTANTS c_apack_interface_cust TYPE seoclsname VALUE 'ZIF_APACK_MANIFEST' ##NO_TEXT. CONSTANTS c_apack_interface_nspc TYPE seoclsname VALUE '/*/IF_APACK_MANIFEST' ##NO_TEXT. ENDINTERFACE. INTERFACE zif_abapgit_cts_api . TYPES: BEGIN OF ty_transport, obj_type TYPE tadir-object, obj_name TYPE tadir-obj_name, trkorr TYPE trkorr, END OF ty_transport . TYPES: ty_transport_list TYPE SORTED TABLE OF ty_transport WITH NON-UNIQUE KEY obj_type obj_name . TYPES: ty_trkorr_tt TYPE STANDARD TABLE OF trkorr WITH DEFAULT KEY . TYPES: BEGIN OF ty_transport_key, object TYPE e071k-object, objname TYPE e071k-objname, tabkey TYPE e071k-tabkey, END OF ty_transport_key . TYPES: BEGIN OF ty_transport_data, trstatus TYPE e070-trstatus, keys TYPE STANDARD TABLE OF ty_transport_key WITH DEFAULT KEY, END OF ty_transport_data . TYPES: BEGIN OF ty_transport_obj, object TYPE e071-object, obj_name TYPE e071-obj_name, END OF ty_transport_obj . TYPES: ty_transport_obj_tt TYPE STANDARD TABLE OF ty_transport_obj WITH DEFAULT KEY . CONSTANTS: BEGIN OF c_transport_type, wb_request TYPE c LENGTH 1 VALUE 'K', "workbench request wb_repair TYPE c LENGTH 1 VALUE 'R', "workbench repair wb_task TYPE c LENGTH 1 VALUE 'S', "workbench task cust_request TYPE c LENGTH 1 VALUE 'W', "customizing request cust_task TYPE c LENGTH 1 VALUE 'Q', "customizing task END OF c_transport_type . CONSTANTS: BEGIN OF c_transport_category, workbench TYPE c LENGTH 4 VALUE 'SYST', customizing TYPE c LENGTH 4 VALUE 'CUST', END OF c_transport_category . CONSTANTS: BEGIN OF c_transport_mode, insert TYPE c LENGTH 1 VALUE 'I', delete TYPE c LENGTH 1 VALUE 'D', END OF c_transport_mode . CONSTANTS: BEGIN OF c_transport_status, modifiable TYPE c LENGTH 1 VALUE 'D', END OF c_transport_status . METHODS confirm_transport_messages RETURNING VALUE(rv_messages_confirmed) TYPE abap_bool . METHODS create_transport_entries IMPORTING !iv_transport TYPE trkorr !it_table_ins TYPE ANY TABLE !it_table_upd TYPE ANY TABLE !it_table_del TYPE ANY TABLE !iv_tabname TYPE tabname RAISING zcx_abapgit_exception . METHODS get_r3tr_obj_for_limu_obj IMPORTING !iv_object TYPE tadir-object !iv_obj_name TYPE trobj_name EXPORTING !ev_object TYPE tadir-object !ev_obj_name TYPE trobj_name RAISING zcx_abapgit_exception . METHODS get_transports_for_list IMPORTING !it_items TYPE zif_abapgit_definitions=>ty_items_tt RETURNING VALUE(rt_transports) TYPE ty_transport_list RAISING zcx_abapgit_exception . "! Returns the transport request / task the object is currently in "! @parameter is_item | Object "! @parameter rv_transport | Transport request / task "! @raising zcx_abapgit_exception | Object is not in a transport METHODS get_transport_for_object IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RETURNING VALUE(rv_transport) TYPE trkorr RAISING zcx_abapgit_exception . METHODS insert_transport_object IMPORTING !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' !iv_object TYPE tadir-object !iv_obj_name TYPE csequence !iv_package TYPE devclass !iv_language TYPE sy-langu DEFAULT sy-langu !iv_mode TYPE c DEFAULT 'I' EXPORTING !ev_object TYPE tadir-object !ev_obj_name TYPE trobj_name RAISING zcx_abapgit_exception . "! Check if change recording is possible for the given package "! @parameter iv_package | Package "! @parameter rv_possible | Change recording is possible "! @raising zcx_abapgit_exception | Package could not be loaded METHODS is_chrec_possible_for_package IMPORTING !iv_package TYPE devclass RETURNING VALUE(rv_possible) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS list_open_requests_by_user IMPORTING !iv_user TYPE sy-uname DEFAULT sy-uname RETURNING VALUE(rt_trkorr) TYPE ty_trkorr_tt RAISING zcx_abapgit_exception . METHODS list_r3tr_by_request IMPORTING !iv_request TYPE trkorr RETURNING VALUE(rt_list) TYPE ty_transport_obj_tt RAISING zcx_abapgit_exception . METHODS read IMPORTING !iv_trkorr TYPE trkorr RETURNING VALUE(rs_request) TYPE ty_transport_data RAISING zcx_abapgit_exception . METHODS read_description IMPORTING !iv_trkorr TYPE trkorr RETURNING VALUE(rv_description) TYPE string . METHODS read_user IMPORTING !iv_trkorr TYPE trkorr RETURNING VALUE(rv_uname) TYPE uname . METHODS validate_transport_request IMPORTING !iv_transport_request TYPE trkorr RAISING zcx_abapgit_exception . METHODS change_transport_type IMPORTING !iv_transport_request TYPE trkorr !iv_transport_type_from TYPE trfunction !iv_transport_type_to TYPE trfunction RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_data_deserializer . TYPES: BEGIN OF ty_result, type TYPE zif_abapgit_data_config=>ty_config-type, name TYPE zif_abapgit_data_config=>ty_config-name, deletes TYPE REF TO data, updates TYPE REF TO data, inserts TYPE REF TO data, file TYPE zif_abapgit_git_definitions=>ty_file_signature, config TYPE zif_abapgit_git_definitions=>ty_file_signature, END OF ty_result. TYPES: ty_results TYPE STANDARD TABLE OF ty_result WITH KEY type name. METHODS deserialize_check IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo !ii_config TYPE REF TO zif_abapgit_data_config RETURNING VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks-customizing RAISING zcx_abapgit_exception . METHODS deserialize IMPORTING !ii_config TYPE REF TO zif_abapgit_data_config !it_files TYPE zif_abapgit_git_definitions=>ty_files_tt RETURNING VALUE(rt_result) TYPE ty_results RAISING zcx_abapgit_exception . METHODS actualize IMPORTING !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks !it_result TYPE ty_results RETURNING VALUE(rt_accessed_files) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_gitv2_porcelain . METHODS list_branches IMPORTING !iv_url TYPE string !iv_prefix TYPE string OPTIONAL RETURNING VALUE(ro_list) TYPE REF TO zcl_abapgit_git_branch_list RAISING zcx_abapgit_exception . METHODS list_no_blobs IMPORTING !iv_url TYPE string !iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1 RETURNING VALUE(rt_expanded) TYPE zif_abapgit_git_definitions=>ty_expanded_tt RAISING zcx_abapgit_exception . METHODS list_no_blobs_multi IMPORTING !iv_url TYPE string !it_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt RETURNING VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception . METHODS commits_last_year IMPORTING !iv_url TYPE string !it_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt RETURNING VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_tadir . METHODS get_object_package IMPORTING !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' !iv_object TYPE tadir-object !iv_obj_name TYPE tadir-obj_name RETURNING VALUE(rv_devclass) TYPE tadir-devclass RAISING zcx_abapgit_exception . METHODS read IMPORTING !iv_package TYPE tadir-devclass !iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false !iv_only_local_objects TYPE abap_bool DEFAULT abap_false !io_dot TYPE REF TO zcl_abapgit_dot_abapgit OPTIONAL !ii_log TYPE REF TO zif_abapgit_log OPTIONAL !it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt OPTIONAL !iv_check_exists TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . METHODS read_single IMPORTING !iv_pgmid TYPE tadir-pgmid DEFAULT 'R3TR' !iv_object TYPE tadir-object !iv_obj_name TYPE tadir-obj_name RETURNING VALUE(rs_tadir) TYPE zif_abapgit_definitions=>ty_tadir. ENDINTERFACE. INTERFACE zif_abapgit_oo_object_fnc. CONSTANTS: BEGIN OF c_parts, locals_def TYPE string VALUE 'locals_def', locals_imp TYPE string VALUE 'locals_imp', macros TYPE string VALUE 'macros', testclasses TYPE string VALUE 'testclasses', END OF c_parts. TYPES: BEGIN OF ty_includes, programm TYPE syrepid, END OF ty_includes, ty_includes_tt TYPE STANDARD TABLE OF ty_includes WITH DEFAULT KEY. TYPES: ty_seocompotx_tt TYPE STANDARD TABLE OF seocompotx WITH DEFAULT KEY . TYPES: ty_seosubcotx_tt TYPE STANDARD TABLE OF seosubcotx WITH DEFAULT KEY . TYPES: BEGIN OF ty_obj_attribute, cmpname TYPE seocmpname, attkeyfld TYPE seokeyfld, attbusobj TYPE seobusobj, exposure TYPE seoexpose, END OF ty_obj_attribute . TYPES: ty_obj_attribute_tt TYPE STANDARD TABLE OF ty_obj_attribute WITH DEFAULT KEY WITH NON-UNIQUE SORTED KEY cmpname COMPONENTS cmpname . METHODS: create IMPORTING iv_check TYPE abap_bool iv_package TYPE devclass it_attributes TYPE ty_obj_attribute_tt OPTIONAL CHANGING cg_properties TYPE any RAISING zcx_abapgit_exception, generate_locals IMPORTING is_key TYPE seoclskey it_local_definitions TYPE seop_source_string OPTIONAL it_local_implementations TYPE seop_source_string OPTIONAL it_local_macros TYPE seop_source_string OPTIONAL it_local_test_classes TYPE seop_source_string OPTIONAL iv_package TYPE devclass iv_version TYPE uccheck RAISING zcx_abapgit_exception, deserialize_source IMPORTING is_key TYPE seoclskey it_source TYPE zif_abapgit_definitions=>ty_string_tt iv_package TYPE devclass iv_version TYPE uccheck RAISING zcx_abapgit_exception cx_sy_dyn_call_error, insert_text_pool IMPORTING iv_class_name TYPE seoclsname it_text_pool TYPE textpool_table iv_language TYPE spras iv_state TYPE c DEFAULT 'I' RAISING zcx_abapgit_exception, update_descriptions IMPORTING is_key TYPE seoclskey it_descriptions TYPE ty_seocompotx_tt, update_descriptions_sub IMPORTING is_key TYPE seoclskey it_descriptions TYPE ty_seosubcotx_tt, add_to_activation_list IMPORTING is_item TYPE zif_abapgit_definitions=>ty_item RAISING zcx_abapgit_exception, create_sotr IMPORTING iv_object_name TYPE sobj_name iv_package TYPE devclass ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception, create_documentation IMPORTING it_lines TYPE tlinetab iv_id TYPE dokhl-id iv_object_name TYPE dokhl-object iv_language TYPE spras iv_no_masterlang TYPE abap_bool OPTIONAL RAISING zcx_abapgit_exception, delete_documentation IMPORTING iv_id TYPE dokhl-id iv_object_name TYPE dokhl-object iv_language TYPE spras RAISING zcx_abapgit_exception, get_includes IMPORTING iv_object_name TYPE sobj_name RETURNING VALUE(rt_includes) TYPE ty_includes_tt RAISING zcx_abapgit_exception, exists IMPORTING is_object_name TYPE seoclskey RETURNING VALUE(rv_exists) TYPE abap_bool, serialize_abap IMPORTING is_class_key TYPE seoclskey iv_type TYPE seop_include_ext_app OPTIONAL RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt RAISING zcx_abapgit_exception cx_sy_dyn_call_error, get_skip_test_classes RETURNING VALUE(rv_skip) TYPE abap_bool, get_class_properties IMPORTING is_class_key TYPE seoclskey RETURNING VALUE(rs_class_properties) TYPE vseoclass RAISING zcx_abapgit_exception, get_interface_properties IMPORTING is_interface_key TYPE seoclskey RETURNING VALUE(rs_interface_properties) TYPE vseointerf RAISING zcx_abapgit_exception, read_text_pool IMPORTING iv_class_name TYPE seoclsname iv_language TYPE spras RETURNING VALUE(rt_text_pool) TYPE textpool_table, read_documentation IMPORTING iv_id TYPE dokhl-id iv_object_name TYPE dokhl-object iv_language TYPE spras RETURNING VALUE(rt_lines) TYPE tlinetab, read_sotr IMPORTING iv_object_name TYPE sobj_name ii_xml TYPE REF TO zif_abapgit_xml_output io_i18n_params TYPE REF TO zcl_abapgit_i18n_params RAISING zcx_abapgit_exception, read_descriptions IMPORTING iv_object_name TYPE seoclsname iv_language TYPE spras OPTIONAL RETURNING VALUE(rt_descriptions) TYPE ty_seocompotx_tt, read_descriptions_sub IMPORTING iv_object_name TYPE seoclsname iv_language TYPE spras OPTIONAL RETURNING VALUE(rt_descriptions) TYPE ty_seosubcotx_tt, delete IMPORTING is_deletion_key TYPE seoclskey RAISING zcx_abapgit_exception, read_superclass IMPORTING iv_classname TYPE seoclsname RETURNING VALUE(rv_superclass) TYPE seoclsname, read_attributes IMPORTING iv_object_name TYPE seoclsname RETURNING VALUE(rt_attributes) TYPE ty_obj_attribute_tt, syntax_check IMPORTING iv_object_name TYPE seoclsname RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_sap_namespace . METHODS exists IMPORTING iv_namespace TYPE trnspace-namespace RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS is_editable IMPORTING iv_namespace TYPE trnspace-namespace RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS split_by_name IMPORTING iv_obj_with_namespace TYPE csequence iv_allow_slash_in_name TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rs_obj_namespace) TYPE zif_abapgit_definitions=>ty_obj_namespace RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_sap_package . TYPES: ty_devclass_tt TYPE STANDARD TABLE OF devclass WITH DEFAULT KEY . TYPES: BEGIN OF ty_create, devclass TYPE devclass, dlvunit TYPE tdevc-dlvunit, component TYPE c LENGTH 20, ctext TYPE c LENGTH 60, parentcl TYPE devclass, pdevclass TYPE c LENGTH 4, as4user TYPE usnam, END OF ty_create. METHODS validate_name RAISING zcx_abapgit_exception . METHODS create IMPORTING !is_package TYPE ty_create RAISING zcx_abapgit_exception . METHODS create_local RAISING zcx_abapgit_exception . METHODS list_subpackages RETURNING VALUE(rt_list) TYPE ty_devclass_tt . METHODS list_superpackages RETURNING VALUE(rt_list) TYPE ty_devclass_tt RAISING zcx_abapgit_exception . METHODS read_parent RETURNING VALUE(rv_parentcl) TYPE devclass RAISING zcx_abapgit_exception . METHODS read_description RETURNING VALUE(rv_description) TYPE string RAISING zcx_abapgit_exception . METHODS read_responsible RETURNING VALUE(rv_responsible) TYPE usnam RAISING zcx_abapgit_exception . METHODS create_child IMPORTING !iv_child TYPE devclass RAISING zcx_abapgit_exception . METHODS exists RETURNING VALUE(rv_bool) TYPE abap_bool . METHODS are_changes_recorded_in_tr_req RETURNING VALUE(rv_are_changes_rec_in_tr_req) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS get_transport_type RETURNING VALUE(rs_transport_type) TYPE zif_abapgit_definitions=>ty_transport_type RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_sap_report. TYPES: BEGIN OF ty_progdir, name TYPE progdir-name, state TYPE progdir-state, sqlx TYPE progdir-sqlx, edtx TYPE progdir-edtx, varcl TYPE progdir-varcl, dbapl TYPE progdir-dbapl, dbna TYPE progdir-dbna, clas TYPE progdir-clas, type TYPE progdir-type, occurs TYPE progdir-occurs, subc TYPE progdir-subc, appl TYPE progdir-appl, secu TYPE progdir-secu, cnam TYPE progdir-cnam, cdat TYPE progdir-cdat, unam TYPE progdir-unam, udat TYPE progdir-udat, vern TYPE progdir-vern, levl TYPE progdir-levl, rstat TYPE progdir-rstat, rmand TYPE progdir-rmand, rload TYPE progdir-rload, fixpt TYPE progdir-fixpt, sset TYPE progdir-sset, sdate TYPE progdir-sdate, stime TYPE progdir-stime, idate TYPE progdir-idate, itime TYPE progdir-itime, ldbname TYPE progdir-ldbname, uccheck TYPE progdir-uccheck, END OF ty_progdir. METHODS read_report IMPORTING iv_name TYPE syrepid iv_state TYPE r3state OPTIONAL is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL RETURNING VALUE(rt_source) TYPE abaptxt255_tab RAISING zcx_abapgit_exception. METHODS insert_report IMPORTING iv_name TYPE syrepid it_source TYPE STANDARD TABLE iv_state TYPE r3state OPTIONAL iv_program_type TYPE c OPTIONAL iv_extension_type TYPE c OPTIONAL iv_package TYPE devclass iv_version TYPE uccheck is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL RAISING zcx_abapgit_exception. METHODS update_report IMPORTING iv_name TYPE syrepid it_source TYPE STANDARD TABLE iv_state TYPE r3state OPTIONAL iv_program_type TYPE c OPTIONAL iv_extension_type TYPE c OPTIONAL iv_package TYPE devclass iv_version TYPE uccheck is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL RETURNING VALUE(rv_updated) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS delete_report IMPORTING iv_name TYPE syrepid iv_raise_error TYPE abap_bool DEFAULT abap_false is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL RAISING zcx_abapgit_exception. METHODS read_progdir IMPORTING iv_name TYPE syrepid iv_state TYPE r3state DEFAULT 'A' RETURNING VALUE(rs_progdir) TYPE ty_progdir RAISING zcx_abapgit_exception. METHODS update_progdir IMPORTING is_progdir TYPE ty_progdir iv_package TYPE devclass iv_state TYPE r3state DEFAULT 'I' RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_lang_definitions . TYPES: BEGIN OF ty_i18n_tpool, language TYPE langu, textpool TYPE zif_abapgit_definitions=>ty_tpool_tt, END OF ty_i18n_tpool, ty_i18n_tpools TYPE STANDARD TABLE OF ty_i18n_tpool. TYPES: BEGIN OF ty_i18n_line, language TYPE langu, lines TYPE tlinetab, END OF ty_i18n_line, ty_i18n_lines TYPE STANDARD TABLE OF ty_i18n_line WITH KEY language. TYPES: ty_langus TYPE STANDARD TABLE OF langu. ENDINTERFACE. INTERFACE zif_abapgit_longtexts . TYPES: BEGIN OF ty_longtext, dokil TYPE dokil, head TYPE thead, lines TYPE tline_tab, END OF ty_longtext . TYPES: ty_longtexts TYPE STANDARD TABLE OF ty_longtext WITH NON-UNIQUE DEFAULT KEY . METHODS changed_by IMPORTING !iv_object_name TYPE tadir-obj_name !iv_longtext_id TYPE dokil-id !it_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt OPTIONAL RETURNING VALUE(rv_user) TYPE syuname RAISING zcx_abapgit_exception . METHODS serialize IMPORTING !iv_longtext_name TYPE string DEFAULT 'LONGTEXTS' !iv_object_name TYPE clike !iv_longtext_id TYPE dokil-id !it_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt OPTIONAL !ii_xml TYPE REF TO zif_abapgit_xml_output !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params RETURNING VALUE(rt_longtexts) TYPE ty_longtexts RAISING zcx_abapgit_exception . METHODS deserialize IMPORTING !iv_longtext_name TYPE string DEFAULT 'LONGTEXTS' !iv_object_name TYPE clike !iv_longtext_id TYPE dokil-id !ii_xml TYPE REF TO zif_abapgit_xml_input !iv_main_language TYPE sy-langu RAISING zcx_abapgit_exception . METHODS delete IMPORTING !iv_object_name TYPE tadir-obj_name !iv_longtext_id TYPE dokil-id RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_object_tabl. CONSTANTS: BEGIN OF c_s_dataname, segment_definition TYPE string VALUE 'SEGMENT_DEFINITION', tabl_extras TYPE string VALUE 'TABL_EXTRAS', END OF c_s_dataname. TYPES: BEGIN OF ty_dd02_text, ddlanguage TYPE dd02t-ddlanguage, ddtext TYPE dd02t-ddtext, END OF ty_dd02_text. TYPES ty_dd02_texts TYPE STANDARD TABLE OF ty_dd02_text WITH DEFAULT KEY. TYPES ty_dd03p_tt TYPE STANDARD TABLE OF dd03p WITH DEFAULT KEY. TYPES: BEGIN OF ty_segment_definition, segmentheader TYPE edisegmhd, segmentdefinition TYPE edisegmdef, segmentstructures TYPE STANDARD TABLE OF edisegstru WITH DEFAULT KEY, END OF ty_segment_definition. TYPES: ty_segment_definitions TYPE STANDARD TABLE OF ty_segment_definition WITH DEFAULT KEY. TYPES: BEGIN OF ty_tabl_extras, tddat TYPE tddat, END OF ty_tabl_extras. TYPES: BEGIN OF ty_internal, dd02v TYPE dd02v, dd09l TYPE dd09l, dd03p TYPE ty_dd03p_tt, dd05m TYPE STANDARD TABLE OF dd05m WITH DEFAULT KEY, dd08v TYPE STANDARD TABLE OF dd08v WITH DEFAULT KEY, dd12v TYPE STANDARD TABLE OF dd12v WITH DEFAULT KEY, dd17v TYPE STANDARD TABLE OF dd17v WITH DEFAULT KEY, dd35v TYPE STANDARD TABLE OF dd35v WITH DEFAULT KEY, dd36m TYPE STANDARD TABLE OF dd36m WITH DEFAULT KEY, dd02_texts TYPE ty_dd02_texts, i18n_langs TYPE STANDARD TABLE OF langu WITH DEFAULT KEY, longtexts TYPE zif_abapgit_longtexts=>ty_longtexts, segment_definitions TYPE ty_segment_definitions, extras TYPE ty_tabl_extras, END OF ty_internal. ENDINTERFACE. INTERFACE zif_abapgit_object . CONSTANTS: BEGIN OF gc_step_id, early TYPE zif_abapgit_definitions=>ty_deserialization_step VALUE `EARLY`, abap TYPE zif_abapgit_definitions=>ty_deserialization_step VALUE `ABAP`, ddic TYPE zif_abapgit_definitions=>ty_deserialization_step VALUE `DDIC`, late TYPE zif_abapgit_definitions=>ty_deserialization_step VALUE `LATE`, END OF gc_step_id. METHODS serialize IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize IMPORTING !iv_package TYPE devclass !io_xml TYPE REF TO zif_abapgit_xml_input !iv_step TYPE zif_abapgit_definitions=>ty_deserialization_step !ii_log TYPE REF TO zif_abapgit_log !iv_transport TYPE trkorr RAISING zcx_abapgit_exception . METHODS delete IMPORTING !iv_package TYPE devclass !iv_transport TYPE trkorr RAISING zcx_abapgit_exception . METHODS exists RETURNING VALUE(rv_bool) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS is_locked RETURNING VALUE(rv_is_locked) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS is_active RETURNING VALUE(rv_active) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS changed_by IMPORTING !iv_extra TYPE string OPTIONAL RETURNING VALUE(rv_user) TYPE syuname RAISING zcx_abapgit_exception . METHODS jump IMPORTING !iv_extra TYPE string OPTIONAL RETURNING VALUE(rv_exit) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS get_metadata RETURNING VALUE(rs_metadata) TYPE zif_abapgit_definitions=>ty_metadata . METHODS get_comparator RETURNING VALUE(ri_comparator) TYPE REF TO zif_abapgit_comparator RAISING zcx_abapgit_exception . METHODS get_deserialize_steps RETURNING VALUE(rt_steps) TYPE zif_abapgit_definitions=>ty_deserialization_step_tt . METHODS get_deserialize_order IMPORTING !it_all_objects TYPE zif_abapgit_definitions=>ty_items_tt RETURNING VALUE(rt_objects_before) TYPE zif_abapgit_definitions=>ty_items_tt. CLASS-METHODS map_filename_to_object IMPORTING !iv_filename TYPE string !iv_path TYPE string OPTIONAL !io_dot TYPE REF TO zcl_abapgit_dot_abapgit OPTIONAL !iv_package TYPE devclass OPTIONAL CHANGING cs_item TYPE zif_abapgit_definitions=>ty_item RAISING zcx_abapgit_exception. CLASS-METHODS map_object_to_filename IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item CHANGING cv_filename TYPE string RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_objects. TYPES: BEGIN OF ty_serialization, files TYPE zif_abapgit_git_definitions=>ty_files_tt, item TYPE zif_abapgit_definitions=>ty_item, END OF ty_serialization . TYPES: BEGIN OF ty_deserialization, obj TYPE REF TO zif_abapgit_object, xml TYPE REF TO zif_abapgit_xml_input, package TYPE devclass, item TYPE zif_abapgit_definitions=>ty_item, END OF ty_deserialization . TYPES: ty_deserialization_tt TYPE STANDARD TABLE OF ty_deserialization WITH DEFAULT KEY . TYPES: BEGIN OF ty_step_data, step_id TYPE zif_abapgit_definitions=>ty_deserialization_step, order TYPE i, descr TYPE string, syntax_check TYPE abap_bool, objects TYPE ty_deserialization_tt, END OF ty_step_data . TYPES: ty_step_data_tt TYPE STANDARD TABLE OF ty_step_data WITH DEFAULT KEY . CONSTANTS: BEGIN OF c_deserialize_action, " also used to determine priority if object has multiple changes, so don't change order no_support TYPE i VALUE -1, none TYPE i VALUE 0, add TYPE i VALUE 1, update TYPE i VALUE 2, overwrite TYPE i VALUE 3, delete TYPE i VALUE 4, delete_add TYPE i VALUE 5, packmove TYPE i VALUE 6, END OF c_deserialize_action. ENDINTERFACE. INTERFACE zif_abapgit_object_filter . METHODS get_filter RETURNING VALUE(rt_filter) TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_merge . TYPES: BEGIN OF ty_merge, repo TYPE REF TO zcl_abapgit_repo_online, source TYPE zif_abapgit_git_definitions=>ty_git_branch, target TYPE zif_abapgit_git_definitions=>ty_git_branch, common TYPE zif_abapgit_definitions=>ty_ancestor, stree TYPE zif_abapgit_git_definitions=>ty_expanded_tt, ttree TYPE zif_abapgit_git_definitions=>ty_expanded_tt, ctree TYPE zif_abapgit_git_definitions=>ty_expanded_tt, result TYPE zif_abapgit_git_definitions=>ty_expanded_tt, stage TYPE REF TO zcl_abapgit_stage, conflict TYPE string, END OF ty_merge . TYPES: BEGIN OF ty_merge_conflict, path TYPE string, filename TYPE string, source_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, source_data TYPE xstring, target_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, target_data TYPE xstring, result_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, result_data TYPE xstring, END OF ty_merge_conflict . TYPES: ty_merge_conflict_tt TYPE STANDARD TABLE OF ty_merge_conflict WITH DEFAULT KEY . METHODS get_conflicts RETURNING VALUE(rt_conflicts) TYPE ty_merge_conflict_tt . METHODS get_result RETURNING VALUE(rs_merge) TYPE ty_merge . METHODS get_source_branch RETURNING VALUE(rv_source_branch) TYPE string . METHODS has_conflicts RETURNING VALUE(rv_conflicts_exists) TYPE abap_bool . METHODS resolve_conflict IMPORTING !is_conflict TYPE ty_merge_conflict RAISING zcx_abapgit_exception . METHODS run RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_stage_logic . METHODS get IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online !ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL RETURNING VALUE(rs_files) TYPE zif_abapgit_definitions=>ty_stage_files RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_dot_abapgit. TYPES: BEGIN OF ty_requirement, component TYPE tdevc-dlvunit, min_release TYPE saprelease, min_patch TYPE sappatchlv, END OF ty_requirement . TYPES: ty_requirement_tt TYPE STANDARD TABLE OF ty_requirement WITH DEFAULT KEY . TYPES: BEGIN OF ty_dot_abapgit, name TYPE string, master_language TYPE spras, i18n_languages TYPE zif_abapgit_definitions=>ty_languages, use_lxe TYPE abap_bool, starting_folder TYPE string, folder_logic TYPE string, ignore TYPE STANDARD TABLE OF string WITH DEFAULT KEY, requirements TYPE ty_requirement_tt, version_constant TYPE string, abap_language_version TYPE string, original_system TYPE tadir-srcsystem, END OF ty_dot_abapgit . CONSTANTS: BEGIN OF c_folder_logic, prefix TYPE string VALUE 'PREFIX', full TYPE string VALUE 'FULL', mixed TYPE string VALUE 'MIXED', END OF c_folder_logic, BEGIN OF c_abap_language_version, standard TYPE string VALUE 'standard', key_user TYPE string VALUE 'keyUser', cloud_development TYPE string VALUE 'cloudDevelopment', ignore TYPE string VALUE 'ignore', undefined TYPE string VALUE 'undefined', " any END OF c_abap_language_version. ENDINTERFACE. INTERFACE zif_abapgit_persistence. TYPES: ty_type TYPE c LENGTH 12 . TYPES: ty_value TYPE c LENGTH 12 . TYPES: BEGIN OF ty_content, type TYPE ty_type, value TYPE ty_value, data_str TYPE string, END OF ty_content . TYPES: ty_contents TYPE SORTED TABLE OF ty_content WITH UNIQUE KEY type value . TYPES: BEGIN OF ty_local_checksum, item TYPE zif_abapgit_definitions=>ty_item_signature, files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt, END OF ty_local_checksum. TYPES: BEGIN OF ty_local_settings, display_name TYPE string, ignore_subpackages TYPE abap_bool, write_protected TYPE abap_bool, only_local_objects TYPE abap_bool, code_inspector_check_variant TYPE sci_chkv, block_commit TYPE abap_bool, main_language_only TYPE abap_bool, labels TYPE string, transport_request TYPE trkorr, customizing_request TYPE trkorr, flow TYPE abap_bool, END OF ty_local_settings. TYPES: ty_local_checksum_tt TYPE STANDARD TABLE OF ty_local_checksum WITH DEFAULT KEY. TYPES: ty_local_checksum_by_item_tt TYPE SORTED TABLE OF ty_local_checksum WITH NON-UNIQUE KEY item-obj_type item-obj_name. TYPES: BEGIN OF ty_repo_xml, url TYPE string, branch_name TYPE string, selected_commit TYPE zif_abapgit_git_definitions=>ty_sha1, package TYPE devclass, created_by TYPE syuname, created_at TYPE timestampl, deserialized_by TYPE syuname, deserialized_at TYPE timestampl, offline TYPE abap_bool, switched_origin TYPE string, dot_abapgit TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit, head_branch TYPE string, " HEAD symref of the repo, master branch local_settings TYPE ty_local_settings, END OF ty_repo_xml. TYPES: BEGIN OF ty_repo_meta_mask, url TYPE abap_bool, branch_name TYPE abap_bool, selected_commit TYPE abap_bool, package TYPE abap_bool, created_by TYPE abap_bool, created_at TYPE abap_bool, deserialized_by TYPE abap_bool, deserialized_at TYPE abap_bool, offline TYPE abap_bool, switched_origin TYPE abap_bool, dot_abapgit TYPE abap_bool, head_branch TYPE abap_bool, local_settings TYPE abap_bool, END OF ty_repo_meta_mask. TYPES: BEGIN OF ty_repo, key TYPE ty_value. INCLUDE TYPE ty_repo_xml. TYPES: END OF ty_repo. TYPES: ty_repos TYPE STANDARD TABLE OF ty_repo WITH DEFAULT KEY. TYPES: ty_repo_keys TYPE STANDARD TABLE OF ty_repo-key WITH DEFAULT KEY. ENDINTERFACE. INTERFACE zif_abapgit_exit. TYPES: BEGIN OF ty_ci_repo, name TYPE string, clone_url TYPE string, END OF ty_ci_repo. TYPES: ty_ci_repos TYPE TABLE OF ty_ci_repo. TYPES: ty_object_types TYPE STANDARD TABLE OF tadir-object WITH DEFAULT KEY. TYPES: BEGIN OF ty_class_key, clsname TYPE abap_classname, END OF ty_class_key. METHODS adjust_display_commit_url IMPORTING !iv_repo_url TYPE csequence !iv_repo_name TYPE csequence !iv_repo_key TYPE csequence !iv_commit_hash TYPE zif_abapgit_git_definitions=>ty_sha1 CHANGING !cv_display_url TYPE csequence RAISING zcx_abapgit_exception. METHODS adjust_display_filename IMPORTING !is_repo_meta TYPE zif_abapgit_persistence=>ty_repo !iv_filename TYPE string RETURNING VALUE(rv_filename) TYPE string. METHODS allow_sap_objects RETURNING VALUE(rv_allowed) TYPE abap_bool. METHODS change_local_host CHANGING !ct_hosts TYPE zif_abapgit_definitions=>ty_string_tt. METHODS change_max_parallel_processes IMPORTING !iv_package TYPE devclass CHANGING !cv_max_processes TYPE i. METHODS change_proxy_authentication IMPORTING !iv_repo_url TYPE csequence CHANGING !cv_proxy_authentication TYPE abap_bool. METHODS change_proxy_port IMPORTING !iv_repo_url TYPE csequence CHANGING !cv_proxy_port TYPE string. METHODS change_proxy_url IMPORTING !iv_repo_url TYPE csequence CHANGING !cv_proxy_url TYPE string. METHODS change_rfc_server_group CHANGING !cv_group TYPE rzlli_apcl. METHODS change_supported_data_objects CHANGING !ct_objects TYPE zif_abapgit_data_supporter=>ty_objects. METHODS change_supported_object_types CHANGING !ct_types TYPE ty_object_types. METHODS change_tadir IMPORTING !iv_package TYPE devclass !ii_log TYPE REF TO zif_abapgit_log !is_dot_abapgit TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit !iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false !iv_only_local_objects TYPE abap_bool DEFAULT abap_false CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. METHODS create_http_client IMPORTING !iv_url TYPE string RETURNING VALUE(ri_client) TYPE REF TO if_http_client RAISING zcx_abapgit_exception. METHODS custom_serialize_abap_clif IMPORTING !is_class_key TYPE ty_class_key !it_source TYPE zif_abapgit_definitions=>ty_string_tt OPTIONAL RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt RAISING zcx_abapgit_exception. METHODS deserialize_postprocess IMPORTING !is_step TYPE zif_abapgit_objects=>ty_step_data !ii_log TYPE REF TO zif_abapgit_log. METHODS determine_transport_request IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo !iv_transport_type TYPE zif_abapgit_definitions=>ty_transport_type CHANGING !cv_transport_request TYPE trkorr. METHODS enhance_repo_toolbar IMPORTING !io_menu TYPE REF TO zcl_abapgit_html_toolbar !iv_key TYPE zif_abapgit_persistence=>ty_value !iv_act TYPE string. METHODS get_ci_tests IMPORTING !iv_object TYPE tadir-object CHANGING !ct_ci_repos TYPE ty_ci_repos. METHODS get_ssl_id RETURNING VALUE(rv_ssl_id) TYPE ssfapplssl. METHODS http_client IMPORTING !iv_url TYPE string !ii_client TYPE REF TO if_http_client. METHODS on_event IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception. METHODS pre_calculate_repo_status IMPORTING !is_repo_meta TYPE zif_abapgit_persistence=>ty_repo CHANGING !ct_local TYPE zif_abapgit_definitions=>ty_files_item_tt !ct_remote TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception. METHODS serialize_postprocess IMPORTING !iv_package TYPE devclass !ii_log TYPE REF TO zif_abapgit_log CHANGING !ct_files TYPE zif_abapgit_definitions=>ty_files_item_tt. METHODS validate_before_push IMPORTING !is_comment TYPE zif_abapgit_git_definitions=>ty_comment !io_stage TYPE REF TO zcl_abapgit_stage !io_repo TYPE REF TO zcl_abapgit_repo_online RAISING zcx_abapgit_exception. METHODS wall_message_list IMPORTING !ii_html TYPE REF TO zif_abapgit_html. METHODS wall_message_repo IMPORTING !is_repo_meta TYPE zif_abapgit_persistence=>ty_repo !ii_html TYPE REF TO zif_abapgit_html. ENDINTERFACE. INTERFACE zif_abapgit_gui_jumper. TYPES: ty_bdcdata_tt TYPE STANDARD TABLE OF bdcdata WITH DEFAULT KEY. METHODS jump IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !is_sub_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL !iv_line_number TYPE i OPTIONAL !iv_new_window TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rv_exit) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS jump_adt IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_sub_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name !iv_line_number TYPE i RETURNING VALUE(rv_exit) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS jump_batch_input IMPORTING !iv_tcode TYPE sy-tcode !it_bdcdata TYPE ty_bdcdata_tt !iv_new_window TYPE abap_bool DEFAULT abap_true RAISING zcx_abapgit_exception. METHODS jump_abapgit IMPORTING !iv_language TYPE spras !iv_key TYPE zif_abapgit_persistence=>ty_value RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_persist_repo . METHODS add IMPORTING !iv_url TYPE string OPTIONAL !iv_branch_name TYPE string OPTIONAL !iv_branch TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL !iv_display_name TYPE string OPTIONAL !iv_package TYPE devclass !iv_offline TYPE abap_bool DEFAULT abap_false !is_dot_abapgit TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit RETURNING VALUE(rv_key) TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . METHODS delete IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . METHODS exists IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS list RETURNING VALUE(rt_repos) TYPE zif_abapgit_persistence=>ty_repos RAISING zcx_abapgit_exception . METHODS list_by_keys IMPORTING it_keys TYPE zif_abapgit_persistence=>ty_repo_keys RETURNING VALUE(rt_repos) TYPE zif_abapgit_persistence=>ty_repos RAISING zcx_abapgit_exception . METHODS lock IMPORTING !iv_mode TYPE enqmode !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . METHODS read IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RETURNING VALUE(rs_repo) TYPE zif_abapgit_persistence=>ty_repo RAISING zcx_abapgit_exception zcx_abapgit_not_found . METHODS update_metadata IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !is_meta TYPE zif_abapgit_persistence=>ty_repo_xml !is_change_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_persist_repo_cs . METHODS update IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !iv_cs_blob TYPE zif_abapgit_persistence=>ty_content-data_str RAISING zcx_abapgit_exception . METHODS delete IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . METHODS read IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RETURNING VALUE(rv_cs_blob) TYPE zif_abapgit_persistence=>ty_content-data_str RAISING zcx_abapgit_exception zcx_abapgit_not_found . ENDINTERFACE. INTERFACE zif_abapgit_persist_user . TYPES ty_favorites TYPE zif_abapgit_persistence=>ty_repo_keys . METHODS get_changes_only RETURNING VALUE(rv_changes_only) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS get_default_git_user_email RETURNING VALUE(rv_email) TYPE string RAISING zcx_abapgit_exception . METHODS get_default_git_user_name RETURNING VALUE(rv_username) TYPE string RAISING zcx_abapgit_exception . METHODS get_diff_unified RETURNING VALUE(rv_diff_unified) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS get_favorites RETURNING VALUE(rt_favorites) TYPE ty_favorites RAISING zcx_abapgit_exception . METHODS get_hide_files RETURNING VALUE(rv_hide) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS get_show_folders RETURNING VALUE(rv_folders) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS get_repo_git_user_email IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url RETURNING VALUE(rv_email) TYPE string RAISING zcx_abapgit_exception . METHODS get_repo_git_user_name IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url RETURNING VALUE(rv_username) TYPE string RAISING zcx_abapgit_exception . METHODS get_repo_last_change_seen IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url RETURNING VALUE(rv_version) TYPE string RAISING zcx_abapgit_exception . METHODS get_repo_login IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url RETURNING VALUE(rv_login) TYPE string RAISING zcx_abapgit_exception . METHODS get_repo_show RETURNING VALUE(rv_key) TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . METHODS is_favorite_repo IMPORTING !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key RETURNING VALUE(rv_yes) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS set_default_git_user_email IMPORTING !iv_email TYPE string RAISING zcx_abapgit_exception . METHODS set_default_git_user_name IMPORTING !iv_username TYPE string RAISING zcx_abapgit_exception . METHODS set_repo_git_user_email IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url !iv_email TYPE string RAISING zcx_abapgit_exception . METHODS set_repo_git_user_name IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url !iv_username TYPE string RAISING zcx_abapgit_exception . METHODS set_repo_last_change_seen IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url !iv_version TYPE string RAISING zcx_abapgit_exception . METHODS set_repo_login IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url !iv_login TYPE string RAISING zcx_abapgit_exception . METHODS set_repo_show IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . METHODS toggle_changes_only RETURNING VALUE(rv_changes_only) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS get_order_by RETURNING VALUE(rv_order_by) TYPE string RAISING zcx_abapgit_exception. METHODS set_order_by IMPORTING iv_order_by TYPE string RETURNING VALUE(rv_order_by) TYPE string RAISING zcx_abapgit_exception. METHODS get_order_descending RETURNING VALUE(rv_order_descending) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS set_order_descending IMPORTING iv_order_descending TYPE abap_bool RETURNING VALUE(rv_order_descending) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS get_diff_first RETURNING VALUE(rv_diff_first) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS set_diff_first IMPORTING iv_diff_first TYPE abap_bool RETURNING VALUE(rv_diff_first) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS toggle_diff_unified RETURNING VALUE(rv_diff_unified) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS toggle_favorite IMPORTING !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . METHODS toggle_hide_files RETURNING VALUE(rv_hide) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS toggle_show_folders RETURNING VALUE(rv_folders) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS get_settings RETURNING VALUE(rs_user_settings) TYPE zif_abapgit_definitions=>ty_s_user_settings RAISING zcx_abapgit_exception. METHODS set_settings IMPORTING is_user_settings TYPE zif_abapgit_definitions=>ty_s_user_settings RAISING zcx_abapgit_exception. METHODS get_list_settings RETURNING VALUE(rs_list_settings) TYPE zif_abapgit_definitions=>ty_list_settings RAISING zcx_abapgit_exception. METHODS set_list_settings IMPORTING is_list_settings TYPE zif_abapgit_definitions=>ty_list_settings RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_repo . DATA ms_data TYPE zif_abapgit_persistence=>ty_repo READ-ONLY. METHODS get_key RETURNING VALUE(rv_key) TYPE zif_abapgit_persistence=>ty_value . METHODS get_name RETURNING VALUE(rv_name) TYPE string. METHODS is_offline RETURNING VALUE(rv_offline) TYPE abap_bool . METHODS get_package RETURNING VALUE(rv_package) TYPE zif_abapgit_persistence=>ty_repo-package . METHODS get_local_settings RETURNING VALUE(rs_settings) TYPE zif_abapgit_persistence=>ty_repo-local_settings . METHODS get_tadir_objects RETURNING VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . METHODS get_files_local_filtered IMPORTING !ii_obj_filter TYPE REF TO zif_abapgit_object_filter !ii_log TYPE REF TO zif_abapgit_log OPTIONAL RETURNING VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt RAISING zcx_abapgit_exception . METHODS get_files_local IMPORTING !ii_log TYPE REF TO zif_abapgit_log OPTIONAL RETURNING VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt RAISING zcx_abapgit_exception . METHODS get_files_remote IMPORTING !ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL !iv_ignore_files TYPE abap_bool DEFAULT abap_false PREFERRED PARAMETER ii_obj_filter RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . METHODS refresh IMPORTING !iv_drop_cache TYPE abap_bool DEFAULT abap_false !iv_drop_log TYPE abap_bool DEFAULT abap_true PREFERRED PARAMETER iv_drop_cache RAISING zcx_abapgit_exception . METHODS get_dot_abapgit RETURNING VALUE(ro_dot_abapgit) TYPE REF TO zcl_abapgit_dot_abapgit . METHODS set_dot_abapgit IMPORTING !io_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit RAISING zcx_abapgit_exception . METHODS find_remote_dot_abapgit RETURNING VALUE(ro_dot) TYPE REF TO zcl_abapgit_dot_abapgit RAISING zcx_abapgit_exception . METHODS deserialize IMPORTING !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks !ii_log TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . METHODS deserialize_checks RETURNING VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks RAISING zcx_abapgit_exception . METHODS checksums RETURNING VALUE(ri_checksums) TYPE REF TO zif_abapgit_repo_checksums RAISING zcx_abapgit_exception . METHODS has_remote_source RETURNING VALUE(rv_yes) TYPE abap_bool . ENDINTERFACE. INTERFACE zif_abapgit_repo_checksums. METHODS get RETURNING VALUE(rt_checksums) TYPE zif_abapgit_persistence=>ty_local_checksum_tt. METHODS get_checksums_per_file RETURNING VALUE(rt_checksums) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt . METHODS rebuild RAISING zcx_abapgit_exception. METHODS update IMPORTING !it_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_repo_listener . METHODS on_meta_change IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !is_meta TYPE zif_abapgit_persistence=>ty_repo_xml !is_change_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_repo_online. INTERFACES zif_abapgit_repo. METHODS get_url RETURNING VALUE(rv_url) TYPE zif_abapgit_persistence=>ty_repo-url . METHODS get_selected_branch RETURNING VALUE(rv_name) TYPE zif_abapgit_persistence=>ty_repo-branch_name . METHODS set_url IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url RAISING zcx_abapgit_exception . METHODS select_branch IMPORTING !iv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name RAISING zcx_abapgit_exception . METHODS get_selected_commit RETURNING VALUE(rv_selected_commit) TYPE zif_abapgit_persistence=>ty_repo-selected_commit RAISING zcx_abapgit_exception . METHODS get_current_remote RETURNING VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . METHODS select_commit IMPORTING !iv_selected_commit TYPE zif_abapgit_persistence=>ty_repo-selected_commit RAISING zcx_abapgit_exception . METHODS switch_origin IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url !iv_branch TYPE zif_abapgit_persistence=>ty_repo-branch_name OPTIONAL !iv_overwrite TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . METHODS get_switched_origin RETURNING VALUE(rv_switched_origin) TYPE zif_abapgit_persistence=>ty_repo-switched_origin. METHODS push IMPORTING !is_comment TYPE zif_abapgit_git_definitions=>ty_comment !io_stage TYPE REF TO zcl_abapgit_stage RAISING zcx_abapgit_exception . METHODS create_branch IMPORTING !iv_name TYPE string !iv_from TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL RAISING zcx_abapgit_exception . METHODS check_for_valid_branch RAISING zcx_abapgit_exception . ENDINTERFACE. INTERFACE zif_abapgit_repo_srv . TYPES: ty_repo_list TYPE STANDARD TABLE OF REF TO zif_abapgit_repo WITH DEFAULT KEY, BEGIN OF ty_label, label TYPE string, END OF ty_label, ty_labels TYPE STANDARD TABLE OF ty_label WITH NON-UNIQUE DEFAULT KEY WITH NON-UNIQUE SORTED KEY key_label COMPONENTS label. METHODS init. METHODS delete IMPORTING !ii_repo TYPE REF TO zif_abapgit_repo RAISING zcx_abapgit_exception . METHODS get IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_value RETURNING VALUE(ri_repo) TYPE REF TO zif_abapgit_repo RAISING zcx_abapgit_exception . METHODS is_repo_installed IMPORTING !iv_url TYPE string !iv_target_package TYPE devclass OPTIONAL RETURNING VALUE(rv_installed) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS list IMPORTING !iv_offline TYPE abap_bool DEFAULT abap_undefined RETURNING VALUE(rt_list) TYPE ty_repo_list RAISING zcx_abapgit_exception . METHODS list_favorites IMPORTING !iv_offline TYPE abap_bool DEFAULT abap_undefined RETURNING VALUE(rt_list) TYPE ty_repo_list RAISING zcx_abapgit_exception . METHODS new_offline IMPORTING !iv_name TYPE string !iv_package TYPE devclass !iv_folder_logic TYPE string DEFAULT zif_abapgit_dot_abapgit=>c_folder_logic-full !iv_labels TYPE string OPTIONAL !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false !iv_main_lang_only TYPE abap_bool DEFAULT abap_false !iv_abap_lang_vers TYPE string OPTIONAL RETURNING VALUE(ri_repo) TYPE REF TO zif_abapgit_repo RAISING zcx_abapgit_exception . METHODS new_online IMPORTING !iv_url TYPE string !iv_branch_name TYPE string OPTIONAL !iv_display_name TYPE string OPTIONAL !iv_name TYPE string OPTIONAL !iv_package TYPE devclass !iv_folder_logic TYPE string DEFAULT zif_abapgit_dot_abapgit=>c_folder_logic-prefix !iv_labels TYPE string OPTIONAL !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false !iv_main_lang_only TYPE abap_bool DEFAULT abap_false !iv_abap_lang_vers TYPE string OPTIONAL RETURNING VALUE(ri_repo) TYPE REF TO zif_abapgit_repo RAISING zcx_abapgit_exception . METHODS purge IMPORTING !ii_repo TYPE REF TO zif_abapgit_repo !is_checks TYPE zif_abapgit_definitions=>ty_delete_checks !iv_keep_repo TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . METHODS validate_package IMPORTING !iv_package TYPE devclass !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false !iv_chk_exists TYPE abap_bool DEFAULT abap_true RAISING zcx_abapgit_exception . METHODS validate_url IMPORTING !iv_url TYPE string !iv_chk_exists TYPE abap_bool DEFAULT abap_true RAISING zcx_abapgit_exception . METHODS get_repo_from_package IMPORTING !iv_package TYPE devclass !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false EXPORTING VALUE(ei_repo) TYPE REF TO zif_abapgit_repo !ev_reason TYPE string RAISING zcx_abapgit_exception . METHODS get_repo_from_url IMPORTING !iv_url TYPE string EXPORTING !ei_repo TYPE REF TO zif_abapgit_repo !ev_reason TYPE string RAISING zcx_abapgit_exception . METHODS get_label_list RETURNING VALUE(rt_labels) TYPE ty_labels RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_gui_page_flow . TYPES: BEGIN OF ty_path_name, path TYPE string, filename TYPE string, remote_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, local_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, END OF ty_path_name. TYPES: ty_path_name_tt TYPE HASHED TABLE OF ty_path_name WITH UNIQUE KEY path filename. TYPES: BEGIN OF ty_feature, BEGIN OF repo, name TYPE string, key TYPE zif_abapgit_persistence=>ty_repo-key, package TYPE devclass, END OF repo, BEGIN OF branch, display_name TYPE string, sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, up_to_date TYPE abap_bool, END OF branch, BEGIN OF pr, title TYPE string, url TYPE string, draft TYPE abap_bool, END OF pr, BEGIN OF transport, trkorr TYPE trkorr, title TYPE string, END OF transport, full_match TYPE abap_bool, changed_files TYPE ty_path_name_tt, changed_objects TYPE zif_abapgit_definitions=>ty_items_ts, END OF ty_feature. TYPES ty_features TYPE STANDARD TABLE OF ty_feature WITH DEFAULT KEY. ENDINTERFACE. INTERFACE zif_abapgit_flow_exit . METHODS toolbar_extras IMPORTING !io_toolbar TYPE REF TO zcl_abapgit_html_toolbar !is_feature TYPE zif_abapgit_gui_page_flow=>ty_feature !iv_index TYPE i . TYPES: BEGIN OF ty_event_result, handled TYPE zif_abapgit_gui_event_handler=>ty_handling_result, refresh TYPE abap_bool, END OF ty_event_result. METHODS on_event IMPORTING ii_event TYPE REF TO zif_abapgit_gui_event it_features TYPE zif_abapgit_gui_page_flow=>ty_features RETURNING VALUE(rs_result) TYPE ty_event_result RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_services_git. TYPES: BEGIN OF ty_commit_fields, repo_key TYPE zif_abapgit_persistence=>ty_repo-key, committer_name TYPE string, committer_email TYPE string, author_name TYPE string, author_email TYPE string, comment TYPE string, body TYPE string, END OF ty_commit_fields. ENDINTERFACE. INTERFACE zif_abapgit_popups . TYPES ty_rows TYPE SORTED TABLE OF i WITH UNIQUE KEY table_line. TYPES: BEGIN OF ty_alv_column, name TYPE string, text TYPE string, length TYPE lvc_outlen, show_icon TYPE abap_bool, center TYPE abap_bool, END OF ty_alv_column, ty_alv_column_tt TYPE TABLE OF ty_alv_column WITH DEFAULT KEY. TYPES: BEGIN OF ty_popup_position, start_column LIKE sy-cucol, start_row LIKE sy-curow, end_column LIKE sy-cucol, end_row LIKE sy-curow, END OF ty_popup_position. CONSTANTS c_new_branch_label TYPE string VALUE '+ create new ...' ##NO_TEXT. METHODS popup_search_help IMPORTING !iv_tab_field TYPE string RETURNING VALUE(rv_value) TYPE ddshretval-fieldval RAISING zcx_abapgit_exception . METHODS popup_folder_logic RETURNING VALUE(rv_folder_logic) TYPE string RAISING zcx_abapgit_exception . METHODS create_branch_popup IMPORTING !iv_source_branch_name TYPE string EXPORTING !ev_name TYPE string !ev_cancel TYPE abap_bool RAISING zcx_abapgit_exception . METHODS branch_list_popup IMPORTING !iv_url TYPE string !iv_default_branch TYPE string OPTIONAL !iv_show_new_option TYPE abap_bool OPTIONAL !iv_hide_branch TYPE zif_abapgit_persistence=>ty_repo-branch_name OPTIONAL !iv_hide_head TYPE abap_bool OPTIONAL RETURNING VALUE(rs_branch) TYPE zif_abapgit_git_definitions=>ty_git_branch RAISING zcx_abapgit_exception . METHODS tag_list_popup IMPORTING !iv_url TYPE string RETURNING VALUE(rs_tag) TYPE zif_abapgit_git_definitions=>ty_git_tag RAISING zcx_abapgit_exception . METHODS commit_list_popup IMPORTING !iv_repo_url TYPE string !iv_branch_name TYPE string OPTIONAL RETURNING VALUE(rs_commit) TYPE zif_abapgit_git_definitions=>ty_commit RAISING zcx_abapgit_exception . TYPES ty_char1 TYPE c LENGTH 1. TYPES ty_icon TYPE c LENGTH 30. METHODS popup_to_confirm IMPORTING !iv_titlebar TYPE clike !iv_text_question TYPE clike !iv_text_button_1 TYPE clike DEFAULT 'Yes' !iv_icon_button_1 TYPE ty_icon DEFAULT space !iv_text_button_2 TYPE clike DEFAULT 'No' !iv_icon_button_2 TYPE ty_icon DEFAULT space !iv_default_button TYPE ty_char1 DEFAULT '1' !iv_display_cancel_button TYPE ty_char1 DEFAULT abap_true !iv_popup_type TYPE clike DEFAULT 'ICON_MESSAGE_QUESTION' RETURNING VALUE(rv_answer) TYPE ty_char1 RAISING zcx_abapgit_exception . METHODS popup_to_create_package IMPORTING is_package_data TYPE zif_abapgit_sap_package=>ty_create OPTIONAL EXPORTING !es_package_data TYPE zif_abapgit_sap_package=>ty_create !ev_create TYPE abap_bool RAISING zcx_abapgit_exception . METHODS popup_to_create_transp_branch IMPORTING !iv_trkorr TYPE trkorr RETURNING VALUE(rs_transport_branch) TYPE zif_abapgit_definitions=>ty_transport_to_branch RAISING zcx_abapgit_exception . METHODS popup_to_select_transport RETURNING VALUE(rv_trkorr) TYPE trkorr . METHODS popup_to_select_from_list IMPORTING !it_list TYPE STANDARD TABLE !iv_title TYPE lvc_title DEFAULT space !iv_header_text TYPE csequence DEFAULT space !iv_start_column TYPE i DEFAULT 10 !iv_end_column TYPE i DEFAULT 125 !iv_start_line TYPE i DEFAULT 10 !iv_end_line TYPE i DEFAULT 30 !iv_striped_pattern TYPE abap_bool DEFAULT abap_false !iv_optimize_col_width TYPE abap_bool DEFAULT abap_true !iv_selection_mode TYPE salv_de_constant DEFAULT if_salv_c_selection_mode=>multiple !iv_select_column_text TYPE csequence DEFAULT space !it_columns_to_display TYPE ty_alv_column_tt !it_preselected_rows TYPE ty_rows OPTIONAL EXPORTING VALUE(et_list) TYPE STANDARD TABLE RAISING zcx_abapgit_exception . METHODS popup_transport_request IMPORTING !is_transport_type TYPE zif_abapgit_definitions=>ty_transport_type OPTIONAL !iv_use_default_transport TYPE abap_bool DEFAULT abap_false PREFERRED PARAMETER is_transport_type RETURNING VALUE(rv_transport) TYPE trkorr RAISING zcx_abapgit_exception . METHODS popup_select_tr_requests IMPORTING is_selection TYPE trwbo_selection iv_title TYPE trwbo_title iv_username_pattern TYPE any DEFAULT sy-uname RETURNING VALUE(rt_r_trkorr) TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt RAISING zcx_abapgit_exception. METHODS popup_select_wb_tc_tr_and_tsk RETURNING VALUE(rt_r_trkorr) TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt RAISING zcx_abapgit_exception. METHODS popup_to_select_labels IMPORTING iv_labels TYPE string OPTIONAL RETURNING VALUE(rv_labels) TYPE string RAISING zcx_abapgit_exception. METHODS choose_code_insp_check_variant RETURNING VALUE(rv_check_variant) TYPE sci_chkv RAISING zcx_abapgit_exception. ENDINTERFACE. INTERFACE zif_abapgit_log . CONSTANTS: BEGIN OF c_status, ok TYPE sy-msgty VALUE 'S', error TYPE sy-msgty VALUE 'E', warning TYPE sy-msgty VALUE 'W', END OF c_status. CONSTANTS: BEGIN OF c_log_level, empty TYPE i VALUE 0, info TYPE i VALUE 1, warning TYPE i VALUE 2, error TYPE i VALUE 3, END OF c_log_level. TYPES: BEGIN OF ty_log_out, type TYPE sy-msgty, text TYPE string, obj_type TYPE tadir-object, obj_name TYPE tadir-obj_name, exception TYPE REF TO cx_root, END OF ty_log_out . TYPES: ty_log_outs TYPE STANDARD TABLE OF ty_log_out WITH NON-UNIQUE DEFAULT KEY . TYPES: BEGIN OF ty_msg, text TYPE string, type TYPE sy-msgty, level TYPE i, END OF ty_msg . TYPES: ty_msgs TYPE STANDARD TABLE OF ty_msg WITH NON-UNIQUE DEFAULT KEY . TYPES: BEGIN OF ty_item_status_out, item TYPE zif_abapgit_definitions=>ty_item, status TYPE sy-msgty, messages TYPE ty_msgs, END OF ty_item_status_out . TYPES: ty_item_status_outs TYPE SORTED TABLE OF ty_item_status_out WITH UNIQUE KEY item-obj_type item-obj_name . METHODS add IMPORTING !iv_msg TYPE csequence !iv_type TYPE sy-msgty DEFAULT 'E' !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL !ix_exc TYPE REF TO cx_root OPTIONAL . METHODS add_error IMPORTING !iv_msg TYPE csequence !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . METHODS add_info IMPORTING !iv_msg TYPE csequence !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . METHODS add_warning IMPORTING !iv_msg TYPE csequence !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . METHODS add_success IMPORTING !iv_msg TYPE csequence !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . METHODS add_exception IMPORTING !ix_exc TYPE REF TO cx_root !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL . METHODS clear . METHODS count RETURNING VALUE(rv_count) TYPE i . METHODS get_messages RETURNING VALUE(rt_msg) TYPE ty_log_outs . METHODS get_item_status RETURNING VALUE(rt_item_status) TYPE ty_item_status_outs . METHODS get_status RETURNING VALUE(rv_status) TYPE sy-msgty . METHODS get_log_level RETURNING VALUE(rv_level) TYPE i . METHODS get_title RETURNING VALUE(rv_title) TYPE string . METHODS set_title IMPORTING !iv_title TYPE csequence RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log. METHODS merge_with IMPORTING ii_log TYPE REF TO zif_abapgit_log iv_min_level TYPE i DEFAULT 0 RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log. METHODS clone RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log. ENDINTERFACE. INTERFACE zif_abapgit_xml_input . METHODS read IMPORTING !iv_name TYPE clike CHANGING !cg_data TYPE any RAISING zcx_abapgit_exception . METHODS get_raw RETURNING VALUE(ri_raw) TYPE REF TO if_ixml_document . * todo, add read_xml to match add_xml in lcl_xml_output METHODS get_metadata RETURNING VALUE(rs_metadata) TYPE zif_abapgit_definitions=>ty_metadata . ENDINTERFACE. INTERFACE zif_abapgit_xml_output . METHODS add IMPORTING !iv_name TYPE clike !ig_data TYPE any RAISING zcx_abapgit_exception . METHODS set_raw IMPORTING !ii_raw TYPE REF TO if_ixml_element . METHODS add_xml IMPORTING !iv_name TYPE clike !ii_xml TYPE REF TO if_ixml_element . METHODS render IMPORTING !iv_normalize TYPE abap_bool DEFAULT abap_true !is_metadata TYPE zif_abapgit_definitions=>ty_metadata OPTIONAL RETURNING VALUE(rv_xml) TYPE string . ENDINTERFACE. INTERFACE zif_abapgit_version . CONSTANTS c_xml_version TYPE string VALUE 'v1.0.0' ##NO_TEXT. CONSTANTS c_abap_version TYPE string VALUE '1.128.0' ##NO_TEXT. ENDINTERFACE. CLASS zcl_abapgit_apack_helper DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS are_dependencies_met IMPORTING !it_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies RETURNING VALUE(rv_status) TYPE zif_abapgit_definitions=>ty_yes_no RAISING zcx_abapgit_exception . CLASS-METHODS dependencies_popup IMPORTING !it_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies RAISING zcx_abapgit_exception . CLASS-METHODS to_file IMPORTING !iv_package TYPE devclass RETURNING VALUE(rs_file) TYPE zif_abapgit_git_definitions=>ty_file RAISING zcx_abapgit_exception . CLASS-METHODS get_manifest_implementations RETURNING VALUE(rt_manifest_implementations) TYPE zif_abapgit_apack_definitions=>ty_manifest_declarations. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_dependency_status, met TYPE zif_abapgit_definitions=>ty_yes_no_partial. INCLUDE TYPE zif_abapgit_apack_definitions=>ty_dependency. TYPES: END OF ty_dependency_status . TYPES: ty_dependency_statuses TYPE STANDARD TABLE OF ty_dependency_status WITH NON-UNIQUE DEFAULT KEY . TYPES: BEGIN OF ty_color_line, exception(1) TYPE c, color TYPE lvc_t_scol. INCLUDE TYPE ty_dependency_status. TYPES: t_hyperlink TYPE salv_t_int4_column, END OF ty_color_line. TYPES: ty_color_tab TYPE STANDARD TABLE OF ty_color_line WITH DEFAULT KEY. CLASS-METHODS get_dependencies_met_status IMPORTING !it_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies RETURNING VALUE(rt_status) TYPE ty_dependency_statuses RAISING zcx_abapgit_exception . CLASS-METHODS get_installed_packages RETURNING VALUE(rt_packages) TYPE zif_abapgit_apack_definitions=>ty_descriptors RAISING zcx_abapgit_exception . CLASS-METHODS show_dependencies_popup IMPORTING !it_dependencies TYPE ty_dependency_statuses RAISING zcx_abapgit_exception . CLASS-METHODS get_color_table IMPORTING !io_alv TYPE REF TO cl_salv_table !it_dependencies TYPE ty_dependency_statuses CHANGING !ct_color_table TYPE ty_color_tab RAISING cx_salv_existing. ENDCLASS. CLASS zcl_abapgit_apack_migration DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. CONSTANTS: c_apack_interface_version TYPE i VALUE 1. CLASS-METHODS: run RAISING zcx_abapgit_exception. METHODS: perform_migration RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. METHODS interface_exists RETURNING VALUE(rv_interface_exists) TYPE abap_bool . METHODS interface_valid RETURNING VALUE(rv_interface_valid) TYPE abap_bool . METHODS create_interface RAISING zcx_abapgit_exception . METHODS add_interface_source_classic IMPORTING !is_clskey TYPE seoclskey RAISING zcx_abapgit_exception . METHODS add_interface_source IMPORTING !is_clskey TYPE seoclskey RAISING zcx_abapgit_exception . METHODS get_interface_source RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt . METHODS add_intf_source_and_activate RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_apack_reader DEFINITION FINAL CREATE PRIVATE . PUBLIC SECTION. TYPES ty_package_name TYPE devclass . CLASS-METHODS create_instance IMPORTING !iv_package_name TYPE ty_package_name RETURNING VALUE(ro_manifest_reader) TYPE REF TO zcl_abapgit_apack_reader . CLASS-METHODS deserialize IMPORTING !iv_package_name TYPE ty_package_name !iv_xstr TYPE xstring RETURNING VALUE(ro_manifest_reader) TYPE REF TO zcl_abapgit_apack_reader RAISING zcx_abapgit_exception. METHODS get_manifest_descriptor RETURNING VALUE(rs_manifest_descriptor) TYPE zif_abapgit_apack_definitions=>ty_descriptor RAISING zcx_abapgit_exception. METHODS set_manifest_descriptor IMPORTING !is_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor RAISING zcx_abapgit_exception. METHODS copy_manifest_descriptor IMPORTING !io_manifest_provider TYPE REF TO object RAISING zcx_abapgit_exception. METHODS has_manifest RETURNING VALUE(rv_has_manifest) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !iv_package_name TYPE ty_package_name . METHODS refresh. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_instance, package TYPE ty_package_name, instance TYPE REF TO zcl_abapgit_apack_reader, END OF ty_instance, ty_instances TYPE HASHED TABLE OF ty_instance WITH UNIQUE KEY package. CLASS-DATA gt_instances TYPE ty_instances. DATA mv_package_name TYPE ty_package_name . DATA ms_cached_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor . DATA mv_is_cached TYPE abap_bool . CLASS-METHODS from_xml IMPORTING iv_xml TYPE string RETURNING VALUE(rs_data) TYPE zif_abapgit_apack_definitions=>ty_descriptor. METHODS format_version RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_apack_writer DEFINITION FINAL CREATE PRIVATE . PUBLIC SECTION. CLASS-METHODS create_instance IMPORTING !is_apack_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor RETURNING VALUE(ro_manifest_writer) TYPE REF TO zcl_abapgit_apack_writer . METHODS serialize RETURNING VALUE(rv_xml) TYPE string RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !is_apack_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor . PROTECTED SECTION. PRIVATE SECTION. DATA ms_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor . ENDCLASS. CLASS zcl_abapgit_background DEFINITION CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_method, class TYPE seoclsname, description TYPE string, END OF ty_method. TYPES: ty_methods TYPE SORTED TABLE OF ty_method WITH UNIQUE KEY class. CLASS-METHODS run RAISING zcx_abapgit_exception . CLASS-METHODS list_methods RETURNING VALUE(rt_methods) TYPE ty_methods. CLASS-METHODS enqueue RAISING zcx_abapgit_exception. CLASS-METHODS dequeue. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_enq_type TYPE c LENGTH 12 VALUE 'BACKGROUND'. ENDCLASS. CLASS zcl_abapgit_background_pull DEFINITION CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_background . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_background_push_au DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_background . PROTECTED SECTION. DATA mi_log TYPE REF TO zif_abapgit_log . METHODS build_comment IMPORTING !is_files TYPE zif_abapgit_definitions=>ty_stage_files RETURNING VALUE(rv_comment) TYPE string . METHODS push_auto IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online RAISING zcx_abapgit_exception . METHODS determine_user_details IMPORTING !iv_changed_by TYPE syuname RETURNING VALUE(rs_user) TYPE zif_abapgit_git_definitions=>ty_git_user . METHODS push_deletions IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online !is_files TYPE zif_abapgit_definitions=>ty_stage_files RAISING zcx_abapgit_exception . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_background_push_fi DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_background . PROTECTED SECTION. CONSTANTS: BEGIN OF c_settings, name TYPE string VALUE 'NAME', email TYPE string VALUE 'EMAIL', END OF c_settings . DATA mi_log TYPE REF TO zif_abapgit_log . METHODS build_comment IMPORTING !is_files TYPE zif_abapgit_definitions=>ty_stage_files RETURNING VALUE(rv_comment) TYPE string . METHODS push_fixed IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online !iv_name TYPE string !iv_email TYPE string RAISING zcx_abapgit_exception . PRIVATE SECTION. ENDCLASS. "! Change transport system API CLASS zcl_abapgit_cts_api DEFINITION FINAL CREATE PRIVATE FRIENDS ZCL_ABAPGIT_factory. PUBLIC SECTION. INTERFACES: zif_abapgit_cts_api. PROTECTED SECTION. PRIVATE SECTION. DATA mv_confirm_transp_msgs_called TYPE abap_bool. "! Returns the transport request / task the object is currently locked in "! @parameter iv_program_id | Program ID "! @parameter iv_object_type | Object type "! @parameter iv_object_name | Object name "! @parameter rv_transport | Transport request / task "! @raising zcx_abapgit_exception | Object is not locked in a transport METHODS get_current_transport_for_obj IMPORTING !iv_program_id TYPE pgmid DEFAULT 'R3TR' !iv_object_type TYPE trobjtype !iv_object_name TYPE sobj_name RETURNING VALUE(rv_transport) TYPE trkorr RAISING zcx_abapgit_exception . "! Returns the transport request / task that includes the object (even if not locked) "! @parameter iv_program_id | Program ID "! @parameter iv_object_type | Object type "! @parameter iv_object_name | Object name "! @parameter rv_transport | Transport request / task "! @raising zcx_abapgit_exception | Object is not locked in a transport METHODS get_current_transport_from_db IMPORTING !iv_program_id TYPE pgmid DEFAULT 'R3TR' !iv_object_type TYPE trobjtype !iv_object_name TYPE sobj_name RETURNING VALUE(rv_transport) TYPE trkorr RAISING zcx_abapgit_exception . "! Check if the object is currently locked in a transport "! @parameter iv_program_id | Program ID "! @parameter iv_object_type | Object type "! @parameter iv_object_name | Object name "! @parameter rv_locked | Object is locked "! @raising zcx_abapgit_exception | Object type is not lockable METHODS is_object_locked_in_transport IMPORTING !iv_program_id TYPE pgmid DEFAULT 'R3TR' !iv_object_type TYPE trobjtype !iv_object_name TYPE sobj_name RETURNING VALUE(rv_locked) TYPE abap_bool RAISING zcx_abapgit_exception . "! Check if the object type is lockable "! @parameter iv_program_id | Program ID "! @parameter iv_object_type | Object type "! @parameter rv_lockable | Lockable METHODS is_object_type_lockable IMPORTING !iv_program_id TYPE pgmid DEFAULT 'R3TR' !iv_object_type TYPE trobjtype RETURNING VALUE(rv_lockable) TYPE abap_bool . "! Check if the object type can be transported "! @parameter iv_program_id | Program ID "! @parameter iv_object_type | Object type "! @parameter rv_transportable | Transportable METHODS is_object_type_transportable IMPORTING !iv_program_id TYPE pgmid DEFAULT 'R3TR' !iv_object_type TYPE trobjtype RETURNING VALUE(rv_transportable) TYPE abap_bool . ENDCLASS. CLASS zcl_abapgit_default_transport DEFINITION CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_default_transport. METHODS constructor RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mv_is_set_by_abapgit TYPE abap_bool . DATA ms_save TYPE e070use . METHODS store RAISING zcx_abapgit_exception . METHODS restore RAISING zcx_abapgit_exception . METHODS set_internal IMPORTING !iv_transport TYPE trkorr RAISING zcx_abapgit_exception . METHODS clear IMPORTING !is_default_task TYPE e070use RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_transport DEFINITION CREATE PUBLIC . PUBLIC SECTION. * todo, add interfaces for this class, consider merging zcl_abapgit_transport_mass into this class? CLASS-METHODS zip IMPORTING !iv_show_log_popup TYPE abap_bool DEFAULT abap_true !iv_logic TYPE string OPTIONAL !is_trkorr TYPE trwbo_request_header OPTIONAL RETURNING VALUE(rv_xstr) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS to_tadir IMPORTING !iv_trkorr TYPE trkorr !iv_deleted_objects TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . CLASS-METHODS add_all_objects_to_trans_req IMPORTING iv_key TYPE zif_abapgit_persistence=>ty_value RAISING zcx_abapgit_exception . PROTECTED SECTION. TYPES ty_trkorr_tt TYPE STANDARD TABLE OF trkorr. CLASS-METHODS read_requests IMPORTING !it_trkorr TYPE ty_trkorr_tt RETURNING VALUE(rt_requests) TYPE trwbo_requests RAISING zcx_abapgit_exception . CLASS-METHODS find_top_package IMPORTING !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RETURNING VALUE(rv_package) TYPE devclass RAISING zcx_abapgit_exception . CLASS-METHODS resolve IMPORTING !it_requests TYPE trwbo_requests !iv_deleted_objects TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . PRIVATE SECTION. CLASS-METHODS collect_all_objects IMPORTING iv_key TYPE zif_abapgit_persistence=>ty_value RETURNING VALUE(rt_objects) TYPE tr_objects RAISING zcx_abapgit_exception. CLASS-METHODS show_log IMPORTING it_log TYPE sprot_u_tab iv_title TYPE string. ENDCLASS. CLASS zcl_abapgit_transport_2_branch DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS create IMPORTING !io_repository TYPE REF TO zcl_abapgit_repo_online !is_transport_to_branch TYPE zif_abapgit_definitions=>ty_transport_to_branch !it_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . PROTECTED SECTION. METHODS generate_commit_message IMPORTING !is_transport_to_branch TYPE zif_abapgit_definitions=>ty_transport_to_branch RETURNING VALUE(rs_comment) TYPE zif_abapgit_git_definitions=>ty_comment . METHODS stage_transport_objects IMPORTING !it_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt !io_stage TYPE REF TO zcl_abapgit_stage !is_stage_objects TYPE zif_abapgit_definitions=>ty_stage_files !it_object_statuses TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_transport_mass DEFINITION INHERITING FROM zcl_abapgit_transport FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS run . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_transport_objects DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING !it_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt . METHODS to_stage IMPORTING !io_stage TYPE REF TO zcl_abapgit_stage !is_stage_objects TYPE zif_abapgit_definitions=>ty_stage_files !it_object_statuses TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. DATA mt_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt . ENDCLASS. CLASS zcl_abapgit_data_config DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_data_config . PROTECTED SECTION. PRIVATE SECTION. DATA mt_config TYPE zif_abapgit_data_config=>ty_config_tt . METHODS dump IMPORTING !is_config TYPE zif_abapgit_data_config=>ty_config RETURNING VALUE(rv_json) TYPE xstring RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_data_deserializer DEFINITION CREATE PRIVATE FRIENDS ZCL_ABAPGIT_data_factory . PUBLIC SECTION. INTERFACES zif_abapgit_data_deserializer . PROTECTED SECTION. PRIVATE SECTION. METHODS convert_json_to_itab IMPORTING !is_file TYPE zif_abapgit_git_definitions=>ty_file !ir_data TYPE REF TO data RAISING zcx_abapgit_exception . METHODS preview_database_changes IMPORTING !iv_name TYPE tadir-obj_name !ir_lc_data TYPE REF TO data !ir_db_data TYPE REF TO data RETURNING VALUE(rs_result) TYPE zif_abapgit_data_deserializer=>ty_result RAISING zcx_abapgit_exception. METHODS write_database_table IMPORTING !iv_name TYPE tadir-obj_name !ir_del TYPE REF TO data !ir_ins TYPE REF TO data !ir_upd TYPE REF TO data RAISING zcx_abapgit_exception . METHODS read_database_table IMPORTING !iv_name TYPE tadir-obj_name !it_where TYPE string_table RETURNING VALUE(rr_data) TYPE REF TO data RAISING zcx_abapgit_exception . METHODS determine_transport_request IMPORTING io_repo TYPE REF TO zcl_abapgit_repo iv_transport_type TYPE zif_abapgit_definitions=>ty_transport_type RETURNING VALUE(rv_transport_request) TYPE trkorr. METHODS is_table_allowed_to_edit IMPORTING !is_result TYPE zif_abapgit_data_deserializer=>ty_result RETURNING VALUE(rv_allowed_to_edit) TYPE abap_bool . ENDCLASS. CLASS zcl_abapgit_data_factory DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS get_supporter RETURNING VALUE(ri_supporter) TYPE REF TO zif_abapgit_data_supporter . CLASS-METHODS get_serializer RETURNING VALUE(ri_serializer) TYPE REF TO zif_abapgit_data_serializer . CLASS-METHODS get_deserializer RETURNING VALUE(ri_deserializer) TYPE REF TO zif_abapgit_data_deserializer . CLASS-METHODS get_config RETURNING VALUE(ri_config) TYPE REF TO zif_abapgit_data_config . PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gi_supporter TYPE REF TO zif_abapgit_data_supporter . CLASS-DATA gi_serializer TYPE REF TO zif_abapgit_data_serializer . CLASS-DATA gi_deserializer TYPE REF TO zif_abapgit_data_deserializer . ENDCLASS. CLASS zcl_abapgit_data_serializer DEFINITION CREATE PRIVATE FRIENDS ZCL_ABAPGIT_data_factory . PUBLIC SECTION. INTERFACES zif_abapgit_data_serializer . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_max_records TYPE i VALUE 20000 ##NO_TEXT. METHODS convert_itab_to_json IMPORTING !ir_data TYPE REF TO data !iv_skip_initial TYPE abap_bool RETURNING VALUE(rv_data) TYPE xstring RAISING zcx_abapgit_exception . METHODS read_database_table IMPORTING !iv_name TYPE tadir-obj_name !it_where TYPE string_table RETURNING VALUE(rr_data) TYPE REF TO data RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_data_supporter DEFINITION CREATE PRIVATE FRIENDS ZCL_ABAPGIT_data_factory . PUBLIC SECTION. INTERFACES zif_abapgit_data_supporter. PROTECTED SECTION. PRIVATE SECTION. DATA mt_supported_objects TYPE zif_abapgit_data_supporter=>ty_objects. METHODS get_supported_objects. ENDCLASS. CLASS zcl_abapgit_data_utils DEFINITION CREATE PUBLIC. PUBLIC SECTION. TYPES ty_names TYPE STANDARD TABLE OF abap_compname WITH DEFAULT KEY . CLASS-METHODS build_table_itab IMPORTING !iv_name TYPE tadir-obj_name RETURNING VALUE(rr_data) TYPE REF TO data RAISING zcx_abapgit_exception. CLASS-METHODS build_data_filename IMPORTING !is_config TYPE zif_abapgit_data_config=>ty_config RETURNING VALUE(rv_filename) TYPE string. CLASS-METHODS build_config_filename IMPORTING !is_config TYPE zif_abapgit_data_config=>ty_config RETURNING VALUE(rv_filename) TYPE string. CLASS-METHODS jump IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RAISING zcx_abapgit_exception. CLASS-METHODS does_table_exist IMPORTING !iv_name TYPE tadir-obj_name RETURNING VALUE(rv_exists) TYPE abap_bool. CLASS-METHODS is_customizing_table IMPORTING !iv_name TYPE tadir-obj_name RETURNING VALUE(rv_customizing) TYPE abap_bool. CLASS-METHODS list_key_fields IMPORTING !iv_name TYPE tadir-obj_name RETURNING VALUE(rt_names) TYPE ty_names RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_abap_language_vers DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. CONSTANTS: c_any_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version VALUE '*', c_no_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version VALUE '-', c_feature_flag TYPE string VALUE 'ALAV'. METHODS constructor IMPORTING !io_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit. METHODS get_abap_language_vers_by_objt IMPORTING !iv_object_type TYPE trobjtype !iv_package TYPE devclass RETURNING VALUE(rv_allowed_abap_langu_version) TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version. METHODS get_repo_abap_language_version RETURNING VALUE(rv_abap_language_version) TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version. METHODS is_import_allowed IMPORTING !iv_package TYPE devclass RETURNING VALUE(rv_allowed) TYPE abap_bool. CLASS-METHODS check_abap_language_version IMPORTING !iv_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version !is_item TYPE zif_abapgit_definitions=>ty_item RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit. " Depends on experimental feature flag and repo setting DATA mv_has_abap_language_vers TYPE abap_bool. METHODS get_default_abap_language_vers IMPORTING !iv_object_type TYPE trobjtype RETURNING VALUE(rv_abap_language_version) TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version. METHODS get_abap_language_vers_by_devc IMPORTING !iv_package TYPE devclass RETURNING VALUE(rv_abap_language_version) TYPE string. METHODS get_abap_language_vers_by_repo RETURNING VALUE(rv_abap_language_version) TYPE string. CLASS-METHODS get_description IMPORTING !iv_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version RETURNING VALUE(rv_description) TYPE string. ENDCLASS. CLASS zcl_abapgit_environment DEFINITION FINAL CREATE PRIVATE FRIENDS ZCL_ABAPGIT_factory . PUBLIC SECTION. INTERFACES zif_abapgit_environment . PROTECTED SECTION. PRIVATE SECTION. DATA mv_cloud TYPE abap_bool VALUE abap_undefined ##NO_TEXT. DATA mv_is_merged TYPE abap_bool VALUE abap_undefined ##NO_TEXT. DATA mv_modifiable TYPE abap_bool VALUE abap_undefined ##NO_TEXT. METHODS is_system_changes_allowed RETURNING VALUE(rv_result) TYPE abap_bool . ENDCLASS. CLASS zcl_abapgit_feature DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. " For dependency injection/testing, use the following " zcl_abapgit_persist_factory=>get_settings( )->read( )->set_experimental_features( ) CLASS-METHODS is_enabled IMPORTING !iv_feature TYPE string OPTIONAL RETURNING VALUE(rv_run) TYPE abap_bool. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. *----------------------------------------------------------------------* * This helper class is used to set and restore the current language. * As some of the SAP functions used rely on SY-LANGU containing the * main language, this class is used to temporarily change and then * restore the value of SY-LANGU. *----------------------------------------------------------------------* CLASS zcl_abapgit_language DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS class_constructor . CLASS-METHODS restore_login_language . CLASS-METHODS set_current_language IMPORTING !iv_language TYPE sy-langu . PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gv_login_language TYPE sy-langu . ENDCLASS. CLASS zcl_abapgit_settings DEFINITION CREATE PUBLIC . PUBLIC SECTION. CONSTANTS c_commitmsg_comment_length_dft TYPE i VALUE 50 ##NO_TEXT. CONSTANTS c_commitmsg_body_size_dft TYPE i VALUE 72 ##NO_TEXT. CONSTANTS: BEGIN OF c_icon_scaling, large TYPE c VALUE 'L', small TYPE c VALUE 'S', END OF c_icon_scaling . CONSTANTS: BEGIN OF c_ui_theme, default TYPE string VALUE 'default', dark TYPE string VALUE 'dark', belize TYPE string VALUE 'belize', synced_with_gui TYPE string VALUE 'synced_with_gui', END OF c_ui_theme . METHODS set_proxy_url IMPORTING !iv_url TYPE string . METHODS set_proxy_port IMPORTING !iv_port TYPE string . METHODS set_proxy_authentication IMPORTING !iv_auth TYPE abap_bool . METHODS set_proxy_bypass IMPORTING !it_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url OPTIONAL . METHODS get_proxy_url RETURNING VALUE(rv_proxy_url) TYPE string . METHODS get_proxy_port RETURNING VALUE(rv_port) TYPE string . METHODS get_proxy_authentication RETURNING VALUE(rv_auth) TYPE abap_bool . METHODS get_proxy_bypass RETURNING VALUE(rt_bypass) TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url . METHODS set_run_critical_tests IMPORTING !iv_run TYPE abap_bool . METHODS get_run_critical_tests RETURNING VALUE(rv_run) TYPE abap_bool . METHODS set_experimental_features IMPORTING !iv_features TYPE string. METHODS get_experimental_features RETURNING VALUE(rv_features) TYPE string. METHODS set_max_lines IMPORTING !iv_lines TYPE i . METHODS get_max_lines RETURNING VALUE(rv_lines) TYPE i . METHODS set_adt_jump_enanbled IMPORTING !iv_adt_jump_enabled TYPE abap_bool . METHODS get_adt_jump_enabled RETURNING VALUE(rv_adt_jump_enabled) TYPE abap_bool . METHODS set_commitmsg_comment_length IMPORTING !iv_length TYPE i . METHODS get_commitmsg_comment_length RETURNING VALUE(rv_length) TYPE i . METHODS set_commitmsg_comment_default IMPORTING !iv_default TYPE string . METHODS get_commitmsg_comment_default RETURNING VALUE(rv_default) TYPE string . METHODS set_commitmsg_body_size IMPORTING !iv_length TYPE i . METHODS get_commitmsg_body_size RETURNING VALUE(rv_length) TYPE i . METHODS set_commitmsg_hide_author IMPORTING !iv_hide_author TYPE abap_bool. METHODS get_commitmsg_hide_author RETURNING VALUE(rv_hide_author) TYPE abap_bool. METHODS get_settings_xml RETURNING VALUE(rv_settings_xml) TYPE string RAISING zcx_abapgit_exception . METHODS get_user_settings RETURNING VALUE(rs_settings) TYPE zif_abapgit_definitions=>ty_s_user_settings RAISING zcx_abapgit_exception . METHODS set_xml_settings IMPORTING !iv_settings_xml TYPE string RAISING zcx_abapgit_exception . METHODS set_defaults . METHODS set_user_settings IMPORTING !is_user_settings TYPE zif_abapgit_definitions=>ty_s_user_settings . METHODS get_show_default_repo RETURNING VALUE(rv_show_default_repo) TYPE abap_bool . METHODS set_show_default_repo IMPORTING !iv_show_default_repo TYPE abap_bool . METHODS set_link_hints_enabled IMPORTING !iv_link_hints_enabled TYPE abap_bool . METHODS get_link_hints_enabled RETURNING VALUE(rv_link_hints_enabled) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS set_link_hint_key IMPORTING !iv_link_hint_key TYPE string . METHODS get_link_hint_key RETURNING VALUE(rv_link_hint_key) TYPE string . METHODS set_parallel_proc_disabled IMPORTING !iv_disable_parallel_proc TYPE abap_bool . METHODS get_parallel_proc_disabled RETURNING VALUE(rv_disable_parallel_proc) TYPE abap_bool . METHODS get_icon_scaling RETURNING VALUE(rv_scaling) TYPE zif_abapgit_definitions=>ty_s_user_settings-icon_scaling . METHODS set_icon_scaling IMPORTING !iv_scaling TYPE zif_abapgit_definitions=>ty_s_user_settings-icon_scaling . METHODS get_ui_theme IMPORTING !iv_resolve_synced TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rv_ui_theme) TYPE zif_abapgit_definitions=>ty_s_user_settings-ui_theme . METHODS set_ui_theme IMPORTING !iv_ui_theme TYPE zif_abapgit_definitions=>ty_s_user_settings-ui_theme . METHODS get_activate_wo_popup RETURNING VALUE(rv_act_wo_popup) TYPE zif_abapgit_definitions=>ty_s_user_settings-activate_wo_popup . METHODS set_activate_wo_popup IMPORTING !iv_act_wo_popup TYPE zif_abapgit_definitions=>ty_s_user_settings-activate_wo_popup . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_s_settings, proxy_url TYPE string, proxy_port TYPE string, proxy_auth TYPE string, proxy_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url, run_critical_tests TYPE abap_bool, experimental_features TYPE string, commitmsg_comment_length TYPE i, commitmsg_comment_deflt TYPE string, commitmsg_body_size TYPE i, commitmsg_hide_author TYPE abap_bool, END OF ty_s_settings. DATA: ms_settings TYPE ty_s_settings, ms_user_settings TYPE zif_abapgit_definitions=>ty_s_user_settings. METHODS: set_default_link_hint_key. ENDCLASS. CLASS zcl_abapgit_user_record DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS reset. CLASS-METHODS get_instance IMPORTING !iv_user TYPE sy-uname RETURNING VALUE(ro_user) TYPE REF TO zcl_abapgit_user_record. METHODS constructor IMPORTING !iv_user TYPE sy-uname. METHODS get_name RETURNING VALUE(rv_name) TYPE string. METHODS get_email RETURNING VALUE(rv_email) TYPE string. CLASS-METHODS get_title IMPORTING iv_username TYPE sy-uname RETURNING VALUE(rv_title) TYPE string. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_user, user TYPE sy-uname, o_user TYPE REF TO zcl_abapgit_user_record, END OF ty_user. CLASS-DATA gt_user TYPE HASHED TABLE OF ty_user WITH UNIQUE KEY user. DATA: BEGIN OF ms_user, name TYPE string, email TYPE string, END OF ms_user . METHODS check_user_exists IMPORTING iv_user TYPE sy-uname EXPORTING ev_fullname TYPE string ev_email TYPE string RAISING zcx_abapgit_exception. METHODS get_user_dtls_from_other_clnt IMPORTING iv_user TYPE sy-uname. ENDCLASS. CLASS zcl_abapgit_auth DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS is_allowed IMPORTING !iv_authorization TYPE zif_abapgit_auth=>ty_authorization !iv_param TYPE string OPTIONAL RETURNING VALUE(rv_allowed) TYPE abap_bool . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_exit DEFINITION CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_exit. CLASS-METHODS get_instance RETURNING VALUE(ri_exit) TYPE REF TO zif_abapgit_exit. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gi_global_exit TYPE REF TO zif_abapgit_exit. CLASS-DATA gi_exit TYPE REF TO zif_abapgit_exit. CLASS-METHODS is_running_in_test_context RETURNING VALUE(rv_running_in_test_context) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_gitv2_porcelain DEFINITION CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gitv2_porcelain. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_service, receive TYPE string VALUE 'receive', "#EC NOTEXT upload TYPE string VALUE 'upload', "#EC NOTEXT END OF c_service . CONSTANTS c_flush_pkt TYPE c LENGTH 4 VALUE '0000'. CONSTANTS c_delim_pkt TYPE c LENGTH 4 VALUE '0001'. CLASS-METHODS send_command IMPORTING iv_url TYPE string iv_service TYPE string iv_command TYPE string it_arguments TYPE string_table OPTIONAL RETURNING VALUE(rv_response) TYPE xstring RAISING zcx_abapgit_exception. CLASS-METHODS decode_pack IMPORTING iv_xstring TYPE xstring RETURNING VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_git_add_patch DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS: constructor IMPORTING it_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, get_patch RETURNING VALUE(rt_patch) TYPE string_table RAISING zcx_abapgit_exception, get_patch_binary RETURNING VALUE(rv_patch_binary) TYPE xstring RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt, mt_patch TYPE string_table. METHODS: calculate_patch RETURNING VALUE(rt_patch) TYPE string_table RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_git_branch_list DEFINITION CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING !iv_data TYPE string RAISING zcx_abapgit_exception . METHODS find_by_name IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rs_branch) TYPE zif_abapgit_git_definitions=>ty_git_branch RAISING zcx_abapgit_exception . METHODS get_head_symref RETURNING VALUE(rv_head_symref) TYPE string . METHODS get_all RETURNING VALUE(rt_branches) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt RAISING zcx_abapgit_exception . METHODS get_branches_only RETURNING VALUE(rt_branches) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt RAISING zcx_abapgit_exception . METHODS get_tags_only " For potential future use RETURNING VALUE(rt_tags) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt RAISING zcx_abapgit_exception . CLASS-METHODS get_display_name IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rv_display_name) TYPE string . CLASS-METHODS get_type IMPORTING !iv_branch_name TYPE clike !it_result TYPE string_table OPTIONAL !iv_current_row_index TYPE sy-tabix OPTIONAL RETURNING VALUE(rv_type) TYPE zif_abapgit_git_definitions=>ty_git_branch_type . CLASS-METHODS get_description IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rv_description) TYPE string. CLASS-METHODS complete_heads_branch_name IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rv_name) TYPE string . CLASS-METHODS normalize_branch_name IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rv_name) TYPE string . PROTECTED SECTION. PRIVATE SECTION. DATA mt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt . DATA mv_head_symref TYPE string . CLASS-METHODS skip_first_pkt IMPORTING !iv_data TYPE string RETURNING VALUE(rv_data) TYPE string RAISING zcx_abapgit_exception . METHODS find_tag_by_name IMPORTING !iv_branch_name TYPE string RETURNING VALUE(rs_branch) TYPE zif_abapgit_git_definitions=>ty_git_branch RAISING zcx_abapgit_exception . CLASS-METHODS parse_branch_list IMPORTING !iv_data TYPE string EXPORTING !et_list TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt !ev_head_symref TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS parse_head_params IMPORTING !iv_data TYPE string RETURNING VALUE(rv_head_symref) TYPE string . ENDCLASS. CLASS zcl_abapgit_git_commit DEFINITION CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_pull_result, commits TYPE zif_abapgit_git_definitions=>ty_commit_tt, commit TYPE zif_abapgit_git_definitions=>ty_sha1, END OF ty_pull_result . CLASS-METHODS get_by_branch IMPORTING !iv_branch_name TYPE string !iv_repo_url TYPE string !iv_deepen_level TYPE i !iv_sorted TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rs_pull_result) TYPE ty_pull_result RAISING zcx_abapgit_exception . CLASS-METHODS get_by_commit IMPORTING !iv_commit_hash TYPE zif_abapgit_git_definitions=>ty_sha1 !iv_repo_url TYPE string !iv_deepen_level TYPE i RETURNING VALUE(rt_commits) TYPE zif_abapgit_git_definitions=>ty_commit_tt RAISING zcx_abapgit_exception . CLASS-METHODS parse_commits IMPORTING !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt RETURNING VALUE(rt_commits) TYPE zif_abapgit_git_definitions=>ty_commit_tt RAISING zcx_abapgit_exception . CLASS-METHODS sort_commits CHANGING !ct_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt RAISING zcx_abapgit_exception . CLASS-METHODS reverse_sort_order CHANGING !ct_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt . CLASS-METHODS clear_missing_parents CHANGING ct_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt . PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_sha1_range TYPE RANGE OF zif_abapgit_git_definitions=>ty_sha1 . CLASS-METHODS get_1st_child_commit IMPORTING it_commit_sha1s TYPE ty_sha1_range EXPORTING et_commit_sha1s TYPE ty_sha1_range es_1st_commit TYPE zif_abapgit_git_definitions=>ty_commit CHANGING ct_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt . CLASS-METHODS is_missing IMPORTING it_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1 RETURNING VALUE(rv_result) TYPE abap_bool. CLASS-METHODS extract_author_data IMPORTING !iv_author TYPE string EXPORTING !ev_author TYPE zif_abapgit_git_definitions=>ty_commit-author !ev_email TYPE zif_abapgit_git_definitions=>ty_commit-email !ev_time TYPE zif_abapgit_git_definitions=>ty_commit-time RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_git_factory DEFINITION FINAL CREATE PRIVATE . PUBLIC SECTION. CLASS-METHODS: get_v2_porcelain RETURNING VALUE(ri_v2) TYPE REF TO zif_abapgit_gitv2_porcelain, get_git_transport RETURNING VALUE(ri_git_transport) TYPE REF TO zif_abapgit_git_transport. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA: gi_git_transport TYPE REF TO zif_abapgit_git_transport. ENDCLASS. CLASS kHGwlHhZbTrIxNkYzsWttffscEwAXR DEFINITION DEFERRED. *"* use this source file for any type of declarations (class *"* definitions, interfaces or type declarations) you need for *"* components in the private section * renamed: zcl_abapgit_git_pack :: lcl_stream CLASS kHGwlHhZbTrIxNkYzsWttffscEwAXR DEFINITION FINAL. PUBLIC SECTION. TYPES: ty_hex TYPE x LENGTH 1. METHODS: constructor IMPORTING iv_data TYPE xstring, get RETURNING VALUE(rv_data) TYPE xstring, eat_byte RETURNING VALUE(rv_x) TYPE ty_hex, eat_bytes IMPORTING iv_length TYPE i RETURNING VALUE(rv_x) TYPE xstring. PRIVATE SECTION. DATA: mv_data TYPE xstring. ENDCLASS. CLASS zcl_abapgit_git_pack DEFINITION CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_node, chmod TYPE zif_abapgit_git_definitions=>ty_chmod, name TYPE string, sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, END OF ty_node . TYPES: ty_nodes_tt TYPE STANDARD TABLE OF ty_node WITH DEFAULT KEY . TYPES: BEGIN OF ty_commit, tree TYPE zif_abapgit_git_definitions=>ty_sha1, parent TYPE zif_abapgit_git_definitions=>ty_sha1, parent2 TYPE zif_abapgit_git_definitions=>ty_sha1, author TYPE string, committer TYPE string, gpgsig TYPE string, body TYPE string, END OF ty_commit . TYPES: BEGIN OF ty_tag, object TYPE string, type TYPE string, tag TYPE string, tagger_name TYPE string, tagger_email TYPE string, message TYPE string, body TYPE string, END OF ty_tag . CLASS-METHODS decode IMPORTING !iv_data TYPE xstring RETURNING VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception . CLASS-METHODS decode_tree IMPORTING !iv_data TYPE xstring RETURNING VALUE(rt_nodes) TYPE ty_nodes_tt RAISING zcx_abapgit_exception . CLASS-METHODS decode_commit IMPORTING !iv_data TYPE xstring RETURNING VALUE(rs_commit) TYPE ty_commit RAISING zcx_abapgit_exception . CLASS-METHODS decode_tag IMPORTING !iv_data TYPE xstring RETURNING VALUE(rs_tag) TYPE ty_tag RAISING zcx_abapgit_exception . CLASS-METHODS encode IMPORTING !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt RETURNING VALUE(rv_data) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS encode_tree IMPORTING !it_nodes TYPE ty_nodes_tt RETURNING VALUE(rv_data) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS encode_commit IMPORTING !is_commit TYPE ty_commit RETURNING VALUE(rv_data) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS encode_tag IMPORTING !is_tag TYPE ty_tag RETURNING VALUE(rv_data) TYPE xstring RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_pack_start TYPE x LENGTH 4 VALUE '5041434B' ##NO_TEXT. CONSTANTS: c_zlib TYPE x LENGTH 2 VALUE '789C' ##NO_TEXT. CONSTANTS: c_zlib_hmm TYPE x LENGTH 2 VALUE '7801' ##NO_TEXT. CONSTANTS: " PACK c_version TYPE x LENGTH 4 VALUE '00000002' ##NO_TEXT. CLASS-METHODS decode_deltas CHANGING !ct_objects TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception . CLASS-METHODS delta IMPORTING !is_object TYPE zif_abapgit_definitions=>ty_object CHANGING !ct_objects TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception . CLASS-METHODS delta_header IMPORTING !io_stream TYPE REF TO kHGwlHhZbTrIxNkYzsWttffscEwAXR RETURNING VALUE(rv_header) TYPE i . CLASS-METHODS sort_tree IMPORTING !it_nodes TYPE ty_nodes_tt RETURNING VALUE(rt_nodes) TYPE ty_nodes_tt . CLASS-METHODS get_type IMPORTING !iv_x TYPE x RETURNING VALUE(rv_type) TYPE zif_abapgit_git_definitions=>ty_type RAISING zcx_abapgit_exception . CLASS-METHODS get_length EXPORTING !ev_length TYPE i CHANGING !cv_data TYPE xstring . CLASS-METHODS type_and_length IMPORTING !iv_type TYPE zif_abapgit_git_definitions=>ty_type !iv_length TYPE i RETURNING VALUE(rv_xstring) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS zlib_decompress CHANGING !cv_data TYPE xstring !cv_decompressed TYPE xstring RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_git_porcelain DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_pull_result, files TYPE zif_abapgit_git_definitions=>ty_files_tt, objects TYPE zif_abapgit_definitions=>ty_objects_tt, commit TYPE zif_abapgit_git_definitions=>ty_sha1, END OF ty_pull_result . TYPES: BEGIN OF ty_push_result, new_files TYPE zif_abapgit_git_definitions=>ty_files_tt, branch TYPE zif_abapgit_git_definitions=>ty_sha1, updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt, new_objects TYPE zif_abapgit_definitions=>ty_objects_tt, END OF ty_push_result . CLASS-METHODS pull_by_branch IMPORTING !iv_url TYPE string !iv_branch_name TYPE string !iv_deepen_level TYPE i DEFAULT 1 RETURNING VALUE(rs_result) TYPE ty_pull_result RAISING zcx_abapgit_exception . CLASS-METHODS pull_by_commit IMPORTING !iv_url TYPE string !iv_commit_hash TYPE zif_abapgit_git_definitions=>ty_sha1 !iv_deepen_level TYPE i DEFAULT 1 RETURNING VALUE(rs_result) TYPE ty_pull_result RAISING zcx_abapgit_exception . CLASS-METHODS push IMPORTING !is_comment TYPE zif_abapgit_git_definitions=>ty_comment !io_stage TYPE REF TO zcl_abapgit_stage !it_old_objects TYPE zif_abapgit_definitions=>ty_objects_tt !iv_parent TYPE zif_abapgit_git_definitions=>ty_sha1 !iv_url TYPE string !iv_branch_name TYPE string RETURNING VALUE(rs_result) TYPE ty_push_result RAISING zcx_abapgit_exception . CLASS-METHODS create_branch IMPORTING !iv_url TYPE string !iv_name TYPE string !iv_from TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . CLASS-METHODS create_tag IMPORTING !iv_url TYPE string !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag RAISING zcx_abapgit_exception . CLASS-METHODS delete_branch IMPORTING !iv_url TYPE string !is_branch TYPE zif_abapgit_git_definitions=>ty_git_branch RAISING zcx_abapgit_exception . CLASS-METHODS delete_tag IMPORTING !iv_url TYPE string !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag RAISING zcx_abapgit_exception . CLASS-METHODS full_tree IMPORTING !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt !iv_parent TYPE zif_abapgit_git_definitions=>ty_sha1 RETURNING VALUE(rt_expanded) TYPE zif_abapgit_git_definitions=>ty_expanded_tt RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_tree, path TYPE string, data TYPE xstring, sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, END OF ty_tree . TYPES: ty_trees_tt TYPE STANDARD TABLE OF ty_tree WITH DEFAULT KEY . TYPES: BEGIN OF ty_folder, path TYPE string, count TYPE i, sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, END OF ty_folder . TYPES: ty_folders_tt TYPE STANDARD TABLE OF ty_folder WITH DEFAULT KEY . CONSTANTS c_zero TYPE zif_abapgit_git_definitions=>ty_sha1 VALUE '0000000000000000000000000000000000000000' ##NO_TEXT. CLASS-METHODS build_trees IMPORTING !it_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt RETURNING VALUE(rt_trees) TYPE ty_trees_tt RAISING zcx_abapgit_exception . CLASS-METHODS find_folders IMPORTING !it_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt RETURNING VALUE(rt_folders) TYPE ty_folders_tt . CLASS-METHODS pull IMPORTING !iv_commit TYPE zif_abapgit_git_definitions=>ty_sha1 !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception. CLASS-METHODS walk IMPORTING !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt !iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1 !iv_path TYPE string CHANGING !ct_files TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . CLASS-METHODS walk_tree IMPORTING !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt !iv_tree TYPE zif_abapgit_git_definitions=>ty_sha1 !iv_base TYPE string RETURNING VALUE(rt_expanded) TYPE zif_abapgit_git_definitions=>ty_expanded_tt RAISING zcx_abapgit_exception . CLASS-METHODS receive_pack_push IMPORTING !is_comment TYPE zif_abapgit_git_definitions=>ty_comment !it_trees TYPE ty_trees_tt !it_blobs TYPE zif_abapgit_git_definitions=>ty_files_tt !iv_parent TYPE zif_abapgit_git_definitions=>ty_sha1 !iv_parent2 TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL !iv_url TYPE string !iv_branch_name TYPE string EXPORTING !ev_new_commit TYPE zif_abapgit_git_definitions=>ty_sha1 !et_new_objects TYPE zif_abapgit_definitions=>ty_objects_tt !ev_new_tree TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . CLASS-METHODS create_annotated_tag IMPORTING !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag !iv_url TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS create_lightweight_tag IMPORTING is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag iv_url TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS delete_annotated_tag IMPORTING !iv_url TYPE string !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag RAISING zcx_abapgit_exception . CLASS-METHODS delete_lightweight_tag IMPORTING !iv_url TYPE string !is_tag TYPE zif_abapgit_git_definitions=>ty_git_tag RAISING zcx_abapgit_exception . CLASS-METHODS empty_packfile RETURNING VALUE(rv_pack) TYPE xstring RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_git_tag DEFINITION CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS add_tag_prefix IMPORTING !iv_text TYPE csequence RETURNING VALUE(rv_text) TYPE string. CLASS-METHODS remove_tag_prefix IMPORTING !iv_text TYPE string RETURNING VALUE(rv_text) TYPE string. CLASS-METHODS add_peel IMPORTING !iv_text TYPE string RETURNING VALUE(rv_text) TYPE string. CLASS-METHODS remove_peel IMPORTING !iv_text TYPE string RETURNING VALUE(rv_text) TYPE string. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_git_time DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: ty_unixtime TYPE c LENGTH 16 . CLASS-METHODS get_unix RETURNING VALUE(rv_time) TYPE ty_unixtime RAISING zcx_abapgit_exception . CLASS-METHODS get_one_year_ago RETURNING VALUE(rv_time) TYPE i RAISING zcx_abapgit_exception . CLASS-METHODS get_utc IMPORTING !iv_unix TYPE ty_unixtime EXPORTING !ev_date TYPE sy-datum !ev_time TYPE sy-uzeit . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_git_transport DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_git_transport. * remote to local CLASS-METHODS upload_pack_by_branch IMPORTING !iv_url TYPE string !iv_branch_name TYPE string !iv_deepen_level TYPE i DEFAULT 1 !it_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt OPTIONAL EXPORTING !et_objects TYPE zif_abapgit_definitions=>ty_objects_tt !ev_branch TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . CLASS-METHODS upload_pack_by_commit IMPORTING !iv_url TYPE string !iv_hash TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL !iv_deepen_level TYPE i DEFAULT 0 EXPORTING !et_objects TYPE zif_abapgit_definitions=>ty_objects_tt !ev_commit TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . * local to remote CLASS-METHODS receive_pack IMPORTING !iv_url TYPE string !iv_old TYPE zif_abapgit_git_definitions=>ty_sha1 !iv_new TYPE zif_abapgit_git_definitions=>ty_sha1 !iv_branch_name TYPE string !iv_pack TYPE xstring OPTIONAL RAISING zcx_abapgit_exception . CLASS-METHODS branches IMPORTING iv_url TYPE string RETURNING VALUE(ro_branch_list) TYPE REF TO zcl_abapgit_git_branch_list RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_service, receive TYPE string VALUE 'receive', "#EC NOTEXT upload TYPE string VALUE 'upload', "#EC NOTEXT END OF c_service . CLASS-METHODS check_report_status IMPORTING !iv_string TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS branch_list IMPORTING !iv_url TYPE string !iv_service TYPE string EXPORTING !eo_client TYPE REF TO zcl_abapgit_http_client !eo_branch_list TYPE REF TO zcl_abapgit_git_branch_list RAISING zcx_abapgit_exception . CLASS-METHODS find_branch IMPORTING !iv_url TYPE string !iv_service TYPE string !iv_branch_name TYPE string EXPORTING !eo_client TYPE REF TO zcl_abapgit_http_client !ev_branch TYPE zif_abapgit_git_definitions=>ty_sha1 !eo_branch_list TYPE REF TO zcl_abapgit_git_branch_list RAISING zcx_abapgit_exception . CLASS-METHODS parse EXPORTING !ev_pack TYPE xstring CHANGING !cv_data TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS upload_pack IMPORTING !io_client TYPE REF TO zcl_abapgit_http_client !iv_url TYPE string !iv_deepen_level TYPE i DEFAULT 0 !it_hashes TYPE zif_abapgit_git_definitions=>ty_sha1_tt RETURNING VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_git_utils DEFINITION CREATE PUBLIC . PUBLIC SECTION. TYPES: ty_null TYPE c LENGTH 1 . CLASS-METHODS get_null RETURNING VALUE(rv_c) TYPE ty_null . CLASS-METHODS pkt_string IMPORTING !iv_string TYPE string RETURNING VALUE(rv_pkt) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS length_utf8_hex IMPORTING !iv_data TYPE xstring RETURNING VALUE(rv_len) TYPE i RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_hash DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS adler32 IMPORTING !iv_xstring TYPE xstring RETURNING VALUE(rv_checksum) TYPE zif_abapgit_git_definitions=>ty_adler32 . CLASS-METHODS sha1 IMPORTING !iv_type TYPE zif_abapgit_git_definitions=>ty_type !iv_data TYPE xstring RETURNING VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . CLASS-METHODS sha1_commit IMPORTING !iv_data TYPE xstring RETURNING VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . CLASS-METHODS sha1_tree IMPORTING !iv_data TYPE xstring RETURNING VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . CLASS-METHODS sha1_tag IMPORTING !iv_data TYPE xstring RETURNING VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . CLASS-METHODS sha1_blob IMPORTING !iv_data TYPE xstring RETURNING VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . CLASS-METHODS sha1_raw IMPORTING !iv_data TYPE xstring RETURNING VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . CLASS-METHODS sha1_string IMPORTING !iv_data TYPE string RETURNING VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1 RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_zlib DEFINITION CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_decompress, raw TYPE xstring, compressed_len TYPE i, END OF ty_decompress . CLASS-METHODS decompress IMPORTING !iv_compressed TYPE xsequence RETURNING VALUE(rs_data) TYPE ty_decompress . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_maxdcodes TYPE i VALUE 30. CLASS-DATA: gv_out TYPE xstring, go_lencode TYPE REF TO zcl_abapgit_zlib_huffman, go_distcode TYPE REF TO zcl_abapgit_zlib_huffman, go_stream TYPE REF TO zcl_abapgit_zlib_stream. TYPES: BEGIN OF ty_pair, length TYPE i, distance TYPE i, END OF ty_pair. CLASS-METHODS: decode IMPORTING io_huffman TYPE REF TO zcl_abapgit_zlib_huffman RETURNING VALUE(rv_symbol) TYPE i, map_length IMPORTING iv_code TYPE i RETURNING VALUE(rv_length) TYPE i, map_distance IMPORTING iv_code TYPE i RETURNING VALUE(rv_distance) TYPE i, dynamic, fixed, not_compressed, decode_loop, read_pair IMPORTING iv_length TYPE i RETURNING VALUE(rs_pair) TYPE ty_pair, copy_out IMPORTING is_pair TYPE ty_pair. ENDCLASS. CLASS zcl_abapgit_zlib_convert DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS hex_to_bits IMPORTING !iv_hex TYPE xsequence RETURNING VALUE(rv_bits) TYPE string. CLASS-METHODS bits_to_int IMPORTING !iv_bits TYPE clike RETURNING VALUE(rv_int) TYPE i. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_zlib_huffman DEFINITION CREATE PUBLIC . PUBLIC SECTION. TYPES: ty_lengths TYPE STANDARD TABLE OF i WITH DEFAULT KEY . CONSTANTS c_maxbits TYPE i VALUE 15 ##NO_TEXT. METHODS constructor IMPORTING !it_lengths TYPE ty_lengths . METHODS get_count IMPORTING !iv_index TYPE i RETURNING VALUE(rv_value) TYPE i . METHODS get_symbol IMPORTING !iv_index TYPE i RETURNING VALUE(rv_value) TYPE i . PROTECTED SECTION. PRIVATE SECTION. DATA: mt_count TYPE STANDARD TABLE OF i WITH DEFAULT KEY, mt_symbol TYPE STANDARD TABLE OF i WITH DEFAULT KEY. ENDCLASS. CLASS zcl_abapgit_zlib_stream DEFINITION CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING !iv_data TYPE xstring . METHODS take_bits IMPORTING !iv_length TYPE i RETURNING VALUE(rv_bits) TYPE string . METHODS take_int IMPORTING !iv_length TYPE i RETURNING VALUE(rv_int) TYPE i . METHODS remaining RETURNING VALUE(rv_length) TYPE i . "! Take bytes, there's an implicit realignment to start at the beginning of a byte "! i.e. if next bit of current byte is not the first bit, then this byte is skipped "! and the bytes are taken from the next one. "! @parameter iv_length |

"! @parameter rv_bytes |

METHODS take_bytes IMPORTING !iv_length TYPE i RETURNING VALUE(rv_bytes) TYPE xstring . METHODS clear_bits . PROTECTED SECTION. PRIVATE SECTION. DATA mv_bits TYPE string . DATA mv_compressed TYPE xstring . ENDCLASS. CLASS zcl_abapgit_git_url DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS get_commit_display_url IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online RETURNING VALUE(rv_url) TYPE string RAISING zcx_abapgit_exception . METHODS validate_url IMPORTING !iv_url TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. METHODS get_default_commit_display_url IMPORTING !iv_repo_url TYPE string !iv_hash TYPE zif_abapgit_git_definitions=>ty_sha1 RETURNING VALUE(rv_commit_url) TYPE string RAISING zcx_abapgit_exception . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_pr_enum_github DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_pr_enum_provider . METHODS constructor IMPORTING !iv_user_and_repo TYPE string !ii_http_agent TYPE REF TO zif_abapgit_http_agent RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_info, repo_json TYPE REF TO zif_abapgit_ajson, pulls TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests, END OF ty_info. DATA mi_http_agent TYPE REF TO zif_abapgit_http_agent. DATA mv_repo_url TYPE string. METHODS fetch_repo_by_url IMPORTING iv_repo_url TYPE string RETURNING VALUE(rs_info) TYPE ty_info RAISING zcx_abapgit_exception. METHODS convert_list IMPORTING ii_json TYPE REF TO zif_abapgit_ajson RETURNING VALUE(rt_pulls) TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests. METHODS clean_url IMPORTING iv_url TYPE string RETURNING VALUE(rv_url) TYPE string. ENDCLASS. CLASS zcl_abapgit_pr_enumerator DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING iv_url TYPE string RAISING zcx_abapgit_exception. METHODS get_pulls RETURNING VALUE(rt_pulls) TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests RAISING zcx_abapgit_exception. CLASS-METHODS new IMPORTING iv_url TYPE string RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_pr_enumerator RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mv_repo_url TYPE string. DATA mi_enum_provider TYPE REF TO zif_abapgit_pr_enum_provider. CLASS-METHODS create_provider IMPORTING iv_repo_url TYPE string RETURNING VALUE(ri_provider) TYPE REF TO zif_abapgit_pr_enum_provider RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_http DEFINITION CREATE PUBLIC . PUBLIC SECTION. CONSTANTS: BEGIN OF c_scheme, digest TYPE string VALUE 'Digest', END OF c_scheme . CLASS-METHODS get_agent RETURNING VALUE(rv_agent) TYPE string . TYPES: BEGIN OF ty_key_value, key TYPE string, value TYPE string, END OF ty_key_value. TYPES ty_headers TYPE STANDARD TABLE OF ty_key_value WITH DEFAULT KEY. CLASS-METHODS create_by_url IMPORTING !iv_url TYPE string !iv_service TYPE string it_headers TYPE ty_headers OPTIONAL RETURNING VALUE(ro_client) TYPE REF TO zcl_abapgit_http_client RAISING zcx_abapgit_exception . CLASS-METHODS check_connection IMPORTING !iv_url TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. CLASS-METHODS check_auth_requested IMPORTING !ii_client TYPE REF TO if_http_client RETURNING VALUE(rv_auth_requested) TYPE abap_bool RAISING zcx_abapgit_exception . CLASS-METHODS is_local_system IMPORTING !iv_url TYPE string RETURNING VALUE(rv_bool) TYPE abap_bool . CLASS-METHODS acquire_login_details IMPORTING !ii_client TYPE REF TO if_http_client !io_client TYPE REF TO zcl_abapgit_http_client !iv_url TYPE string RETURNING VALUE(rv_scheme) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS get_http_client IMPORTING !iv_url TYPE string RETURNING VALUE(ri_client) TYPE REF TO if_http_client RAISING zcx_abapgit_exception. CLASS-METHODS get_connection_longtext IMPORTING !iv_host TYPE string !iv_ssl_id TYPE ssfapplssl !iv_proxy_host TYPE string !iv_proxy_service TYPE string RETURNING VALUE(rv_longtext) TYPE string. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_http_agent DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_http_agent . CLASS-METHODS create RETURNING VALUE(ri_instance) TYPE REF TO zif_abapgit_http_agent . METHODS constructor. PROTECTED SECTION. PRIVATE SECTION. DATA mo_global_headers TYPE REF TO zcl_abapgit_string_map. CLASS-METHODS attach_payload IMPORTING ii_request TYPE REF TO if_http_request iv_payload TYPE any RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_http_client DEFINITION CREATE PUBLIC. PUBLIC SECTION. METHODS: constructor IMPORTING ii_client TYPE REF TO if_http_client, close, set_digest IMPORTING io_digest TYPE REF TO zcl_abapgit_http_digest, send_receive_close IMPORTING iv_data TYPE xstring RETURNING VALUE(rv_data) TYPE xstring RAISING zcx_abapgit_exception, get_cdata RETURNING VALUE(rv_value) TYPE string, check_http_200 RAISING zcx_abapgit_exception, check_smart_response IMPORTING iv_expected_content_type TYPE string iv_content_regex TYPE string RAISING zcx_abapgit_exception, send_receive RAISING zcx_abapgit_exception, set_headers IMPORTING iv_url TYPE string iv_service TYPE string RAISING zcx_abapgit_exception. METHODS set_header IMPORTING iv_key TYPE string iv_value TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mi_client TYPE REF TO if_http_client, mo_digest TYPE REF TO zcl_abapgit_http_digest. ENDCLASS. CLASS zcl_abapgit_http_digest DEFINITION CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING !ii_client TYPE REF TO if_http_client !iv_username TYPE string !iv_password TYPE string RAISING zcx_abapgit_exception. METHODS run IMPORTING !ii_client TYPE REF TO if_http_client RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mv_ha1 TYPE string, mv_username TYPE string, mv_realm TYPE string, mv_qop TYPE string, mv_nonce TYPE string. CLASS-DATA: gv_nc TYPE n LENGTH 8. CLASS-METHODS: md5 IMPORTING iv_data TYPE string RETURNING VALUE(rv_hash) TYPE string RAISING zcx_abapgit_exception. METHODS: hash IMPORTING iv_qop TYPE string iv_nonce TYPE string iv_uri TYPE string iv_method TYPE string iv_cnonse TYPE string RETURNING VALUE(rv_response) TYPE string RAISING zcx_abapgit_exception, parse IMPORTING ii_client TYPE REF TO if_http_client. ENDCLASS. CLASS zcl_abapgit_login_manager DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS load IMPORTING !iv_uri TYPE string RETURNING VALUE(rv_authorization) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS save IMPORTING !iv_uri TYPE string !iv_authorization TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS clear . CLASS-METHODS set IMPORTING !iv_uri TYPE string !iv_username TYPE string !iv_password TYPE string RETURNING VALUE(rv_auth) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS get IMPORTING !iv_uri TYPE string RETURNING VALUE(rv_auth) TYPE string RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_auth, uri TYPE string, authorization TYPE string, END OF ty_auth . CLASS-DATA: gt_auth TYPE TABLE OF ty_auth WITH DEFAULT KEY . CLASS-METHODS append IMPORTING !iv_uri TYPE string !iv_auth TYPE string RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_proxy_auth DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS: run IMPORTING ii_client TYPE REF TO if_http_client RAISING zcx_abapgit_exception. PRIVATE SECTION. CLASS-DATA: gv_username TYPE string, gv_password TYPE string. CLASS-METHODS: enter RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_proxy_config DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS: constructor, get_proxy_url IMPORTING iv_repo_url TYPE csequence OPTIONAL RETURNING VALUE(rv_proxy_url) TYPE string, get_proxy_port IMPORTING iv_repo_url TYPE csequence OPTIONAL RETURNING VALUE(rv_port) TYPE string, get_proxy_authentication IMPORTING iv_repo_url TYPE csequence OPTIONAL RETURNING VALUE(rv_auth) TYPE abap_bool. PROTECTED SECTION. PRIVATE SECTION. DATA: mo_settings TYPE REF TO zcl_abapgit_settings, mi_exit TYPE REF TO zif_abapgit_exit. METHODS: bypass_proxy IMPORTING iv_repo_url TYPE csequence OPTIONAL RETURNING VALUE(rv_bypass_proxy) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_url DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS validate IMPORTING !iv_url TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS host IMPORTING !iv_url TYPE string RETURNING VALUE(rv_host) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS name IMPORTING !iv_url TYPE string !iv_validate TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_name) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS path_name IMPORTING !iv_url TYPE string RETURNING VALUE(rv_path_name) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS is_abapgit_repo IMPORTING !iv_url TYPE string RETURNING VALUE(rv_abapgit) TYPE abap_bool . CLASS-METHODS url_address IMPORTING !iv_url TYPE string RETURNING VALUE(rv_adress) TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS regex IMPORTING !iv_url TYPE string EXPORTING !ev_host TYPE string !ev_path TYPE string !ev_name TYPE string RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_code_inspector DEFINITION CREATE PROTECTED FRIENDS ZCL_ABAPGIT_factory . PUBLIC SECTION. INTERFACES zif_abapgit_code_inspector . METHODS constructor IMPORTING !iv_package TYPE devclass RAISING zcx_abapgit_exception . PROTECTED SECTION. DATA mv_package TYPE devclass . METHODS create_variant IMPORTING !iv_variant TYPE sci_chkv RETURNING VALUE(ro_variant) TYPE REF TO cl_ci_checkvariant RAISING zcx_abapgit_exception . METHODS cleanup IMPORTING !io_set TYPE REF TO cl_ci_objectset RAISING zcx_abapgit_exception . METHODS skip_object IMPORTING !is_obj TYPE scir_objs RETURNING VALUE(rv_skip) TYPE abap_bool. PRIVATE SECTION. DATA mv_success TYPE abap_bool . DATA mv_summary TYPE string. TYPES: ty_run_mode TYPE c LENGTH 1. CONSTANTS: BEGIN OF co_run_mode, run_with_popup TYPE ty_run_mode VALUE 'P', run_after_popup TYPE ty_run_mode VALUE 'A', run_via_rfc TYPE ty_run_mode VALUE 'R', run_in_batch TYPE ty_run_mode VALUE 'B', run_loc_parallel TYPE ty_run_mode VALUE 'L', run_direct TYPE ty_run_mode VALUE 'L', END OF co_run_mode . DATA mo_inspection TYPE REF TO cl_ci_inspection . DATA mv_name TYPE sci_objs . DATA mv_run_mode TYPE c LENGTH 1 . METHODS create_objectset RETURNING VALUE(ro_set) TYPE REF TO cl_ci_objectset . METHODS run_inspection IMPORTING !io_inspection TYPE REF TO cl_ci_inspection RETURNING VALUE(rt_list) TYPE scit_alvlist RAISING zcx_abapgit_exception . METHODS create_inspection IMPORTING !io_set TYPE REF TO cl_ci_objectset !io_variant TYPE REF TO cl_ci_checkvariant RETURNING VALUE(ro_inspection) TYPE REF TO cl_ci_inspection RAISING zcx_abapgit_exception . METHODS decide_run_mode RETURNING VALUE(rv_run_mode) TYPE ty_run_mode . METHODS filter_inspection CHANGING !ct_list TYPE scit_alvlist . ENDCLASS. CLASS zcl_abapgit_where_used_tools DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES ty_devc_range TYPE RANGE OF tadir-devclass. TYPES: BEGIN OF ty_dependency, package TYPE devclass, obj_type TYPE tadir-object, obj_prog_type TYPE trdir-subc, obj_name TYPE tadir-obj_name, obj_cls TYPE rsfindlst-object_cls, dep_package TYPE devclass, dep_obj_type TYPE tadir-object, dep_obj_name TYPE tadir-obj_name, dep_used_cls TYPE rsfindlst-used_cls, dep_used_obj TYPE rsfindlst-used_obj, END OF ty_dependency. TYPES: ty_dependency_tt TYPE STANDARD TABLE OF ty_dependency WITH DEFAULT KEY. CLASS-METHODS new RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_where_used_tools. " the initial version of this utility is also available as a standalone tool " here: https://github.com/sbcgua/crossdeps METHODS select_external_usages IMPORTING iv_package TYPE tadir-devclass iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false ir_package_scope TYPE ty_devc_range OPTIONAL RETURNING VALUE(rt_objs) TYPE ty_dependency_tt RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_obj_signature, package TYPE devclass, obj_type TYPE tadir-object, obj_name TYPE tadir-obj_name, END OF ty_obj_signature. TYPES ty_where_used_tt TYPE STANDARD TABLE OF rsfindlst WITH DEFAULT KEY. TYPES ty_seu_obj TYPE STANDARD TABLE OF seu_obj WITH DEFAULT KEY. TYPES: BEGIN OF ty_dev_object, type TYPE seu_stype, tadir TYPE trobjtype, END OF ty_dev_object. DATA mt_object_packages TYPE HASHED TABLE OF ty_obj_signature WITH UNIQUE KEY obj_type obj_name. DATA mt_dev_obj_cache TYPE HASHED TABLE OF ty_dev_object WITH UNIQUE KEY type. METHODS get_where_used IMPORTING iv_obj_type TYPE euobj-id iv_obj_name TYPE tadir-obj_name it_scope TYPE ty_seu_obj OPTIONAL ir_package_scope TYPE ty_devc_range OPTIONAL RETURNING VALUE(rt_findings) TYPE ty_where_used_tt RAISING zcx_abapgit_exception. METHODS get_obj_package IMPORTING iv_obj_type TYPE tadir-object iv_obj_name TYPE tadir-obj_name RETURNING VALUE(rv_package) TYPE tadir-devclass. METHODS get_func_package IMPORTING iv_func_name TYPE tadir-obj_name RETURNING VALUE(rv_package) TYPE tadir-devclass. METHODS get_incl_package IMPORTING iv_prog_name TYPE tadir-obj_name RETURNING VALUE(rv_package) TYPE tadir-devclass. METHODS build_package_scope IMPORTING it_tadir TYPE STANDARD TABLE ir_package_scope TYPE ty_devc_range RETURNING VALUE(rt_package_scope) TYPE ty_devc_range. METHODS collect_where_used IMPORTING it_tadir TYPE STANDARD TABLE ir_package_scope TYPE ty_devc_range RETURNING VALUE(rt_objs) TYPE ty_dependency_tt RAISING zcx_abapgit_exception. METHODS convert_list IMPORTING iv_package TYPE ty_dependency-dep_package iv_obj_type TYPE ty_dependency-dep_obj_type iv_obj_name TYPE ty_dependency-dep_obj_name it_where_used TYPE ty_where_used_tt RETURNING VALUE(rt_objs) TYPE ty_dependency_tt. METHODS decode_obj_type IMPORTING iv_type TYPE rsfindlst-object_cls RETURNING VALUE(rv_type) TYPE ty_dev_object-tadir. ENDCLASS. CLASS zcl_abapgit_ajson DEFINITION CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_ajson . ALIASES: is_empty FOR zif_abapgit_ajson~is_empty, exists FOR zif_abapgit_ajson~exists, members FOR zif_abapgit_ajson~members, get FOR zif_abapgit_ajson~get, get_boolean FOR zif_abapgit_ajson~get_boolean, get_integer FOR zif_abapgit_ajson~get_integer, get_number FOR zif_abapgit_ajson~get_number, get_date FOR zif_abapgit_ajson~get_date, get_timestamp FOR zif_abapgit_ajson~get_timestamp, get_string FOR zif_abapgit_ajson~get_string, slice FOR zif_abapgit_ajson~slice, to_abap FOR zif_abapgit_ajson~to_abap, array_to_string_table FOR zif_abapgit_ajson~array_to_string_table. ALIASES: clear FOR zif_abapgit_ajson~clear, set FOR zif_abapgit_ajson~set, setx FOR zif_abapgit_ajson~setx, set_boolean FOR zif_abapgit_ajson~set_boolean, set_string FOR zif_abapgit_ajson~set_string, set_integer FOR zif_abapgit_ajson~set_integer, set_date FOR zif_abapgit_ajson~set_date, set_timestamp FOR zif_abapgit_ajson~set_timestamp, set_null FOR zif_abapgit_ajson~set_null, delete FOR zif_abapgit_ajson~delete, touch_array FOR zif_abapgit_ajson~touch_array, push FOR zif_abapgit_ajson~push, stringify FOR zif_abapgit_ajson~stringify. ALIASES: clone FOR zif_abapgit_ajson~clone, filter FOR zif_abapgit_ajson~filter, map FOR zif_abapgit_ajson~map. ALIASES: mt_json_tree FOR zif_abapgit_ajson~mt_json_tree, keep_item_order FOR zif_abapgit_ajson~keep_item_order, format_datetime FOR zif_abapgit_ajson~format_datetime, to_abap_corresponding_only FOR zif_abapgit_ajson~to_abap_corresponding_only, freeze FOR zif_abapgit_ajson~freeze. CLASS-METHODS parse IMPORTING !iv_json TYPE string !iv_freeze TYPE abap_bool DEFAULT abap_false !ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL !iv_keep_item_order TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson RAISING zcx_abapgit_ajson_error . CLASS-METHODS create_empty " Might be deprecated, prefer using new( ) or create object IMPORTING !ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL iv_keep_item_order TYPE abap_bool DEFAULT abap_false iv_format_datetime TYPE abap_bool DEFAULT abap_true iv_to_abap_corresponding_only TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson. " Experimental ! May change CLASS-METHODS create_from " TODO, rename to 'from' ? IMPORTING !ii_source_json TYPE REF TO zif_abapgit_ajson !ii_filter TYPE REF TO zif_abapgit_ajson_filter OPTIONAL " Might be deprecated, use filter() instead !ii_mapper TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL " Might be deprecated, use map() instead RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson RAISING zcx_abapgit_ajson_error . METHODS constructor IMPORTING iv_keep_item_order TYPE abap_bool DEFAULT abap_false iv_format_datetime TYPE abap_bool DEFAULT abap_true iv_to_abap_corresponding_only TYPE abap_bool DEFAULT abap_false. CLASS-METHODS new IMPORTING iv_keep_item_order TYPE abap_bool DEFAULT abap_false iv_format_datetime TYPE abap_bool DEFAULT abap_true iv_to_abap_corresponding_only TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA go_float_regex TYPE REF TO cl_abap_regex. DATA ms_opts TYPE zif_abapgit_ajson=>ty_opts. DATA mi_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping. " DEPRECATED, will be removed METHODS get_item IMPORTING iv_path TYPE string RETURNING VALUE(rv_item) TYPE REF TO zif_abapgit_ajson_types=>ty_node. METHODS prove_path_exists IMPORTING iv_path TYPE string RETURNING VALUE(rr_end_node) TYPE REF TO zif_abapgit_ajson_types=>ty_node RAISING zcx_abapgit_ajson_error. METHODS delete_subtree IMPORTING iv_path TYPE string iv_name TYPE string ir_parent TYPE REF TO zif_abapgit_ajson_types=>ty_node OPTIONAL RETURNING VALUE(rs_top_node) TYPE zif_abapgit_ajson_types=>ty_node. METHODS read_only_watchdog RAISING zcx_abapgit_ajson_error. ENDCLASS. CLASS zcl_abapgit_ajson_filter_lib DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS create_empty_filter RETURNING VALUE(ri_filter) TYPE REF TO zif_abapgit_ajson_filter RAISING zcx_abapgit_ajson_error . CLASS-METHODS create_path_filter IMPORTING !it_skip_paths TYPE string_table OPTIONAL !iv_skip_paths TYPE string OPTIONAL !iv_pattern_search TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_filter) TYPE REF TO zif_abapgit_ajson_filter RAISING zcx_abapgit_ajson_error . CLASS-METHODS create_and_filter IMPORTING !it_filters TYPE zif_abapgit_ajson_filter=>ty_filter_tab RETURNING VALUE(ri_filter) TYPE REF TO zif_abapgit_ajson_filter RAISING zcx_abapgit_ajson_error . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS kHGwlpuwVGRXmbkWZJMoWRsLzEdjUi DEFINITION DEFERRED. CLASS kHGwlpuwVGRXmbkWZJMorCLylKulMM DEFINITION DEFERRED. CLASS kHGwlpuwVGRXmbkWZJMooAlevhaDMg DEFINITION DEFERRED. CLASS kHGwlpuwVGRXmbkWZJMoYWDnXPYsQA DEFINITION DEFERRED. CLASS kHGwlpuwVGRXmbkWZJMoIaLFAtEmIg DEFINITION DEFERRED. CLASS kHGwlpuwVGRXmbkWZJMoayhtkOTSGN DEFINITION DEFERRED. CLASS kHGwlpuwVGRXmbkWZJMocwrelrEIET DEFINITION DEFERRED. CLASS kHGwlpuwVGRXmbkWZJMoTFhfUGDgXz DEFINITION DEFERRED. * renamed: zcl_abapgit_ajson_mapping :: lcl_mapping_fields CLASS kHGwlpuwVGRXmbkWZJMoTFhfUGDgXz DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_mapping. METHODS constructor IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields OPTIONAL. PROTECTED SECTION. PRIVATE SECTION. DATA mt_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields. ENDCLASS. * renamed: zcl_abapgit_ajson_mapping :: lcl_rename CLASS kHGwlpuwVGRXmbkWZJMocwrelrEIET DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_mapping. METHODS constructor IMPORTING it_rename_map TYPE zif_abapgit_ajson_mapping~tty_rename_map iv_rename_by TYPE i. PROTECTED SECTION. PRIVATE SECTION. DATA mt_rename_map TYPE zif_abapgit_ajson_mapping~tty_rename_map. DATA mv_rename_by TYPE i. ENDCLASS. * renamed: zcl_abapgit_ajson_mapping :: lcl_mapping_to_upper CLASS kHGwlpuwVGRXmbkWZJMoayhtkOTSGN DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_mapping. METHODS constructor IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields OPTIONAL. PROTECTED SECTION. PRIVATE SECTION. DATA mi_mapping_fields TYPE REF TO zif_abapgit_ajson_mapping. ENDCLASS. * renamed: zcl_abapgit_ajson_mapping :: lcl_mapping_to_lower CLASS kHGwlpuwVGRXmbkWZJMoIaLFAtEmIg DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_mapping. METHODS constructor IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields OPTIONAL. PROTECTED SECTION. PRIVATE SECTION. DATA mi_mapping_fields TYPE REF TO zif_abapgit_ajson_mapping. ENDCLASS. * renamed: zcl_abapgit_ajson_mapping :: lcl_mapping_camel CLASS kHGwlpuwVGRXmbkWZJMoYWDnXPYsQA DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_mapping. METHODS constructor IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields OPTIONAL iv_first_json_upper TYPE abap_bool DEFAULT abap_true. PROTECTED SECTION. PRIVATE SECTION. DATA mv_first_json_upper TYPE abap_bool. DATA mi_mapping_fields TYPE REF TO zif_abapgit_ajson_mapping. ENDCLASS. * renamed: zcl_abapgit_ajson_mapping :: lcl_compound_mapper CLASS kHGwlpuwVGRXmbkWZJMooAlevhaDMg DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_mapping. METHODS constructor IMPORTING it_queue TYPE zif_abapgit_ajson_mapping=>ty_table_of. PROTECTED SECTION. PRIVATE SECTION. DATA mt_queue TYPE zif_abapgit_ajson_mapping=>ty_table_of. ENDCLASS. * renamed: zcl_abapgit_ajson_mapping :: lcl_to_snake CLASS kHGwlpuwVGRXmbkWZJMorCLylKulMM DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_mapping. ENDCLASS. * renamed: zcl_abapgit_ajson_mapping :: lcl_to_camel CLASS kHGwlpuwVGRXmbkWZJMoWRsLzEdjUi DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_mapping. METHODS constructor IMPORTING iv_first_json_upper TYPE abap_bool. PRIVATE SECTION. DATA mv_first_json_upper TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_ajson_mapping DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. CONSTANTS: BEGIN OF rename_by, attr_name TYPE i VALUE 0, full_path TYPE i VALUE 1, pattern TYPE i VALUE 2, " regex type i value 3, " TODO add if needed in future END OF rename_by. CLASS-METHODS create_camel_case " DEPRECATED IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL iv_first_json_upper TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. CLASS-METHODS create_upper_case IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. CLASS-METHODS create_lower_case IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. CLASS-METHODS create_field_mapping " DEPRECATED IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. CLASS-METHODS create_rename IMPORTING it_rename_map TYPE zif_abapgit_ajson_mapping=>tty_rename_map iv_rename_by TYPE i DEFAULT rename_by-attr_name RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. CLASS-METHODS create_compound_mapper IMPORTING ii_mapper1 TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL ii_mapper2 TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL ii_mapper3 TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL it_more TYPE zif_abapgit_ajson_mapping=>ty_table_of OPTIONAL RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. CLASS-METHODS create_to_snake_case RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. CLASS-METHODS create_to_camel_case IMPORTING iv_first_json_upper TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_ajson_utilities DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS new RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson_utilities. METHODS diff IMPORTING !iv_json_a TYPE string OPTIONAL !iv_json_b TYPE string OPTIONAL !io_json_a TYPE REF TO zif_abapgit_ajson OPTIONAL !io_json_b TYPE REF TO zif_abapgit_ajson OPTIONAL !iv_keep_empty_arrays TYPE abap_bool DEFAULT abap_false EXPORTING !eo_insert TYPE REF TO zif_abapgit_ajson !eo_delete TYPE REF TO zif_abapgit_ajson !eo_change TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error . METHODS merge IMPORTING !iv_json_a TYPE string OPTIONAL !iv_json_b TYPE string OPTIONAL !io_json_a TYPE REF TO zif_abapgit_ajson OPTIONAL !io_json_b TYPE REF TO zif_abapgit_ajson OPTIONAL !iv_keep_empty_arrays TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error . METHODS sort IMPORTING !iv_json TYPE string OPTIONAL !io_json TYPE REF TO zif_abapgit_ajson OPTIONAL RETURNING VALUE(rv_sorted) TYPE string RAISING zcx_abapgit_ajson_error . METHODS is_equal IMPORTING !iv_json_a TYPE string OPTIONAL !iv_json_b TYPE string OPTIONAL !ii_json_a TYPE REF TO zif_abapgit_ajson OPTIONAL !ii_json_b TYPE REF TO zif_abapgit_ajson OPTIONAL RETURNING VALUE(rv_yes) TYPE abap_bool RAISING zcx_abapgit_ajson_error . PROTECTED SECTION. PRIVATE SECTION. DATA mo_json_a TYPE REF TO zif_abapgit_ajson . DATA mo_json_b TYPE REF TO zif_abapgit_ajson . DATA mo_insert TYPE REF TO zif_abapgit_ajson . DATA mo_delete TYPE REF TO zif_abapgit_ajson . DATA mo_change TYPE REF TO zif_abapgit_ajson . METHODS normalize_input IMPORTING !iv_json TYPE string OPTIONAL !io_json TYPE REF TO zif_abapgit_ajson OPTIONAL RETURNING VALUE(ro_json) TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error . METHODS diff_a_b IMPORTING !iv_path TYPE string RAISING zcx_abapgit_ajson_error . METHODS diff_b_a IMPORTING !iv_path TYPE string !iv_array TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_ajson_error . METHODS delete_empty_nodes IMPORTING !io_json TYPE REF TO zif_abapgit_ajson !iv_keep_empty_arrays TYPE abap_bool RAISING zcx_abapgit_ajson_error . ENDCLASS. CLASS zcl_abapgit_aff_registry DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_aff_registry. CONSTANTS c_aff_feature TYPE string VALUE 'AFF'. METHODS constructor. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_registry_entry, obj_type TYPE tadir-object, experimental TYPE abap_bool, END OF ty_registry_entry. CLASS-DATA: gt_registry TYPE HASHED TABLE OF ty_registry_entry WITH UNIQUE KEY obj_type. DATA mv_aff_enabled TYPE abap_bool. CLASS-METHODS initialize_registry_table. CLASS-METHODS: register IMPORTING iv_obj_type TYPE tadir-object iv_experimental TYPE abap_bool DEFAULT abap_false. ENDCLASS. CLASS zcl_abapgit_json_handler DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_json_abap_mapping, json TYPE string, abap TYPE string, END OF ty_json_abap_mapping . TYPES: ty_json_abap_mappings TYPE STANDARD TABLE OF ty_json_abap_mapping WITH DEFAULT KEY . TYPES: BEGIN OF ty_enum_mapping, path TYPE string, mappings TYPE ty_json_abap_mappings, END OF ty_enum_mapping . TYPES: ty_enum_mappings TYPE TABLE OF ty_enum_mapping WITH DEFAULT KEY . TYPES: BEGIN OF ty_path_value_pair, path TYPE string, value TYPE string, END OF ty_path_value_pair . TYPES: ty_skip_paths TYPE STANDARD TABLE OF ty_path_value_pair WITH KEY path . "! Serializes data to xstring. Type of data is specified in the "! implementing class. "! "! @parameter iv_data | data to be serialized "! @parameter iv_enum_mappings | ABAP/JSON value mappings "! @parameter iv_skip_paths | path/value pairs to be skipped during serialization "! @parameter rv_result | serialized data METHODS serialize IMPORTING !iv_data TYPE data !iv_enum_mappings TYPE ty_enum_mappings OPTIONAL !iv_skip_paths TYPE ty_skip_paths OPTIONAL RETURNING VALUE(rv_result) TYPE xstring RAISING cx_static_check . "! Deserializes xstring into data. The type of data is specified in "! the implementing class "! "! @parameter iv_content | xstring to be deserialized "! @parameter iv_defaults | path-value pairs that apply if value is initial "! @parameter ev_data | data of the xstring METHODS deserialize IMPORTING !iv_content TYPE string !iv_defaults TYPE ty_skip_paths OPTIONAL !iv_enum_mappings TYPE ty_enum_mappings OPTIONAL EXPORTING !ev_data TYPE data RAISING cx_static_check . PROTECTED SECTION. PRIVATE SECTION. METHODS: map2json_original_language CHANGING co_ajson TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error, map2json_custom_enum IMPORTING it_enum_mappings TYPE ty_enum_mappings CHANGING co_ajson TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error, map2json_abap_language_version CHANGING co_ajson TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error, "! Get the enum mapping from object handler, as other enums as well map2abap_abap_language_version CHANGING co_ajson TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error, "! For deserialization map2abap_original_language CHANGING co_ajson TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error, "! For deserialization set_defaults IMPORTING it_defaults TYPE ty_skip_paths CHANGING co_ajson TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error, map2abap_custom_enum IMPORTING it_enum_mappings TYPE ty_enum_mappings CHANGING co_ajson TYPE REF TO zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. ENDCLASS. CLASS zcl_abapgit_json_path DEFINITION CREATE PUBLIC. PUBLIC SECTION. METHODS: serialize IMPORTING iv_json TYPE string RETURNING VALUE(rt_result) TYPE string_table RAISING zcx_abapgit_exception. METHODS: deserialize IMPORTING it_json_path TYPE string_table RETURNING VALUE(rv_result) TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_dependencies DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS resolve CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_dependency, depname TYPE dd02l-tabname, deptyp TYPE c LENGTH 4, deplocal TYPE dd02l-as4local, refname TYPE dd02l-tabname, reftyp TYPE c LENGTH 4, kind TYPE c LENGTH 1, END OF ty_dependency . TYPES: ty_dedenpencies TYPE STANDARD TABLE OF ty_dependency WITH NON-UNIQUE DEFAULT KEY . TYPES: BEGIN OF ty_item, obj_type TYPE tadir-object, obj_name TYPE tadir-obj_name, devclass TYPE devclass, END OF ty_item . CLASS-METHODS resolve_ddic CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . CLASS-METHODS get_ddls_dependencies IMPORTING iv_ddls_name TYPE tadir-obj_name RETURNING VALUE(rt_dependency) TYPE ty_dedenpencies. CLASS-METHODS resolve_packages CHANGING ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. ENDCLASS. CLASS zcl_abapgit_file_deserialize DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS get_results 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 . PROTECTED SECTION. PRIVATE SECTION. 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 prioritize_deser IMPORTING !ii_log TYPE REF TO zif_abapgit_log !it_results TYPE zif_abapgit_definitions=>ty_results_tt RETURNING VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_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 . ENDCLASS. CLASS zcl_abapgit_filename_logic DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CONSTANTS: BEGIN OF c_package_file, obj_name TYPE c LENGTH 7 VALUE 'package', sep1 TYPE c LENGTH 1 VALUE '.', obj_type TYPE c LENGTH 4 VALUE 'devc', sep2 TYPE c LENGTH 1 VALUE '.', extension TYPE c LENGTH 3 VALUE 'xml', END OF c_package_file. CONSTANTS: BEGIN OF c_json_file, extension TYPE c LENGTH 4 VALUE 'json', END OF c_json_file. CLASS-METHODS detect_obj_definition IMPORTING !iv_type TYPE string !iv_ext TYPE string EXPORTING !ev_is_xml TYPE abap_bool !ev_is_json TYPE abap_bool. CLASS-METHODS is_obj_definition_file IMPORTING !iv_filename TYPE string RETURNING VALUE(rv_yes) TYPE abap_bool. CLASS-METHODS file_to_object IMPORTING !iv_filename TYPE string !iv_path TYPE string !iv_devclass TYPE devclass OPTIONAL !io_dot TYPE REF TO zcl_abapgit_dot_abapgit EXPORTING !es_item TYPE zif_abapgit_definitions=>ty_item !ev_is_xml TYPE abap_bool !ev_is_json TYPE abap_bool RAISING zcx_abapgit_exception . CLASS-METHODS i18n_file_to_object IMPORTING !iv_filename TYPE string !iv_path TYPE string EXPORTING !es_item TYPE zif_abapgit_definitions=>ty_item !ev_lang TYPE laiso !ev_ext TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS object_to_file IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_ext TYPE string !iv_extra TYPE clike OPTIONAL RETURNING VALUE(rv_filename) TYPE string . CLASS-METHODS object_to_i18n_file IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_lang TYPE laiso !iv_ext TYPE string RETURNING VALUE(rv_filename) TYPE string. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA: go_aff_registry TYPE REF TO zif_abapgit_aff_registry. CLASS-METHODS name_escape IMPORTING !iv_name TYPE csequence RETURNING VALUE(rv_name) TYPE string. CLASS-METHODS name_unescape IMPORTING !iv_name TYPE csequence RETURNING VALUE(rv_name) TYPE string. CLASS-METHODS map_filename_to_object IMPORTING !iv_filename TYPE string !iv_path TYPE string !iv_package TYPE devclass !io_dot TYPE REF TO zcl_abapgit_dot_abapgit CHANGING cs_item TYPE zif_abapgit_definitions=>ty_item RAISING zcx_abapgit_exception. CLASS-METHODS map_object_to_filename IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item CHANGING cv_filename TYPE string RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_folder_logic DEFINITION CREATE PUBLIC . PUBLIC SECTION. METHODS package_to_path IMPORTING !iv_top TYPE devclass !io_dot TYPE REF TO zcl_abapgit_dot_abapgit !iv_package TYPE devclass RETURNING VALUE(rv_path) TYPE string RAISING zcx_abapgit_exception . METHODS path_to_package IMPORTING !iv_top TYPE devclass !io_dot TYPE REF TO zcl_abapgit_dot_abapgit !iv_path TYPE string !iv_create_if_not_exists TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rv_package) TYPE devclass RAISING zcx_abapgit_exception . CLASS-METHODS get_instance RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_folder_logic . PROTECTED SECTION. METHODS get_parent IMPORTING !iv_top TYPE devclass !iv_package TYPE devclass RETURNING VALUE(rv_parent) TYPE devclass RAISING zcx_abapgit_exception . PRIVATE SECTION. TYPES: BEGIN OF ty_devclass_info, devclass TYPE devclass, namespace TYPE namespace, parentcl TYPE parentcl, END OF ty_devclass_info . TYPES: ty_devclass_info_tt TYPE SORTED TABLE OF ty_devclass_info WITH UNIQUE KEY devclass . DATA mt_top_subpackages TYPE ty_devclass_info_tt . DATA mt_parent TYPE ty_devclass_info_tt . ENDCLASS. CLASS zcl_abapgit_item_graph DEFINITION CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING !it_items TYPE zif_abapgit_definitions=>ty_items_tt . METHODS add_edge IMPORTING !is_from TYPE zif_abapgit_definitions=>ty_item !is_to TYPE zif_abapgit_definitions=>ty_item . METHODS has_vertices RETURNING VALUE(rv_bool) TYPE abap_bool . METHODS get_next IMPORTING !ii_log TYPE REF TO zif_abapgit_log RETURNING VALUE(rs_item) TYPE zif_abapgit_definitions=>ty_item . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_edge, from TYPE zif_abapgit_definitions=>ty_item, to TYPE zif_abapgit_definitions=>ty_item, END OF ty_edge. DATA mt_vertices TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_item WITH DEFAULT KEY. DATA mt_edges TYPE STANDARD TABLE OF ty_edge WITH DEFAULT KEY WITH NON-UNIQUE SORTED KEY sec_to COMPONENTS to WITH NON-UNIQUE SORTED KEY sec_from COMPONENTS from. DATA mv_warning TYPE abap_bool. METHODS remove_vertex IMPORTING iv_index TYPE i. ENDCLASS. CLASS zcl_abapgit_objects_activation DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS add IMPORTING !iv_type TYPE trobjtype !iv_name TYPE clike !iv_delete TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . CLASS-METHODS add_item IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RAISING zcx_abapgit_exception . CLASS-METHODS activate IMPORTING !iv_ddic TYPE abap_bool DEFAULT abap_false !ii_log TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . CLASS-METHODS clear . CLASS-METHODS is_ddic_type IMPORTING !iv_obj_type TYPE trobjtype RETURNING VALUE(rv_result) TYPE abap_bool . 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_classes, object TYPE trobjtype, clsname TYPE seoclsname, END OF ty_classes. CONSTANTS: c_domain TYPE c LENGTH 9 VALUE 'DOMA DOMD', c_types TYPE c LENGTH 50 VALUE 'DTEL DTED TABL TABD SQLT SQLD TTYP TTYD VIEW VIED', c_technset TYPE c LENGTH 24 VALUE 'TABT VIET SQTT INDX XINX', c_f4_objects TYPE c LENGTH 35 VALUE 'SHLP SHLD MCOB MCOD MACO MACD MCID', c_enqueue TYPE c LENGTH 9 VALUE 'ENQU ENQD', c_sqsc TYPE c LENGTH 4 VALUE 'SQSC', c_stob TYPE c LENGTH 4 VALUE 'STOB', c_ntab TYPE c LENGTH 14 VALUE 'NTTT NTTB NTDT', c_ddls TYPE c LENGTH 24 VALUE 'DDLS DRUL DTDC DTEB', c_switches TYPE c LENGTH 24 VALUE 'SF01 SF02 SFSW SFBS SFBF', c_para TYPE c LENGTH 4 VALUE 'PARA', " can be referenced by DTEL c_enhd TYPE c LENGTH 4 VALUE 'ENHD'. CLASS-DATA: gt_classes TYPE STANDARD TABLE OF ty_classes WITH DEFAULT KEY . CLASS-DATA: gt_objects TYPE TABLE OF dwinactiv . CLASS-METHODS update_where_used IMPORTING !ii_log TYPE REF TO zif_abapgit_log. CLASS-METHODS use_new_activation_logic RETURNING VALUE(rv_use_new_activation_logic) TYPE abap_bool . CLASS-METHODS activate_new IMPORTING !iv_ddic TYPE abap_bool DEFAULT abap_false !ii_log TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . CLASS-METHODS activate_old IMPORTING !iv_ddic TYPE abap_bool DEFAULT abap_false !ii_log TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . CLASS-METHODS activate_ddic IMPORTING !ii_log TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . CLASS-METHODS add_errors_and_warnings_to_log IMPORTING !iv_logname TYPE ddmass-logname !ii_log TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . CLASS-METHODS add_activation_errors_to_log IMPORTING !io_checklist TYPE REF TO cl_wb_checklist !ii_log TYPE REF TO zif_abapgit_log RETURNING VALUE(rv_try_again) TYPE abap_bool RAISING zcx_abapgit_exception . CLASS-METHODS is_non_ddic_active IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RETURNING VALUE(rv_active) TYPE abap_bool RAISING zcx_abapgit_exception . CLASS-METHODS is_ddic_active IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RETURNING VALUE(rv_active) TYPE abap_bool RAISING zcx_abapgit_exception . CLASS-METHODS get_ddic_type IMPORTING !iv_obj_type TYPE clike !iv_obj_name TYPE clike EXPORTING !ev_type TYPE ddobjtyp !ev_name TYPE ddobjname !ev_id TYPE ddobjectid RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_objects_check DEFINITION CREATE PUBLIC . PUBLIC SECTION. 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 class_constructor. 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 . PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA: gi_exit TYPE REF TO zif_abapgit_exit. 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 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 determine_transport_request IMPORTING io_repo TYPE REF TO zcl_abapgit_repo iv_transport_type TYPE zif_abapgit_definitions=>ty_transport_type RETURNING VALUE(rv_transport_request) TYPE trkorr. CLASS-METHODS check_multiple_files IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_objects_files DEFINITION CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS new IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_path TYPE string OPTIONAL RETURNING VALUE(ro_files) TYPE REF TO zcl_abapgit_objects_files. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_path TYPE string OPTIONAL . METHODS add_string IMPORTING !iv_extra TYPE clike OPTIONAL !iv_ext TYPE string !iv_string TYPE string RAISING zcx_abapgit_exception . METHODS read_string IMPORTING !iv_extra TYPE clike OPTIONAL !iv_ext TYPE string RETURNING VALUE(rv_string) TYPE string RAISING zcx_abapgit_exception . METHODS add_xml IMPORTING !iv_extra TYPE clike OPTIONAL !ii_xml TYPE REF TO zif_abapgit_xml_output !iv_normalize TYPE abap_bool DEFAULT abap_true !is_metadata TYPE zif_abapgit_definitions=>ty_metadata OPTIONAL RAISING zcx_abapgit_exception . METHODS read_xml IMPORTING !iv_extra TYPE clike OPTIONAL RETURNING VALUE(ri_xml) TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS read_abap IMPORTING !iv_extra TYPE clike OPTIONAL !iv_error TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rt_abap) TYPE abaptxt255_tab RAISING zcx_abapgit_exception . METHODS add_abap IMPORTING !iv_extra TYPE clike OPTIONAL !it_abap TYPE STANDARD TABLE RAISING zcx_abapgit_exception . METHODS add IMPORTING !is_file TYPE zif_abapgit_git_definitions=>ty_file . METHODS add_raw IMPORTING !iv_extra TYPE clike OPTIONAL !iv_ext TYPE string !iv_data TYPE xstring. METHODS read_raw IMPORTING !iv_extra TYPE clike OPTIONAL !iv_ext TYPE string RETURNING VALUE(rv_data) TYPE xstring RAISING zcx_abapgit_exception . METHODS get_files RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt . METHODS set_files IMPORTING !it_files TYPE zif_abapgit_git_definitions=>ty_files_tt . METHODS get_accessed_files RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt . METHODS contains_file IMPORTING !iv_extra TYPE clike OPTIONAL !iv_ext TYPE string RETURNING VALUE(rv_present) TYPE abap_bool . METHODS get_file_pattern RETURNING VALUE(rv_pattern) TYPE string . METHODS is_json_metadata RETURNING VALUE(rv_result) TYPE abap_bool. METHODS add_i18n_file IMPORTING !ii_i18n_file TYPE REF TO zif_abapgit_i18n_file RAISING zcx_abapgit_exception . METHODS read_i18n_files RETURNING VALUE(rt_i18n_files) TYPE zif_abapgit_i18n_file=>ty_table_of RAISING zcx_abapgit_exception . PROTECTED SECTION. METHODS read_file IMPORTING !iv_filename TYPE string !iv_error TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rv_data) TYPE xstring RAISING zcx_abapgit_exception . PRIVATE SECTION. DATA ms_item TYPE zif_abapgit_definitions=>ty_item . DATA mt_accessed_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt . DATA mt_files TYPE zif_abapgit_git_definitions=>ty_files_tt . DATA mv_path TYPE string . METHODS mark_accessed IMPORTING !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path !iv_file TYPE zif_abapgit_git_definitions=>ty_file-filename !iv_sha1 TYPE zif_abapgit_git_definitions=>ty_file-sha1. ENDCLASS. CLASS zcl_abapgit_serialize DEFINITION CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING !io_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit OPTIONAL !is_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings OPTIONAL RAISING zcx_abapgit_exception . METHODS on_end_of_task IMPORTING !p_task TYPE clike ##NEEDED. METHODS serialize IMPORTING !iv_package TYPE devclass OPTIONAL !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt !ii_log TYPE REF TO zif_abapgit_log OPTIONAL !iv_force_sequential TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt RAISING zcx_abapgit_exception . METHODS files_local IMPORTING !iv_package TYPE devclass !ii_log TYPE REF TO zif_abapgit_log !it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt OPTIONAL !ii_data_config TYPE REF TO zif_abapgit_data_config OPTIONAL RETURNING VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt RAISING zcx_abapgit_exception . PROTECTED SECTION. TYPES: BEGIN OF ty_unsupported_count, obj_type TYPE tadir-object, obj_name TYPE tadir-obj_name, count TYPE i, END OF ty_unsupported_count . TYPES: ty_unsupported_count_tt TYPE HASHED TABLE OF ty_unsupported_count WITH UNIQUE KEY obj_type . TYPES: ty_char32 TYPE c LENGTH 32 . CLASS-DATA gv_max_processes TYPE i . DATA mt_files TYPE zif_abapgit_definitions=>ty_files_item_tt . DATA mv_free TYPE i . DATA mi_log TYPE REF TO zif_abapgit_log . DATA mv_group TYPE rzlli_apcl . DATA mo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit. DATA ms_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings. DATA ms_i18n_params TYPE zif_abapgit_definitions=>ty_i18n_params. DATA mo_abap_language_version TYPE REF TO zcl_abapgit_abap_language_vers. METHODS add_apack IMPORTING !iv_package TYPE devclass CHANGING !ct_files TYPE zif_abapgit_definitions=>ty_files_item_tt RAISING zcx_abapgit_exception . METHODS add_data IMPORTING !ii_data_config TYPE REF TO zif_abapgit_data_config CHANGING !ct_files TYPE zif_abapgit_definitions=>ty_files_item_tt RAISING zcx_abapgit_exception . METHODS add_dot_abapgit CHANGING !ct_files TYPE zif_abapgit_definitions=>ty_files_item_tt RAISING zcx_abapgit_exception . METHODS add_to_return IMPORTING !iv_path TYPE string !is_file_item TYPE zif_abapgit_objects=>ty_serialization . METHODS run_parallel IMPORTING !is_tadir TYPE zif_abapgit_definitions=>ty_tadir !iv_task TYPE ty_char32 RAISING zcx_abapgit_exception . METHODS run_sequential IMPORTING !is_tadir TYPE zif_abapgit_definitions=>ty_tadir RAISING zcx_abapgit_exception . METHODS add_objects IMPORTING !iv_package TYPE devclass !ii_log TYPE REF TO zif_abapgit_log !it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt OPTIONAL CHANGING VALUE(ct_files) TYPE zif_abapgit_definitions=>ty_files_item_tt RAISING zcx_abapgit_exception . METHODS determine_max_processes IMPORTING !iv_force_sequential TYPE abap_bool DEFAULT abap_false iv_package TYPE devclass RETURNING VALUE(rv_processes) TYPE i RAISING zcx_abapgit_exception . METHODS filter_unsupported_objects CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt . METHODS filter_ignored_objects IMPORTING !iv_package TYPE devclass CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS is_parallelization_possible RETURNING VALUE(rv_result) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_tadir DEFINITION FINAL CREATE PRIVATE FRIENDS ZCL_ABAPGIT_factory . PUBLIC SECTION. INTERFACES zif_abapgit_tadir . PROTECTED SECTION. PRIVATE SECTION. METHODS check_exists IMPORTING !it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RETURNING VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . METHODS build IMPORTING !iv_package TYPE tadir-devclass !io_dot TYPE REF TO zcl_abapgit_dot_abapgit !iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false !iv_only_local_objects TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rt_tadir) TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . METHODS select_objects IMPORTING !iv_package TYPE tadir-devclass !iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false !iv_only_local_objects TYPE abap_bool EXPORTING !et_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt !et_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . METHODS add_local_packages IMPORTING !it_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . METHODS add_namespaces IMPORTING !iv_package TYPE devclass CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . METHODS add_namespace IMPORTING !iv_package TYPE devclass !iv_object TYPE csequence CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt !ct_tadir_nspc TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . METHODS determine_path IMPORTING !iv_package TYPE tadir-devclass !io_dot TYPE REF TO zcl_abapgit_dot_abapgit CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_ecatt_config_downl DEFINITION INHERITING FROM cl_apl_ecatt_config_download CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_download. METHODS: download REDEFINITION. PROTECTED SECTION. METHODS: download_data REDEFINITION. PRIVATE SECTION. DATA: mv_xml_stream TYPE xstring. ENDCLASS. CLASS zcl_abapgit_ecatt_config_upl DEFINITION INHERITING FROM cl_apl_ecatt_config_upload FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_upload. PROTECTED SECTION. METHODS: upload_data_from_stream REDEFINITION. PRIVATE SECTION. DATA: mv_external_xml TYPE xstring. ENDCLASS. CLASS zcl_abapgit_ecatt_data_downl DEFINITION INHERITING FROM cl_apl_ecatt_data_download CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_download. METHODS: download REDEFINITION. PROTECTED SECTION. METHODS: download_data REDEFINITION. PRIVATE SECTION. DATA: mv_xml_stream TYPE xstring. ENDCLASS. CLASS zcl_abapgit_ecatt_data_upload DEFINITION INHERITING FROM cl_apl_ecatt_data_upload FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_upload. METHODS upload REDEFINITION. PROTECTED SECTION. METHODS: upload_data_from_stream REDEFINITION. PRIVATE SECTION. DATA: mv_external_xml TYPE xstring, BEGIN OF ms_current_object, s_obj_type TYPE etobj_type, d_obj_name TYPE etobjdname, d_obj_ver TYPE etobjdver, END OF ms_current_object, mx_ecatt_apl TYPE REF TO cx_ecatt_apl. METHODS on_ev_object_saved FOR EVENT ev_object_saved OF cl_apl_ecatt_object IMPORTING ex_ecatt_object. ENDCLASS. CLASS zcl_abapgit_ecatt_helper DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS: build_xml_of_object IMPORTING iv_object_name TYPE etobj_name iv_object_version TYPE etobj_ver iv_object_type TYPE etobj_type io_download TYPE REF TO cl_apl_ecatt_download RETURNING VALUE(rv_xml_stream) TYPE xstring RAISING zcx_abapgit_exception, download_data IMPORTING ii_template_over_all TYPE REF TO if_ixml_document RETURNING VALUE(rv_xml_stream) TYPE xstring, upload_data_from_stream IMPORTING iv_xml_stream TYPE xstring RETURNING VALUE(ri_template_over_all) TYPE REF TO if_ixml_document RAISING cx_ecatt_apl. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_xml TYPE i VALUE 1. " downport of if_apl_ecatt_xml=>co_xml ENDCLASS. CLASS zcl_abapgit_ecatt_script_downl DEFINITION INHERITING FROM cl_apl_ecatt_script_download CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_download. METHODS: download REDEFINITION. PROTECTED SECTION. METHODS: download_data REDEFINITION. PRIVATE SECTION. DATA: mv_xml_stream TYPE xstring, mi_script_node TYPE REF TO if_ixml_element. METHODS: set_script_to_template RAISING cx_ecatt_apl, set_control_data_for_tcd IMPORTING is_param TYPE etpar_gui io_params TYPE REF TO cl_apl_ecatt_params RAISING cx_ecatt_apl, escape_control_data IMPORTING ii_element TYPE REF TO if_ixml_element iv_tabname TYPE string iv_node TYPE string RAISING cx_ecatt_apl, set_blob_to_template RAISING cx_ecatt_apl, set_artmp_to_template RAISING cx_ecatt_apl. ENDCLASS. CLASS zcl_abapgit_ecatt_script_upl DEFINITION INHERITING FROM cl_apl_ecatt_script_upload FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_upload. PROTECTED SECTION. METHODS: upload_data_from_stream REDEFINITION. PRIVATE SECTION. DATA: mv_external_xml TYPE xstring. ENDCLASS. CLASS zcl_abapgit_ecatt_sp_download DEFINITION INHERITING FROM cl_apl_ecatt_download CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_download. METHODS: download REDEFINITION. PROTECTED SECTION. METHODS: download_data REDEFINITION. PRIVATE SECTION. DATA: mv_xml_stream TYPE xstring. METHODS: set_sp_data_to_template. ENDCLASS. CLASS zcl_abapgit_ecatt_sp_upload DEFINITION INHERITING FROM cl_apl_ecatt_upload FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_upload. METHODS: upload REDEFINITION. PROTECTED SECTION. METHODS: upload_data_from_stream REDEFINITION, get_ecatt_sp RAISING cx_ecatt_apl . PRIVATE SECTION. DATA: mv_external_xml TYPE xstring. ENDCLASS. CLASS zcl_abapgit_ecatt_system_downl DEFINITION INHERITING FROM cl_apl_ecatt_systems_download CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_download. METHODS: download REDEFINITION. PROTECTED SECTION. METHODS: download_data REDEFINITION. PRIVATE SECTION. DATA: mv_xml_stream TYPE xstring. METHODS: set_systems_data_to_template. ENDCLASS. CLASS zcl_abapgit_ecatt_system_upl DEFINITION INHERITING FROM cl_apl_ecatt_systems_upload FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_upload. PROTECTED SECTION. METHODS: upload_data_from_stream REDEFINITION. PRIVATE SECTION. DATA: mv_external_xml TYPE xstring. ENDCLASS. CLASS zcl_abapgit_ecatt_val_obj_down DEFINITION INHERITING FROM cl_apl_ecatt_download CREATE PUBLIC. PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_download. METHODS: download REDEFINITION. PROTECTED SECTION. DATA: mi_objects_node TYPE REF TO if_ixml_element. METHODS: download_data REDEFINITION. PRIVATE SECTION. DATA: mv_xml_stream TYPE xstring. METHODS: set_ecatt_impl_detail, set_ecatt_flags, set_business_msgs. ENDCLASS. CLASS zcl_abapgit_ecatt_val_obj_upl DEFINITION INHERITING FROM cl_apl_ecatt_upload FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_ecatt_upload. METHODS: upload REDEFINITION. PROTECTED SECTION. METHODS: upload_data_from_stream REDEFINITION, get_business_msgs_from_dom RAISING cx_ecatt_apl, get_impl_detail_from_dom RAISING cx_ecatt_apl, get_vo_flags_from_dom RAISING cx_ecatt_apl. PRIVATE SECTION. DATA: mv_external_xml TYPE xstring. ENDCLASS. CLASS zcl_abapgit_object_enho_badi DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING is_item TYPE zif_abapgit_definitions=>ty_item. INTERFACES: zif_abapgit_object_enho. PROTECTED SECTION. PRIVATE SECTION. DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. ENDCLASS. CLASS zcl_abapgit_object_enho_class DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING is_item TYPE zif_abapgit_definitions=>ty_item io_files TYPE REF TO zcl_abapgit_objects_files. INTERFACES: zif_abapgit_object_enho. PROTECTED SECTION. PRIVATE SECTION. METHODS: serialize_includes IMPORTING io_class TYPE REF TO cl_enh_tool_class RAISING zcx_abapgit_exception, deserialize_includes IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input io_class TYPE REF TO cl_enh_tool_class RAISING zcx_abapgit_exception. DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. DATA: mo_files TYPE REF TO zcl_abapgit_objects_files. ENDCLASS. CLASS zcl_abapgit_object_enho_clif DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS deserialize IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input !io_clif TYPE REF TO cl_enh_tool_clif RAISING zcx_abapgit_exception cx_enh_root . CLASS-METHODS serialize IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output !io_clif TYPE REF TO cl_enh_tool_clif RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_enho_fugr DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING is_item TYPE zif_abapgit_definitions=>ty_item io_files TYPE REF TO zcl_abapgit_objects_files. INTERFACES: zif_abapgit_object_enho. PROTECTED SECTION. PRIVATE SECTION. DATA: ms_item TYPE zif_abapgit_definitions=>ty_item, mo_files TYPE REF TO zcl_abapgit_objects_files. ENDCLASS. CLASS zcl_abapgit_object_enho_hook DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING is_item TYPE zif_abapgit_definitions=>ty_item io_files TYPE REF TO zcl_abapgit_objects_files. INTERFACES: zif_abapgit_object_enho. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_spaces, full_name TYPE string, spaces TYPE STANDARD TABLE OF i WITH DEFAULT KEY, END OF ty_spaces. TYPES: ty_spaces_tt TYPE STANDARD TABLE OF ty_spaces WITH DEFAULT KEY. TYPES: BEGIN OF ty_file, name TYPE string, file TYPE string, END OF ty_file. TYPES: ty_files TYPE HASHED TABLE OF ty_file WITH UNIQUE KEY name. CONSTANTS c_enhancement TYPE string VALUE 'ENHANCEMENT 0 *.' ##NO_TEXT. CONSTANTS c_endenhancement TYPE string VALUE 'ENDENHANCEMENT.' ##NO_TEXT. DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. DATA: mo_files TYPE REF TO zcl_abapgit_objects_files. METHODS add_sources CHANGING !ct_enhancements TYPE enh_hook_impl_it !ct_files TYPE ty_files RAISING zcx_abapgit_exception . METHODS read_sources CHANGING !ct_enhancements TYPE enh_hook_impl_it !ct_files TYPE ty_files RAISING zcx_abapgit_exception . METHODS hook_impl_deserialize IMPORTING !it_spaces TYPE ty_spaces_tt CHANGING !ct_impl TYPE enh_hook_impl_it RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_enho_intf DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING is_item TYPE zif_abapgit_definitions=>ty_item io_files TYPE REF TO zcl_abapgit_objects_files. INTERFACES: zif_abapgit_object_enho. PROTECTED SECTION. PRIVATE SECTION. DATA: ms_item TYPE zif_abapgit_definitions=>ty_item, mo_files TYPE REF TO zcl_abapgit_objects_files. ENDCLASS. CLASS zcl_abapgit_object_enho_wdyc DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING is_item TYPE zif_abapgit_definitions=>ty_item. INTERFACES: zif_abapgit_object_enho. PROTECTED SECTION. PRIVATE SECTION. DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. ENDCLASS. CLASS zcl_abapgit_object_enho_wdyn DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING is_item TYPE zif_abapgit_definitions=>ty_item. INTERFACES: zif_abapgit_object_enho. PROTECTED SECTION. PRIVATE SECTION. DATA: ms_item TYPE zif_abapgit_definitions=>ty_item. ENDCLASS. CLASS zcl_abapgit_object_enhs_badi_d DEFINITION. PUBLIC SECTION. INTERFACES: zif_abapgit_object_enhs. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_enhs_hook_d DEFINITION. PUBLIC SECTION. INTERFACES: zif_abapgit_object_enhs. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_hook_defifnition, pgmid TYPE pgmid, obj_name TYPE trobj_name, obj_type TYPE trobjtype, main_type TYPE trobjtype, main_name TYPE eu_aname, program TYPE progname, def_hooks TYPE enh_hook_def_ext_it, END OF ty_hook_defifnition. ENDCLASS. CLASS zcl_abapgit_adt_link DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS jump IMPORTING !iv_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name !iv_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type !iv_sub_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name OPTIONAL !iv_line_number TYPE i OPTIONAL RAISING zcx_abapgit_exception. CLASS-METHODS link_transport IMPORTING iv_transport TYPE trkorr RETURNING VALUE(rv_link) TYPE string. PROTECTED SECTION. CLASS-METHODS generate IMPORTING !iv_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name !iv_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type !iv_sub_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name OPTIONAL !iv_line_number TYPE i OPTIONAL RETURNING VALUE(rv_result) TYPE string RAISING zcx_abapgit_exception. PRIVATE SECTION. CLASS-METHODS get_adt_objects_and_names IMPORTING iv_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name iv_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type EXPORTING eo_adt_uri_mapper TYPE REF TO object eo_adt_objectref TYPE REF TO object ev_program TYPE progname ev_include TYPE progname RAISING zcx_abapgit_exception. CLASS-METHODS is_adt_jump_possible IMPORTING io_object TYPE REF TO cl_wb_object io_adt TYPE REF TO object RETURNING VALUE(rv_is_adt_jump_possible) TYPE abap_bool RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_jumper DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_gui_jumper. PROTECTED SECTION. PRIVATE SECTION. METHODS jump_tr IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RETURNING VALUE(rv_exit) TYPE abap_bool. METHODS jump_wb IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_new_window TYPE abap_bool RETURNING VALUE(rv_exit) TYPE abap_bool. METHODS jump_wb_line IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_sub_obj_name TYPE zif_abapgit_definitions=>ty_item-obj_name !iv_sub_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type !iv_line_number TYPE i !iv_new_window TYPE abap_bool RETURNING VALUE(rv_exit) TYPE abap_bool. METHODS jump_bw IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_new_window TYPE abap_bool RETURNING VALUE(rv_exit) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_oo_base DEFINITION ABSTRACT CREATE PROTECTED. PUBLIC SECTION. INTERFACES zif_abapgit_oo_object_fnc . CONSTANTS c_cp_program_type TYPE c LENGTH 1 VALUE 'K'. CONSTANTS c_include_program_type TYPE c LENGTH 1 VALUE 'I'. CONSTANTS c_ip_program_type TYPE c LENGTH 1 VALUE 'J'. PROTECTED SECTION. CLASS-METHODS: convert_attrib_to_vseoattrib IMPORTING iv_clsname TYPE seoclsname it_attributes TYPE zif_abapgit_oo_object_fnc=>ty_obj_attribute_tt RETURNING VALUE(rt_vseoattrib) TYPE seoo_attributes_r. PRIVATE SECTION. CONSTANTS c_docu_state_active TYPE dokstate VALUE 'A'. " See include SDOC_CONSTANTS DATA mv_skip_test_classes TYPE abap_bool . ENDCLASS. CLASS zcl_abapgit_oo_class DEFINITION INHERITING FROM zcl_abapgit_oo_base CREATE PUBLIC FRIENDS ZCL_ABAPGIT_oo_factory. PUBLIC SECTION. METHODS zif_abapgit_oo_object_fnc~create REDEFINITION . METHODS zif_abapgit_oo_object_fnc~create_sotr REDEFINITION . METHODS zif_abapgit_oo_object_fnc~delete REDEFINITION . METHODS zif_abapgit_oo_object_fnc~deserialize_source REDEFINITION . METHODS zif_abapgit_oo_object_fnc~generate_locals REDEFINITION . METHODS zif_abapgit_oo_object_fnc~get_class_properties REDEFINITION . METHODS zif_abapgit_oo_object_fnc~get_includes REDEFINITION . METHODS zif_abapgit_oo_object_fnc~insert_text_pool REDEFINITION . METHODS zif_abapgit_oo_object_fnc~read_sotr REDEFINITION . METHODS zif_abapgit_oo_object_fnc~read_text_pool REDEFINITION . METHODS zif_abapgit_oo_object_fnc~exists REDEFINITION . METHODS zif_abapgit_oo_object_fnc~syntax_check REDEFINITION . PROTECTED SECTION. TYPES: ty_char1 TYPE c LENGTH 1 . TYPES: ty_char2 TYPE c LENGTH 2 . PRIVATE SECTION. CLASS-METHODS update_source_index IMPORTING !iv_clsname TYPE csequence !io_scanner TYPE REF TO cl_oo_source_scanner_class . CLASS-METHODS update_report IMPORTING !iv_program TYPE syrepid !it_source TYPE string_table !iv_package TYPE devclass !iv_version TYPE uccheck RETURNING VALUE(rv_updated) TYPE abap_bool RAISING zcx_abapgit_exception . CLASS-METHODS generate_classpool IMPORTING !iv_name TYPE seoclsname RAISING zcx_abapgit_exception . CLASS-METHODS update_meta IMPORTING !iv_name TYPE seoclsname !iv_exposure TYPE seoexpose !it_source TYPE rswsourcet RAISING zcx_abapgit_exception . CLASS-METHODS determine_method_include IMPORTING !iv_name TYPE seoclsname !iv_method TYPE seocpdname RETURNING VALUE(rv_program) TYPE syrepid RAISING zcx_abapgit_exception . CLASS-METHODS init_scanner IMPORTING !it_source TYPE zif_abapgit_definitions=>ty_string_tt !iv_name TYPE seoclsname RETURNING VALUE(ro_scanner) TYPE REF TO cl_oo_source_scanner_class RAISING zcx_abapgit_exception . CLASS-METHODS update_full_class_include IMPORTING !iv_classname TYPE seoclsname !it_source TYPE string_table !it_methods TYPE cl_oo_source_scanner_class=>type_method_implementations !iv_package TYPE devclass !iv_version TYPE uccheck RAISING zcx_abapgit_exception. CLASS-METHODS create_report IMPORTING !iv_program TYPE syrepid !it_source TYPE string_table !iv_extension TYPE ty_char2 !iv_program_type TYPE ty_char1 !iv_state TYPE r3state !iv_package TYPE devclass !iv_version TYPE uccheck RAISING zcx_abapgit_exception. CLASS-METHODS update_cs_number_of_methods IMPORTING !iv_classname TYPE seoclsname !iv_number_of_impl_methods TYPE i . CLASS-METHODS delete_report IMPORTING !iv_program TYPE syrepid RAISING zcx_abapgit_exception. CLASS-METHODS get_method_includes IMPORTING !iv_classname TYPE seoclsname RETURNING VALUE(rt_includes) TYPE seop_methods_w_include. CLASS-METHODS repair_classpool IMPORTING !is_key TYPE seoclskey RAISING zcx_abapgit_exception . CLASS-METHODS repair_redefinitions IMPORTING !is_key TYPE seoclskey RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_oo_factory DEFINITION. PUBLIC SECTION. CLASS-METHODS: get_by_type IMPORTING iv_object_type TYPE tadir-object RETURNING VALUE(ri_object_oriented_object) TYPE REF TO zif_abapgit_oo_object_fnc, get_by_name IMPORTING iv_object_name TYPE seoclsname RETURNING VALUE(ri_object_oriented_object) TYPE REF TO zif_abapgit_oo_object_fnc RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_oo_interface DEFINITION INHERITING FROM zcl_abapgit_oo_base CREATE PUBLIC FRIENDS ZCL_ABAPGIT_oo_factory. PUBLIC SECTION. METHODS zif_abapgit_oo_object_fnc~create REDEFINITION . METHODS zif_abapgit_oo_object_fnc~delete REDEFINITION . METHODS zif_abapgit_oo_object_fnc~get_includes REDEFINITION . METHODS zif_abapgit_oo_object_fnc~get_interface_properties REDEFINITION . METHODS zif_abapgit_oo_object_fnc~deserialize_source REDEFINITION . METHODS zif_abapgit_oo_object_fnc~exists REDEFINITION . METHODS zif_abapgit_oo_object_fnc~syntax_check REDEFINITION . PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS update_report IMPORTING !iv_program TYPE syrepid !it_source TYPE string_table !iv_package TYPE devclass !iv_version TYPE uccheck RETURNING VALUE(rv_updated) TYPE abap_bool RAISING zcx_abapgit_exception . CLASS-METHODS update_meta IMPORTING !iv_name TYPE seoclsname !it_source TYPE rswsourcet RAISING zcx_abapgit_exception . CLASS-METHODS init_scanner IMPORTING !it_source TYPE zif_abapgit_definitions=>ty_string_tt !iv_name TYPE seoclsname RETURNING VALUE(ro_scanner) TYPE REF TO cl_oo_source_scanner_interface RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_oo_serializer DEFINITION CREATE PUBLIC . PUBLIC SECTION. METHODS serialize_abap_clif_source IMPORTING !is_class_key TYPE seoclskey RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt RAISING zcx_abapgit_exception cx_sy_dyn_call_error . METHODS are_test_classes_skipped RETURNING VALUE(rv_return) TYPE abap_bool . METHODS serialize_locals_imp IMPORTING !is_clskey TYPE seoclskey RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt RAISING zcx_abapgit_exception . METHODS serialize_locals_def IMPORTING !is_clskey TYPE seoclskey RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt RAISING zcx_abapgit_exception . METHODS serialize_testclasses IMPORTING !is_clskey TYPE seoclskey RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt RAISING zcx_abapgit_exception . METHODS serialize_macros IMPORTING !is_clskey TYPE seoclskey RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. DATA mv_skip_testclass TYPE abap_bool . METHODS calculate_skip_testclass IMPORTING !it_source TYPE zif_abapgit_definitions=>ty_string_tt RETURNING VALUE(rv_skip_testclass) TYPE abap_bool . METHODS serialize_abap_old IMPORTING !is_clskey TYPE seoclskey RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt RAISING zcx_abapgit_exception . METHODS serialize_abap_new IMPORTING !is_clskey TYPE seoclskey RETURNING VALUE(rt_source) TYPE zif_abapgit_definitions=>ty_string_tt RAISING zcx_abapgit_exception cx_sy_dyn_call_error . METHODS remove_signatures CHANGING !ct_source TYPE zif_abapgit_definitions=>ty_string_tt . METHODS read_include IMPORTING !is_clskey TYPE seoclskey !iv_type TYPE seop_include_ext_app RETURNING VALUE(rt_source) TYPE seop_source_string RAISING zcx_abapgit_exception. METHODS reduce CHANGING !ct_source TYPE zif_abapgit_definitions=>ty_string_tt . ENDCLASS. CLASS zcl_abapgit_field_rules DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_field_rules. CLASS-METHODS create RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_item, tabname TYPE tabname, fieldname TYPE fieldname, fill_rule TYPE zif_abapgit_field_rules=>ty_fill_rule, END OF ty_item, ty_items TYPE SORTED TABLE OF ty_item WITH UNIQUE KEY tabname fieldname. DATA mt_item TYPE ty_items. METHODS fill_value IMPORTING iv_rule TYPE zif_abapgit_field_rules=>ty_fill_rule iv_package TYPE devclass CHANGING cv_value TYPE any. ENDCLASS. CLASS zcl_abapgit_function_module DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_function_module. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_sap_namespace DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_sap_namespace. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_sap_package DEFINITION CREATE PRIVATE FRIENDS ZCL_ABAPGIT_factory . PUBLIC SECTION. INTERFACES zif_abapgit_sap_package . METHODS constructor IMPORTING !iv_package TYPE devclass . PROTECTED SECTION. PRIVATE SECTION. DATA: mv_package TYPE devclass. METHODS get_transport_layer RETURNING VALUE(rv_transport_layer) TYPE devlayer RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_sap_report DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_sap_report. PROTECTED SECTION. PRIVATE SECTION. METHODS authorization_check IMPORTING iv_mode TYPE csequence is_item TYPE zif_abapgit_definitions=>ty_item RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_tabl_compar DEFINITION CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_comparator . METHODS constructor IMPORTING !ii_local TYPE REF TO zif_abapgit_xml_input. PROTECTED SECTION. TYPES: ty_founds TYPE STANDARD TABLE OF rsfindlst WITH NON-UNIQUE DEFAULT KEY . TYPES: ty_seu_obj TYPE STANDARD TABLE OF seu_obj WITH NON-UNIQUE DEFAULT KEY . DATA mi_local TYPE REF TO zif_abapgit_xml_input. METHODS get_where_used_recursive IMPORTING !iv_object_name TYPE csequence !iv_depth TYPE i !iv_object_type TYPE euobj-id !it_scope TYPE ty_seu_obj RETURNING VALUE(rt_founds_all) TYPE ty_founds RAISING zcx_abapgit_exception . METHODS is_structure_used_in_db_table IMPORTING !iv_object_name TYPE dd02v-tabname RETURNING VALUE(rv_is_structure_used_in_db_tab) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS validate IMPORTING !ii_remote_version TYPE REF TO zif_abapgit_xml_input !ii_local_version TYPE REF TO zif_abapgit_xml_input !ii_log TYPE REF TO zif_abapgit_log RETURNING VALUE(rv_message) TYPE string RAISING zcx_abapgit_exception . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_tabl_ddl DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS read_data IMPORTING !iv_name TYPE tadir-obj_name RETURNING VALUE(rs_data) TYPE zif_abapgit_object_tabl=>ty_internal . METHODS serialize IMPORTING !is_data TYPE zif_abapgit_object_tabl=>ty_internal RETURNING VALUE(rv_ddl) TYPE string . METHODS deserialize IMPORTING !iv_ddl TYPE string RETURNING VALUE(rs_data) TYPE zif_abapgit_object_tabl=>ty_internal . METHODS serialize_adt IMPORTING !iv_name TYPE tadir-obj_name RETURNING VALUE(rv_ddl) TYPE string RAISING cx_static_check . PROTECTED SECTION. PRIVATE SECTION. METHODS parse_top_annotations CHANGING !cs_data TYPE zif_abapgit_object_tabl=>ty_internal !cv_ddl TYPE string . METHODS parse_field_annotations EXPORTING !es_dd08v TYPE dd08v CHANGING !cv_ddl TYPE string . METHODS parse_field IMPORTING !iv_field TYPE string CHANGING !cs_data TYPE zif_abapgit_object_tabl=>ty_internal . METHODS serialize_top IMPORTING !is_data TYPE zif_abapgit_object_tabl=>ty_internal RETURNING VALUE(rv_ddl) TYPE string . METHODS serialize_extend IMPORTING !is_dd03p TYPE dd03p !is_data TYPE zif_abapgit_object_tabl=>ty_internal RETURNING VALUE(rv_ddl) TYPE string . METHODS serialize_field_annotations IMPORTING !iv_fieldname TYPE clike !is_data TYPE zif_abapgit_object_tabl=>ty_internal RETURNING VALUE(rv_ddl) TYPE string . METHODS serialize_fkey_annotations IMPORTING !iv_fieldname TYPE clike !is_data TYPE zif_abapgit_object_tabl=>ty_internal RETURNING VALUE(rv_ddl) TYPE string . METHODS serialize_field_foreign_key IMPORTING !iv_fieldname TYPE clike !is_data TYPE zif_abapgit_object_tabl=>ty_internal RETURNING VALUE(rv_ddl) TYPE string . METHODS serialize_value_help IMPORTING !iv_fieldname TYPE clike !is_data TYPE zif_abapgit_object_tabl=>ty_internal RETURNING VALUE(rv_ddl) TYPE string . METHODS escape_string IMPORTING !iv_string TYPE clike RETURNING VALUE(rv_string) TYPE string . METHODS unescape_string IMPORTING !iv_string TYPE clike RETURNING VALUE(rv_string) TYPE string . METHODS serialize_type IMPORTING !is_dd03p TYPE dd03p RETURNING VALUE(rv_type) TYPE string . METHODS parse_type IMPORTING !iv_token TYPE string CHANGING !cs_dd03p TYPE dd03p . ENDCLASS. CLASS zcl_abapgit_i18n_params DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. DATA ms_params TYPE zif_abapgit_definitions=>ty_i18n_params READ-ONLY . CLASS-METHODS new IMPORTING !iv_main_language TYPE spras DEFAULT zif_abapgit_definitions=>c_english !iv_main_language_only TYPE abap_bool DEFAULT abap_false !it_translation_langs TYPE zif_abapgit_definitions=>ty_languages OPTIONAL !iv_use_lxe TYPE abap_bool DEFAULT abap_false !is_params TYPE zif_abapgit_definitions=>ty_i18n_params OPTIONAL RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_i18n_params . METHODS constructor IMPORTING !iv_main_language TYPE spras DEFAULT zif_abapgit_definitions=>c_english !iv_main_language_only TYPE abap_bool DEFAULT abap_false !it_translation_langs TYPE zif_abapgit_definitions=>ty_languages OPTIONAL !iv_use_lxe TYPE abap_bool DEFAULT abap_false !is_params TYPE zif_abapgit_definitions=>ty_i18n_params OPTIONAL . METHODS is_lxe_applicable RETURNING VALUE(rv_yes) TYPE abap_bool . METHODS build_language_filter RETURNING VALUE(rt_language_filter) TYPE zif_abapgit_environment=>ty_system_language_filter . METHODS trim_saplang_list CHANGING ct_sap_langs TYPE zif_abapgit_definitions=>ty_sap_langu_tab RAISING zcx_abapgit_exception. METHODS trim_saplang_keyed_table IMPORTING iv_lang_field_name TYPE abap_compname iv_keep_master_lang TYPE abap_bool DEFAULT abap_false "sy-langu OPTIONAL CHANGING ct_tab TYPE STANDARD TABLE RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. CLASS-METHODS iso_langs_to_lang_filter IMPORTING it_iso_filter TYPE zif_abapgit_definitions=>ty_languages RETURNING VALUE(rt_language_filter) TYPE zif_abapgit_environment=>ty_system_language_filter. ENDCLASS. CLASS zcl_abapgit_longtexts DEFINITION CREATE PRIVATE FRIENDS ZCL_ABAPGIT_factory. PUBLIC SECTION. INTERFACES zif_abapgit_longtexts. PROTECTED SECTION. METHODS read IMPORTING !iv_object_name TYPE clike !iv_longtext_id TYPE dokil-id !it_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt !iv_main_lang_only TYPE abap_bool DEFAULT abap_false !iv_clear_fields TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rt_longtexts) TYPE zif_abapgit_longtexts=>ty_longtexts RAISING zcx_abapgit_exception . PRIVATE SECTION. CONSTANTS c_docu_state_active TYPE dokstate VALUE 'A' ##NO_TEXT. METHODS escape_name IMPORTING !iv_longtext_id TYPE dokil-id !iv_object_name TYPE clike RETURNING VALUE(rv_object) TYPE dokil-object. ENDCLASS. CLASS zcl_abapgit_lxe_texts DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_lxe_texts . CLASS-METHODS class_constructor. CLASS-METHODS get_translation_languages IMPORTING !iv_main_language TYPE spras !it_i18n_languages TYPE zif_abapgit_definitions=>ty_languages RETURNING VALUE(rt_languages) TYPE zif_abapgit_definitions=>ty_languages RAISING zcx_abapgit_exception. CLASS-METHODS get_installed_languages RETURNING VALUE(rt_languages) TYPE zif_abapgit_definitions=>ty_languages RAISING zcx_abapgit_exception. CLASS-METHODS convert_lang_string_to_table IMPORTING !iv_langs TYPE string !iv_skip_main_language TYPE spras OPTIONAL RETURNING VALUE(rt_languages) TYPE zif_abapgit_definitions=>ty_languages RAISING zcx_abapgit_exception . CLASS-METHODS convert_table_to_lang_string IMPORTING !it_languages TYPE zif_abapgit_definitions=>ty_languages RETURNING VALUE(rv_langs) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS detect_unsupported_languages IMPORTING !it_languages TYPE zif_abapgit_definitions=>ty_languages RETURNING VALUE(rt_unsupported_languages) TYPE zif_abapgit_definitions=>ty_languages RAISING zcx_abapgit_exception . CLASS-METHODS is_object_supported IMPORTING iv_object_type TYPE tadir-object RETURNING VALUE(rv_yes) TYPE abap_bool. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_custmnr TYPE lxecustmnr VALUE '999999' ##NEEDED. " The value for ABAP system translation is always 999999 (from lxecustmnr docs) TYPES: BEGIN OF ty_lxe_translation, source_lang TYPE lxeisolang, target_lang TYPE lxeisolang, custmnr TYPE lxecustmnr, objtype TYPE trobjtype, objname TYPE lxeobjname, text_pairs TYPE zif_abapgit_lxe_texts=>ty_text_pairs, END OF ty_lxe_translation. TYPES: ty_lxe_translations TYPE STANDARD TABLE OF ty_lxe_translation WITH DEFAULT KEY . CLASS-DATA gt_installed_languages_cache TYPE zif_abapgit_definitions=>ty_languages. CLASS-DATA gt_supported_obj_types TYPE STANDARD TABLE OF tadir-object. DATA mo_i18n_params TYPE REF TO zcl_abapgit_i18n_params. DATA mi_xml_out TYPE REF TO zif_abapgit_xml_output. DATA mi_xml_in TYPE REF TO zif_abapgit_xml_input. DATA mo_files TYPE REF TO zcl_abapgit_objects_files. METHODS serialize_xml IMPORTING !iv_lxe_text_name TYPE string DEFAULT 'LXE_TEXTS' !iv_object_type TYPE tadir-object !iv_object_name TYPE tadir-obj_name RAISING zcx_abapgit_exception . METHODS serialize_as_po IMPORTING !iv_object_type TYPE tadir-object !iv_object_name TYPE tadir-obj_name RAISING zcx_abapgit_exception . " Implementation of deserialize_xml is not complete (but kept as future option) METHODS deserialize_xml IMPORTING !iv_lxe_text_name TYPE string DEFAULT 'LXE_TEXTS' !iv_object_type TYPE tadir-object OPTIONAL !iv_object_name TYPE tadir-obj_name OPTIONAL RAISING zcx_abapgit_exception ##NEEDED. METHODS deserialize_from_po IMPORTING !iv_object_type TYPE tadir-object !iv_object_name TYPE tadir-obj_name RAISING zcx_abapgit_exception . METHODS get_lang_iso4 IMPORTING iv_src TYPE laiso RETURNING VALUE(rv_iso4) TYPE lxeisolang RAISING zcx_abapgit_exception. METHODS get_lxe_object_list IMPORTING iv_object_type TYPE trobjtype iv_object_name TYPE sobj_name RETURNING VALUE(rt_obj_list) TYPE lxe_tt_colob . METHODS read_lxe_object_text_pair IMPORTING iv_s_lang TYPE lxeisolang iv_t_lang TYPE lxeisolang iv_custmnr TYPE lxecustmnr iv_objtype TYPE trobjtype iv_objname TYPE lxeobjname iv_read_only TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rt_text_pairs_tmp) TYPE ty_lxe_translation-text_pairs RAISING zcx_abapgit_exception. METHODS write_lxe_object_text_pair IMPORTING iv_s_lang TYPE lxeisolang iv_t_lang TYPE lxeisolang iv_custmnr TYPE lxecustmnr iv_objtype TYPE trobjtype iv_objname TYPE lxeobjname it_pcx_s1 TYPE ty_lxe_translation-text_pairs RAISING zcx_abapgit_exception. METHODS read_text_items IMPORTING iv_object_type TYPE tadir-object iv_object_name TYPE tadir-obj_name RETURNING VALUE(rt_text_items) TYPE ty_lxe_translations RAISING zcx_abapgit_exception. CLASS-METHODS langu_to_laiso_safe IMPORTING iv_langu TYPE sy-langu RETURNING VALUE(rv_laiso) TYPE laiso RAISING zcx_abapgit_exception. CLASS-METHODS iso4_to_iso2 IMPORTING iv_lxe_lang TYPE lxeisolang RETURNING VALUE(rv_laiso) TYPE laiso RAISING zcx_abapgit_exception. CLASS-METHODS check_langs_versus_installed IMPORTING it_languages TYPE zif_abapgit_definitions=>ty_languages it_installed TYPE zif_abapgit_definitions=>ty_languages EXPORTING et_intersection TYPE zif_abapgit_definitions=>ty_languages et_missfits TYPE zif_abapgit_definitions=>ty_languages. ENDCLASS. CLASS zcl_abapgit_po_file DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_i18n_file. METHODS constructor IMPORTING iv_lang TYPE laiso. METHODS parse IMPORTING iv_xdata TYPE xstring RAISING zcx_abapgit_exception. METHODS push_text_pairs IMPORTING iv_objtype TYPE trobjtype iv_objname TYPE lxeobjname it_text_pairs TYPE zif_abapgit_lxe_texts=>ty_text_pairs RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_comment, translator TYPE i VALUE 1, extracted TYPE i VALUE 2, reference TYPE i VALUE 3, flag TYPE i VALUE 4, previous TYPE i VALUE 5, END OF c_comment. TYPES: BEGIN OF ty_comment, kind TYPE i, text TYPE string, END OF ty_comment. TYPES: BEGIN OF ty_msg_pair, source TYPE string, target TYPE string, comments TYPE STANDARD TABLE OF ty_comment WITH KEY kind text, END OF ty_msg_pair. DATA mv_lang TYPE laiso. DATA mt_pairs TYPE SORTED TABLE OF ty_msg_pair WITH UNIQUE KEY source. METHODS build_po_body RETURNING VALUE(ro_buf) TYPE REF TO zcl_abapgit_string_buffer. METHODS build_po_head RETURNING VALUE(ro_buf) TYPE REF TO zcl_abapgit_string_buffer. METHODS parse_po IMPORTING iv_data TYPE string RAISING zcx_abapgit_exception. CLASS-METHODS get_comment_marker IMPORTING iv_comment_kind TYPE i RETURNING VALUE(rv_marker) TYPE string. CLASS-METHODS quote IMPORTING iv_text TYPE string RETURNING VALUE(rv_text) TYPE string. CLASS-METHODS unquote IMPORTING iv_text TYPE string RETURNING VALUE(rv_text) TYPE string RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_properties_file DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_i18n_file. CONSTANTS: c_properties_feature TYPE string VALUE 'TRANSL'. METHODS constructor IMPORTING iv_lang TYPE laiso. METHODS parse IMPORTING iv_xdata TYPE xstring RAISING zcx_abapgit_exception. METHODS push_text_pairs IMPORTING it_translation TYPE string_table. METHODS get_translations EXPORTING ev_data TYPE data RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mv_lang TYPE laiso. DATA mt_translation TYPE string_table. ENDCLASS. CLASS zcl_abapgit_sotr_handler DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_sotr, header TYPE sotr_head, entries TYPE sotr_text_tt, END OF ty_sotr . TYPES: ty_sotr_tt TYPE STANDARD TABLE OF ty_sotr WITH DEFAULT KEY . TYPES: ty_sotr_use_tt TYPE STANDARD TABLE OF sotr_use WITH DEFAULT KEY . CLASS-METHODS read_sotr IMPORTING !iv_pgmid TYPE pgmid DEFAULT 'R3TR' !iv_object TYPE trobjtype !iv_obj_name TYPE csequence !io_xml TYPE REF TO zif_abapgit_xml_output OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params EXPORTING !et_sotr TYPE ty_sotr_tt !et_sotr_use TYPE ty_sotr_use_tt RAISING zcx_abapgit_exception . CLASS-METHODS create_sotr IMPORTING !iv_package TYPE devclass !io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . CLASS-METHODS create_sotr_from_data IMPORTING !iv_package TYPE devclass !it_sotr TYPE ty_sotr_tt !it_sotr_use TYPE ty_sotr_use_tt RAISING zcx_abapgit_exception . CLASS-METHODS delete_sotr IMPORTING !iv_pgmid TYPE pgmid DEFAULT 'R3TR' !iv_object TYPE trobjtype !iv_obj_name TYPE csequence RAISING zcx_abapgit_exception . CLASS-METHODS delete_sotr_package IMPORTING !iv_package TYPE devclass RAISING zcx_abapgit_exception . PROTECTED SECTION. CLASS-METHODS get_sotr_usage IMPORTING !iv_pgmid TYPE pgmid !iv_object TYPE trobjtype !iv_obj_name TYPE csequence RETURNING VALUE(rt_sotr_use) TYPE ty_sotr_use_tt. CLASS-METHODS get_sotr_4_concept IMPORTING !iv_concept TYPE sotr_conc RETURNING VALUE(rs_sotr) TYPE ty_sotr . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_sots_handler DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. TYPES: BEGIN OF ty_sots, header TYPE sotr_headu, entries TYPE sotr_textl_tt, END OF ty_sots. TYPES: ty_sots_tt TYPE STANDARD TABLE OF ty_sots WITH DEFAULT KEY. TYPES: ty_sots_use_tt TYPE STANDARD TABLE OF sotr_useu WITH DEFAULT KEY. CLASS-METHODS read_sots IMPORTING !iv_pgmid TYPE pgmid DEFAULT 'R3TR' !iv_object TYPE trobjtype !iv_obj_name TYPE csequence !io_xml TYPE REF TO zif_abapgit_xml_output OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params EXPORTING !et_sots TYPE ty_sots_tt !et_sots_use TYPE ty_sots_use_tt RAISING zcx_abapgit_exception. CLASS-METHODS create_sots IMPORTING !iv_package TYPE devclass !io_xml TYPE REF TO zif_abapgit_xml_input OPTIONAL RAISING zcx_abapgit_exception. CLASS-METHODS create_sots_from_data IMPORTING !iv_package TYPE devclass !it_sots TYPE ty_sots_tt OPTIONAL !it_sots_use TYPE ty_sots_use_tt OPTIONAL RAISING zcx_abapgit_exception. CLASS-METHODS delete_sots IMPORTING !iv_pgmid TYPE pgmid DEFAULT 'R3TR' !iv_object TYPE trobjtype !iv_obj_name TYPE csequence RAISING zcx_abapgit_exception. PROTECTED SECTION. CLASS-METHODS get_sots_usage IMPORTING !iv_pgmid TYPE pgmid !iv_object TYPE trobjtype !iv_obj_name TYPE csequence RETURNING VALUE(rt_sots_use) TYPE ty_sots_use_tt. CLASS-METHODS get_sots_4_concept IMPORTING !iv_concept TYPE sotr_conc RETURNING VALUE(rs_sots) TYPE ty_sots. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_objects DEFINITION CREATE PUBLIC . PUBLIC SECTION. TYPES: ty_types_tt TYPE SORTED TABLE OF tadir-object WITH UNIQUE KEY table_line . CLASS-METHODS serialize IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params RETURNING VALUE(rs_files_and_item) TYPE zif_abapgit_objects=>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_git_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 !is_sub_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL !iv_filename TYPE string OPTIONAL !iv_line_number TYPE i OPTIONAL !iv_new_window TYPE abap_bool DEFAULT abap_true RAISING zcx_abapgit_exception . CLASS-METHODS changed_by IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_filename TYPE string OPTIONAL RETURNING VALUE(rv_user) TYPE syuname . 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 is_type_supported IMPORTING !iv_obj_type TYPE zif_abapgit_definitions=>ty_item-obj_type 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_supported_types, obj_type TYPE tadir-object, supported TYPE abap_bool, END OF ty_supported_types. TYPES: ty_supported_types_tt TYPE SORTED TABLE OF ty_supported_types WITH UNIQUE KEY obj_type. 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-DATA gt_supported_obj_types TYPE ty_supported_types_tt . CLASS-DATA gv_supported_obj_types_loaded TYPE abap_bool . CLASS-METHODS check_duplicates IMPORTING !it_files TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . CLASS-METHODS class_name IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item RETURNING VALUE(rv_class_name) TYPE string . CLASS-METHODS update_package_tree IMPORTING !iv_package TYPE devclass . CLASS-METHODS delete_object IMPORTING !iv_package TYPE devclass !is_item TYPE zif_abapgit_definitions=>ty_item !iv_transport TYPE trkorr RAISING 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 IMPORTING !it_steps TYPE zif_abapgit_objects=>ty_step_data_tt !ii_log TYPE REF TO zif_abapgit_log !iv_transport TYPE trkorr CHANGING !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt RAISING zcx_abapgit_exception . CLASS-METHODS deserialize_step IMPORTING !is_step TYPE zif_abapgit_objects=>ty_step_data !ii_log TYPE REF TO zif_abapgit_log !iv_transport TYPE trkorr CHANGING !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt RAISING zcx_abapgit_exception . CLASS-METHODS check_original_system IMPORTING !it_items TYPE zif_abapgit_definitions=>ty_items_tt !ii_log TYPE REF TO zif_abapgit_log !io_dot TYPE REF TO zcl_abapgit_dot_abapgit RAISING zcx_abapgit_exception . CLASS-METHODS update_original_system IMPORTING !it_items TYPE zif_abapgit_definitions=>ty_items_tt !ii_log TYPE REF TO zif_abapgit_log !io_dot TYPE REF TO zcl_abapgit_dot_abapgit !iv_transport TYPE trkorr RAISING zcx_abapgit_exception . CLASS-METHODS check_objects_locked IMPORTING !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 !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL !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 get_deserialize_steps RETURNING VALUE(rt_steps) TYPE zif_abapgit_objects=>ty_step_data_tt . CLASS-METHODS check_main_package IMPORTING !iv_package TYPE devclass !iv_obj_type TYPE tadir-object RAISING zcx_abapgit_exception . CLASS-METHODS change_package_assignments IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !ii_log TYPE REF TO zif_abapgit_log . CLASS-METHODS get_extra_from_filename IMPORTING !iv_filename TYPE string RETURNING VALUE(rv_extra) TYPE string. ENDCLASS. CLASS zcl_abapgit_objects_factory DEFINITION CREATE PRIVATE . PUBLIC SECTION. CLASS-METHODS get_gui_jumper RETURNING VALUE(ri_gui_jumper) TYPE REF TO zif_abapgit_gui_jumper . PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gi_gui_jumper TYPE REF TO zif_abapgit_gui_jumper . ENDCLASS. CLASS zcl_abapgit_objects_generic DEFINITION CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras DEFAULT sy-langu io_field_rules TYPE REF TO zif_abapgit_field_rules OPTIONAL RAISING zcx_abapgit_exception . METHODS delete IMPORTING !iv_package TYPE devclass RAISING zcx_abapgit_exception . METHODS deserialize IMPORTING !iv_package TYPE devclass !io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS exists RETURNING VALUE(rv_bool) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS serialize IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . PROTECTED SECTION. TYPES: BEGIN OF ty_s_objkey, num TYPE n LENGTH 3, value TYPE c LENGTH 128, END OF ty_s_objkey . TYPES: ty_t_objkey TYPE SORTED TABLE OF ty_s_objkey WITH UNIQUE KEY num . DATA ms_object_header TYPE objh . DATA: mt_object_table TYPE STANDARD TABLE OF objsl WITH DEFAULT KEY . DATA: mt_object_method TYPE STANDARD TABLE OF objm WITH DEFAULT KEY . DATA ms_item TYPE zif_abapgit_definitions=>ty_item . DATA mv_language TYPE spras . METHODS after_import . METHODS before_export . METHODS corr_insert IMPORTING !iv_package TYPE devclass RAISING zcx_abapgit_exception . METHODS deserialize_data IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input !iv_package TYPE devclass RAISING zcx_abapgit_exception . METHODS distribute_name_to_components IMPORTING !it_key_component TYPE ddfields CHANGING !ct_objkey TYPE ty_t_objkey !cs_objkey TYPE ty_s_objkey !cv_non_value_pos TYPE numc3 . METHODS get_key_fields IMPORTING !iv_table TYPE objsl-tobj_name RETURNING VALUE(rt_keys) TYPE ddfields RAISING zcx_abapgit_exception . METHODS get_primary_table RETURNING VALUE(rv_table) TYPE objsl-tobj_name RAISING zcx_abapgit_exception . METHODS get_where_clause IMPORTING !iv_tobj_name TYPE objsl-tobj_name RETURNING VALUE(rv_where) TYPE string RAISING zcx_abapgit_exception . METHODS serialize_data IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS split_value_to_keys IMPORTING !it_key_component TYPE ddfields CHANGING !ct_objkey TYPE ty_t_objkey !cs_objkey TYPE ty_s_objkey !cv_non_value_pos TYPE numc3 . METHODS validate IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . PRIVATE SECTION. DATA mo_field_rules TYPE REF TO zif_abapgit_field_rules . METHODS apply_clear_logic IMPORTING !iv_table TYPE objsl-tobj_name CHANGING !ct_data TYPE STANDARD TABLE . METHODS apply_fill_logic IMPORTING !iv_table TYPE objsl-tobj_name !iv_package TYPE devclass CHANGING !ct_data TYPE STANDARD TABLE . ENDCLASS. CLASS zcl_abapgit_objects_super DEFINITION ABSTRACT CREATE PUBLIC. PUBLIC SECTION. CONSTANTS c_user_unknown TYPE syuname VALUE 'UNKNOWN'. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL. METHODS get_accessed_files RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt. PROTECTED SECTION. DATA: ms_item TYPE zif_abapgit_definitions=>ty_item, mv_language TYPE spras, mo_files TYPE REF TO zcl_abapgit_objects_files, mo_i18n_params TYPE REF TO zcl_abapgit_i18n_params. METHODS get_metadata RETURNING VALUE(rs_metadata) TYPE zif_abapgit_definitions=>ty_metadata . METHODS corr_insert IMPORTING !iv_package TYPE devclass !ig_object_class TYPE any OPTIONAL RAISING zcx_abapgit_exception . METHODS tadir_insert IMPORTING !iv_package TYPE devclass RAISING zcx_abapgit_exception . METHODS tadir_delete RAISING zcx_abapgit_exception . METHODS exists_a_lock_entry_for IMPORTING !iv_lock_object TYPE string !iv_argument TYPE csequence OPTIONAL !iv_prefix TYPE csequence OPTIONAL RETURNING VALUE(rv_exists_a_lock_entry) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS set_default_package IMPORTING !iv_package TYPE devclass . METHODS set_default_transport IMPORTING !iv_transport TYPE trkorr. METHODS serialize_longtexts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output !iv_longtext_id TYPE dokil-id OPTIONAL !it_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt OPTIONAL !iv_longtext_name TYPE string DEFAULT 'LONGTEXTS' RAISING zcx_abapgit_exception . METHODS deserialize_longtexts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input !iv_longtext_id TYPE dokil-id OPTIONAL !iv_longtext_name TYPE string DEFAULT 'LONGTEXTS' RAISING zcx_abapgit_exception . METHODS delete_longtexts IMPORTING !iv_longtext_id TYPE dokil-id RAISING zcx_abapgit_exception . METHODS is_active RETURNING VALUE(rv_active) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS delete_ddic IMPORTING !iv_objtype TYPE string !iv_no_ask TYPE abap_bool DEFAULT abap_true !iv_no_ask_delete_append TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . METHODS set_abap_language_version CHANGING !cv_abap_language_version TYPE uccheck RAISING zcx_abapgit_exception . METHODS clear_abap_language_version CHANGING !cv_abap_language_version TYPE uccheck RAISING zcx_abapgit_exception . PRIVATE SECTION. ENDCLASS. "! Provides common functionality for the abapGit integration of objects based on ABAP File Formats (AFF). "! It inherits from {@link ZCL_ABAPGIT_OBJECTS_SUPER} and implements the interface {@link ZIF_ABAPGIT_OBJECT}. "!

"! Each subclass must implement at least the abstract method ZIF_ABAPGIT_OBJECT~CHANGED_BY. "! In case you deal with a DDIC object, the methods GET_METADATA and ZIF_ABAPGIT_OBJECT~GET_DESERIALIZE_STEPS "! have to be redefined in the subclass. "!

"! In case the object has an additional file to the json file, the subclass needs "! to redefine the method GET_ADDITIONAL_EXTENSIONS. "!

"! This common class fully relies on the implementation of the object-specific AFF handler "! (it inherits from {@link CL_AFF_OBJECT_HANDLER}). "! Precisely, for the existence check-, serialization-, deserialization- or deletion-functionality, the corresponding "! AFF object handler method is called. CLASS zcl_abapgit_object_common_aff DEFINITION INHERITING FROM zcl_abapgit_objects_super ABSTRACT CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object ABSTRACT METHODS changed_by . METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. TYPES: BEGIN OF ty_extension_mapper_pair, "! file extension extension TYPE string, "! instance of {@link CL_AFF_FILE_NAME_MAPPER} providing file names for file extensions file_name_mapper TYPE REF TO object, END OF ty_extension_mapper_pair, ty_extension_mapper_pairs TYPE STANDARD TABLE OF ty_extension_mapper_pair WITH DEFAULT KEY. "! Delivers other file extensions than json to be considered at serialize or deserialize of an object METHODS get_additional_extensions RETURNING VALUE(rv_additional_extensions) TYPE ty_extension_mapper_pairs ##NEEDED. "! Delivers an instance of AFF object handler ({@link IF_AFF_OBJECT_HANDLER}) METHODS get_object_handler RETURNING VALUE(ro_object_handler) TYPE REF TO object RAISING zcx_abapgit_exception. METHODS create_aff_setting_deserialize FINAL RETURNING VALUE(ro_settings_deserialize) TYPE REF TO object. PRIVATE SECTION. METHODS is_file_empty IMPORTING io_object_json_file TYPE REF TO object RETURNING VALUE(rv_is_empty) TYPE abap_bool. CLASS-METHODS remove_abap_language_version IMPORTING iv_json_as_xstring TYPE xstring RETURNING VALUE(rv_json_as_xstring_wo_alv) TYPE xstring RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_chkc DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_chko DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_chkv DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_drty DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION. METHODS zif_abapgit_object~get_deserialize_steps REDEFINITION. PROTECTED SECTION. METHODS get_additional_extensions REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_dteb DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION . METHODS zif_abapgit_object~get_deserialize_steps REDEFINITION. PROTECTED SECTION. METHODS get_additional_extensions REDEFINITION . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_eeec DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS: zif_abapgit_object~changed_by REDEFINITION . PROTECTED SECTION. METHODS: get_object_handler REDEFINITION. ENDCLASS. CLASS zcl_abapgit_object_evtb DEFINITION INHERITING FROM zcl_abapgit_object_common_aff CREATE PUBLIC. PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_table_name TYPE tabname VALUE 'EVTB_HEADER'. ENDCLASS. CLASS zcl_abapgit_object_gsmp DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_nont DEFINITION INHERITING FROM zcl_abapgit_object_common_aff CREATE PUBLIC. PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_table_name TYPE tabname VALUE 'NONT_HEADER'. ENDCLASS. CLASS zcl_abapgit_object_ront DEFINITION INHERITING FROM zcl_abapgit_object_common_aff CREATE PUBLIC. PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_table_name TYPE tabname VALUE 'RONT_HEADER'. ENDCLASS. CLASS zcl_abapgit_object_smbc DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_uipg DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_uist DEFINITION INHERITING FROM zcl_abapgit_object_common_aff FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS zif_abapgit_object~changed_by REDEFINITION . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_tabl DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. "! get additional data like table authorization group "! @parameter iv_tabname | name of the table METHODS read_extras IMPORTING iv_tabname TYPE ddobjname RETURNING VALUE(rs_tabl_extras) TYPE zif_abapgit_object_tabl=>ty_tabl_extras. "! Update additional data "! @parameter iv_tabname | name of the table "! @parameter is_tabl_extras | additional table data METHODS update_extras IMPORTING iv_tabname TYPE ddobjname is_tabl_extras TYPE zif_abapgit_object_tabl=>ty_tabl_extras. "! Delete additional data "! @parameter iv_tabname | name of the table METHODS delete_extras IMPORTING iv_tabname TYPE ddobjname. "! Serialize IDoc Segment type/definition if exits "! @raising zcx_abapgit_exception | Exceptions METHODS serialize_idoc_segment CHANGING cs_internal TYPE zif_abapgit_object_tabl=>ty_internal RAISING zcx_abapgit_exception. "! Deserialize IDoc Segment type/definition if exits "! @parameter iv_package | Target package "! @parameter rv_deserialized | It's a segment and was deserialized "! @raising zcx_abapgit_exception | Exceptions METHODS deserialize_idoc_segment IMPORTING is_internal TYPE zif_abapgit_object_tabl=>ty_internal iv_transport TYPE trkorr iv_package TYPE devclass RETURNING VALUE(rv_deserialized) TYPE abap_bool RAISING zcx_abapgit_exception. "! Delete the IDoc Segment type if exists "! @parameter rv_deleted | It's a segment and was deleted "! @raising zcx_abapgit_exception | Exceptions METHODS delete_idoc_segment RETURNING VALUE(rv_deleted) TYPE abap_bool RAISING zcx_abapgit_exception. PRIVATE SECTION. CONSTANTS c_longtext_id_tabl TYPE dokil-id VALUE 'TB' ##NO_TEXT. METHODS deserialize_indexes IMPORTING !is_internal TYPE zif_abapgit_object_tabl=>ty_internal RAISING zcx_abapgit_exception . METHODS clear_dd03p_fields CHANGING !ct_dd03p TYPE zif_abapgit_object_tabl=>ty_dd03p_tt . "! Check if structure is an IDoc segment "! @parameter rv_is_idoc_segment | It's an IDoc segment or not METHODS is_idoc_segment RETURNING VALUE(rv_is_idoc_segment) TYPE abap_bool . METHODS clear_dd03p_fields_common CHANGING !cs_dd03p TYPE dd03p . METHODS clear_dd03p_fields_dataelement CHANGING !cs_dd03p TYPE dd03p . METHODS serialize_texts CHANGING !cs_internal TYPE zif_abapgit_object_tabl=>ty_internal RAISING zcx_abapgit_exception . METHODS deserialize_texts CHANGING !cs_internal TYPE zif_abapgit_object_tabl=>ty_internal RAISING zcx_abapgit_exception . METHODS is_db_table_category IMPORTING !iv_tabclass TYPE dd02l-tabclass RETURNING VALUE(rv_is_db_table_type) TYPE dd02l-tabclass . ENDCLASS. CLASS zcl_abapgit_object_acid DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS: create_object RETURNING VALUE(ro_aab) TYPE REF TO cl_aab_id RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_aifc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. TYPES: BEGIN OF ty_aif_key_s, ns TYPE c LENGTH 6, ifname TYPE c LENGTH 10, ifver TYPE c LENGTH 5, END OF ty_aif_key_s. TYPES: BEGIN OF ty_icd_data_key_s, depl_scenario TYPE c LENGTH 20, ns TYPE c LENGTH 6, ifname TYPE c LENGTH 10, ifver2 TYPE c LENGTH 4, END OF ty_icd_data_key_s. TYPES: BEGIN OF ty_icd_data_key, depl_scenario TYPE c LENGTH 20, ns TYPE c LENGTH 6, ifname TYPE c LENGTH 10, ifver2 TYPE c LENGTH 4, ifver TYPE c LENGTH 5, END OF ty_icd_data_key. TYPES: BEGIN OF ty_table_data_s, tabname TYPE tabname, table_data TYPE REF TO data, END OF ty_table_data_s. TYPES: ty_table_data_t TYPE SORTED TABLE OF ty_table_data_s WITH UNIQUE KEY tabname. DATA ms_icd_data_key TYPE ty_icd_data_key_s. METHODS handle_table_data IMPORTING !iv_tabname TYPE tabname !it_data TYPE STANDARD TABLE RAISING zcx_abapgit_exception. METHODS clear_client CHANGING !ct_data TYPE STANDARD TABLE RAISING zcx_abapgit_exception. METHODS authorization_check RETURNING VALUE(rv_success) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS get_content_compress IMPORTING !io_log TYPE REF TO zif_abapgit_log !is_ifkeys TYPE ty_aif_key_s !iv_package TYPE devclass RAISING zcx_abapgit_exception. METHODS validate_interface IMPORTING !is_ifkeys TYPE ty_aif_key_s RETURNING VALUE(rv_success) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS compress_interface IMPORTING !is_ifkeys TYPE ty_aif_key_s RETURNING VALUE(rv_success) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS execute_checks IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input RETURNING VALUE(rv_success) TYPE abap_bool RAISING zcx_abapgit_exception. PRIVATE SECTION. TYPES: BEGIN OF ty_content_s, tabname TYPE tabname, END OF ty_content_s. TYPES: ty_content_t TYPE STANDARD TABLE OF ty_content_s WITH NON-UNIQUE DEFAULT KEY. DATA mo_abapgit_util TYPE REF TO object. ENDCLASS. CLASS zcl_abapgit_object_amsd DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. METHODS: clear_fields CHANGING cs_logical_db_schema TYPE any, clear_field IMPORTING iv_fieldname TYPE csequence CHANGING cs_logical_db_schema TYPE any, fill_metadata_from_db CHANGING cs_logical_db_schema TYPE any RAISING zcx_abapgit_exception, get_wb_object_operator RETURNING VALUE(ri_wb_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception. DATA: mr_logical_db_schema TYPE REF TO data, mv_logical_db_schema_key TYPE seu_objkey, mi_persistence TYPE REF TO if_wb_object_persist, mi_wb_object_operator TYPE REF TO object. ENDCLASS. CLASS zcl_abapgit_object_apis DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_model TYPE string VALUE 'ARS_S_API_ABAPGIT'. DATA mo_handler TYPE REF TO object. METHODS initialize. ENDCLASS. CLASS zcl_abapgit_object_aqbg DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_aqqu DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_aqsg DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_area DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_asfc DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_auth DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mv_fieldname TYPE authx-fieldname. ENDCLASS. CLASS zcl_abapgit_object_avar DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS: create_object RETURNING VALUE(ro_aab_var) TYPE REF TO cl_aab_variant RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_avas DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. TYPES: BEGIN OF ty_header, guid TYPE guid_32, attribute TYPE cls_attribute_name, object TYPE pak_object_key, END OF ty_header . TYPES: BEGIN OF ty_avas, header TYPE ty_header, values TYPE cls_value_assignments, links TYPE cls_linked_objects, END OF ty_avas . METHODS insert_assignments IMPORTING !is_avas TYPE ty_avas RAISING zcx_abapgit_exception . METHODS instantiate RETURNING VALUE(ro_avas) TYPE REF TO cl_cls_attr_value_assignment RAISING zcx_abapgit_exception . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_bdef DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mi_persistence TYPE REF TO if_wb_object_persist . DATA mi_wb_object_operator TYPE REF TO object . DATA mv_behaviour_definition_key TYPE seu_objkey . DATA mr_behaviour_definition TYPE REF TO data . METHODS clear_fields CHANGING !cs_metadata TYPE any . METHODS clear_field IMPORTING !iv_fieldname TYPE csequence CHANGING !cs_metadata TYPE any . METHODS get_wb_object_operator RETURNING VALUE(ri_wb_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception . METHODS merge_object_data IMPORTING !io_object_data TYPE REF TO object RETURNING VALUE(ro_object_data_merged) TYPE REF TO if_wb_object_data_model RAISING zcx_abapgit_exception . METHODS get_object_data IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input RETURNING VALUE(ro_object_data) TYPE REF TO if_wb_object_data_model RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_char DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_char, cls_attribute TYPE cls_attribute, cls_attributet TYPE STANDARD TABLE OF cls_attributet WITH DEFAULT KEY, cls_attr_value TYPE STANDARD TABLE OF cls_attr_value WITH DEFAULT KEY, cls_attr_valuet TYPE STANDARD TABLE OF cls_attr_valuet WITH DEFAULT KEY, END OF ty_char . CONSTANTS c_longtext_id_char TYPE dokil-id VALUE 'CH'. METHODS instantiate_char_and_lock IMPORTING !iv_type_group TYPE cls_object_type_group !iv_activation_state TYPE pak_activation_state RETURNING VALUE(ro_char) TYPE REF TO cl_cls_attribute RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_chdo DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. METHODS after_import RAISING zcx_abapgit_exception . METHODS delete_tadir_cdnames IMPORTING !is_cdnames TYPE cdnames RAISING zcx_abapgit_exception . METHODS delete_tadir_tabl IMPORTING !is_tcdrs TYPE tcdrs RAISING zcx_abapgit_exception . PRIVATE SECTION. TYPES: BEGIN OF ty_change_document, reports_generated TYPE SORTED TABLE OF tcdrps WITH UNIQUE KEY object reportname, objects TYPE SORTED TABLE OF tcdobs WITH UNIQUE KEY object tabname, objects_text TYPE SORTED TABLE OF tcdobts WITH UNIQUE KEY spras object, END OF ty_change_document. DATA: mv_object TYPE cdobjectcl. ENDCLASS. CLASS zcl_abapgit_object_cmod DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_cmpt DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. DATA: mo_cmp_db TYPE REF TO object, mv_name TYPE c LENGTH 30. ENDCLASS. CLASS zcl_abapgit_object_cus0 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_img_activity_texts TYPE STANDARD TABLE OF cus_imgact WITH NON-UNIQUE DEFAULT KEY, BEGIN OF ty_img_activity, header TYPE cus_imgach, texts TYPE ty_img_activity_texts, END OF ty_img_activity. DATA: mv_img_activity TYPE cus_img_ac. ENDCLASS. CLASS zcl_abapgit_object_cus1 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_activity_titles TYPE STANDARD TABLE OF cus_actt WITH NON-UNIQUE DEFAULT KEY, ty_objects TYPE STANDARD TABLE OF cus_actobj WITH NON-UNIQUE DEFAULT KEY, ty_objects_title TYPE STANDARD TABLE OF cus_actobt WITH NON-UNIQUE DEFAULT KEY, BEGIN OF ty_customzing_activity, activity_header TYPE cus_acth, activity_customer_exit TYPE cus_actext, activity_title TYPE ty_activity_titles, objects TYPE ty_objects, objects_title TYPE ty_objects_title, END OF ty_customzing_activity. DATA: mv_customizing_activity TYPE cus_img_ac. ENDCLASS. CLASS zcl_abapgit_object_cus2 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_attribute_titles TYPE STANDARD TABLE OF cus_atrt WITH NON-UNIQUE DEFAULT KEY, ty_attribute_countries TYPE STANDARD TABLE OF cus_atrcou WITH NON-UNIQUE DEFAULT KEY, ty_attribute_components TYPE STANDARD TABLE OF tfm18 WITH NON-UNIQUE DEFAULT KEY, ty_attribute_comp_variants TYPE STANDARD TABLE OF cus_atrvco WITH NON-UNIQUE DEFAULT KEY. TYPES: BEGIN OF ty_customizing_attribute, header TYPE cus_atrh, titles TYPE ty_attribute_titles, countries TYPE ty_attribute_countries, components TYPE ty_attribute_components, components_variants TYPE ty_attribute_comp_variants, END OF ty_customizing_attribute. DATA: mv_img_attribute TYPE cus_atr. ENDCLASS. CLASS zcl_abapgit_object_dcls DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_ddls DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. METHODS open_adt_stob IMPORTING iv_ddls_name TYPE tadir-obj_name RAISING zcx_abapgit_exception. PRIVATE SECTION. METHODS is_baseinfo_supported RETURNING VALUE(rv_supported) TYPE abap_bool . METHODS read_baseinfo RETURNING VALUE(rv_baseinfo_string) TYPE string. METHODS format_source_before_serialize CHANGING cv_string TYPE string. ENDCLASS. CLASS zcl_abapgit_object_ddlx DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. DATA mi_persistence TYPE REF TO if_wb_object_persist . METHODS get_persistence RETURNING VALUE(ri_persistence) TYPE REF TO if_wb_object_persist RAISING zcx_abapgit_exception . METHODS clear_fields CHANGING !cg_data TYPE any . METHODS clear_field IMPORTING !iv_fieldname TYPE csequence CHANGING !cg_metadata TYPE any . ENDCLASS. CLASS zcl_abapgit_object_devc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES: zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mv_local_devclass TYPE devclass . METHODS get_package RETURNING VALUE(ri_package) TYPE REF TO if_package RAISING zcx_abapgit_exception . METHODS update_pinf_usages IMPORTING !ii_package TYPE REF TO if_package !it_usage_data TYPE scomppdata RAISING zcx_abapgit_exception . METHODS set_lock IMPORTING !ii_package TYPE REF TO if_package !iv_lock TYPE abap_bool RAISING zcx_abapgit_exception . METHODS unlock_and_raise_error IMPORTING !ii_package TYPE REF TO if_package RAISING zcx_abapgit_exception . METHODS is_empty IMPORTING !iv_package_name TYPE devclass RETURNING VALUE(rv_is_empty) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS load_package IMPORTING !iv_package_name TYPE devclass RETURNING VALUE(ri_package) TYPE REF TO if_package RAISING zcx_abapgit_exception . METHODS is_local IMPORTING !iv_package_name TYPE devclass RETURNING VALUE(rv_is_local) TYPE abap_bool . METHODS remove_obsolete_tadir IMPORTING !iv_package_name TYPE devclass . METHODS adjust_sw_component CHANGING cv_dlvunit TYPE dlvunit. ENDCLASS. CLASS zcl_abapgit_object_dial DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_dialog_module, tdct TYPE tdct, dia_pars TYPE STANDARD TABLE OF diapar WITH NON-UNIQUE DEFAULT KEY, END OF ty_dialog_module. METHODS: _read_tdct RETURNING VALUE(rs_tdct) TYPE tdct. ENDCLASS. CLASS zcl_abapgit_object_doct DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_id TYPE dokhl-id VALUE 'TX' ##NO_TEXT. CONSTANTS c_name TYPE string VALUE 'DOC' ##NO_TEXT. DATA mi_longtexts TYPE REF TO zif_abapgit_longtexts . ENDCLASS. CLASS zcl_abapgit_object_docv DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_data, doctitle TYPE dsyst-doktitle, head TYPE thead, lines TYPE tline_tab, END OF ty_data. CONSTANTS c_typ TYPE dokhl-typ VALUE 'E' ##NO_TEXT. CONSTANTS c_version TYPE dokhl-dokversion VALUE '0001' ##NO_TEXT. CONSTANTS c_name TYPE string VALUE 'DOC' ##NO_TEXT. DATA mv_id TYPE dokhl-id. DATA mv_doc_object TYPE dokhl-object. METHODS read RETURNING VALUE(rs_data) TYPE ty_data. ENDCLASS. CLASS zcl_abapgit_object_doma DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_dd01_text, ddlanguage TYPE dd01v-ddlanguage, ddtext TYPE dd01v-ddtext, END OF ty_dd01_text . TYPES: BEGIN OF ty_dd07_text, valpos TYPE dd07v-valpos, ddlanguage TYPE dd07v-ddlanguage, domvalue_l TYPE dd07v-domvalue_l, domvalue_h TYPE dd07v-domvalue_h, ddtext TYPE dd07v-ddtext, domval_ld TYPE dd07v-domval_ld, domval_hd TYPE dd07v-domval_hd, END OF ty_dd07_text . TYPES: ty_dd01_texts TYPE STANDARD TABLE OF ty_dd01_text . TYPES: ty_dd07_texts TYPE STANDARD TABLE OF ty_dd07_text . CONSTANTS c_longtext_id_doma TYPE dokil-id VALUE 'DO' ##NO_TEXT. METHODS serialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output !it_dd07v TYPE dd07v_tab RAISING zcx_abapgit_exception . METHODS deserialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input !is_dd01v TYPE dd01v !it_dd07v TYPE dd07v_tab RAISING zcx_abapgit_exception . METHODS handle_dependencies IMPORTING !iv_step TYPE zif_abapgit_definitions=>ty_deserialization_step CHANGING !cv_exit TYPE dd01v-convexit !cv_done TYPE abap_bool. METHODS adjust_exit CHANGING !cv_exit TYPE dd01v-convexit. METHODS check_exit IMPORTING !iv_exit TYPE dd01v-convexit RETURNING VALUE(rv_done) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_object_drul DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. METHODS: clear_fields CHANGING cs_dependency_rule TYPE any, clear_field IMPORTING iv_fieldname TYPE csequence CHANGING cs_dependency_rule TYPE any, fill_metadata_from_db CHANGING cs_dependency_rule TYPE any RAISING zcx_abapgit_exception, get_wb_object_operator RETURNING VALUE(ri_wb_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception. DATA: mr_dependency_rule TYPE REF TO data, mv_dependency_rule_key TYPE seu_objkey, mi_persistence TYPE REF TO if_wb_object_persist, mi_wb_object_operator TYPE REF TO object. ENDCLASS. CLASS zcl_abapgit_object_dsys DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_typ TYPE dokhl-typ VALUE 'E', c_id TYPE dokhl-id VALUE 'HY'. DATA: mv_doc_object TYPE sobj_name. TYPES: BEGIN OF ty_data, doctitle TYPE dsyst-doktitle, head TYPE thead, lines TYPE tline_tab, END OF ty_data. METHODS deserialize_dsys IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception. METHODS get_main_lang RETURNING VALUE(rv_language) TYPE spras. ENDCLASS. CLASS zcl_abapgit_object_dtdc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. METHODS: clear_fields CHANGING cs_dynamic_cache TYPE any, clear_field IMPORTING iv_fieldname TYPE csequence CHANGING cs_dynamic_cache TYPE any, fill_metadata_from_db CHANGING cs_dynamic_cache TYPE any RAISING zcx_abapgit_exception, get_wb_object_operator RETURNING VALUE(ri_wb_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception, has_own_wb_data_class RETURNING VALUE(rv_supported) TYPE abap_bool. DATA: mr_dynamic_cache TYPE REF TO data, mv_dynamic_cache_key TYPE seu_objkey, mv_has_own_wb_data_class TYPE abap_bool, mi_persistence TYPE REF TO if_wb_object_persist, mi_wb_object_operator TYPE REF TO object. ENDCLASS. CLASS zcl_abapgit_object_dtel DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_dd04_text, ddlanguage TYPE dd04t-ddlanguage, ddtext TYPE dd04t-ddtext, reptext TYPE dd04t-reptext, scrtext_s TYPE dd04t-scrtext_s, scrtext_m TYPE dd04t-scrtext_m, scrtext_l TYPE dd04t-scrtext_l, END OF ty_dd04_text . TYPES: ty_dd04_texts TYPE STANDARD TABLE OF ty_dd04_text . CONSTANTS c_longtext_id_dtel TYPE dokil-id VALUE 'DE' ##NO_TEXT. CONSTANTS c_longtext_id_dtel_suppl TYPE dokil-id VALUE 'DZ' ##NO_TEXT. METHODS serialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input !is_dd04v TYPE dd04v RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_ecatt_super DEFINITION INHERITING FROM zcl_abapgit_objects_super ABSTRACT CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. METHODS: get_object_type ABSTRACT RETURNING VALUE(rv_object_type) TYPE etobj_type, get_upload ABSTRACT RETURNING VALUE(ro_upload) TYPE REF TO cl_apl_ecatt_upload, get_download ABSTRACT RETURNING VALUE(ro_download) TYPE REF TO cl_apl_ecatt_download, get_lock_object ABSTRACT RETURNING VALUE(rv_lock_object) TYPE eqeobj. PRIVATE SECTION. TYPES: BEGIN OF ty_last_changed, luser TYPE syuname, ldate TYPE d, ltime TYPE t, END OF ty_last_changed. CONSTANTS: BEGIN OF c_name, version TYPE string VALUE 'VERSION' ##NO_TEXT, versions TYPE string VALUE 'VERSIONS' ##NO_TEXT, END OF c_name, c_default_version TYPE etobj_ver VALUE '1' ##NO_TEXT. CLASS-METHODS: is_change_more_recent_than IMPORTING is_currently_changed TYPE ty_last_changed is_last_changed TYPE ty_last_changed RETURNING VALUE(rv_is_change_more_recent) TYPE abap_bool. DATA: mv_object_name TYPE etobj_name. METHODS: get_changed_date IMPORTING ii_document TYPE REF TO if_ixml_document RETURNING VALUE(rv_changed_date) TYPE d, get_changed_time IMPORTING ii_document TYPE REF TO if_ixml_document RETURNING VALUE(rv_changed_time) TYPE t, get_changed_by_user IMPORTING ii_document TYPE REF TO if_ixml_document RETURNING VALUE(rv_changed_by_user) TYPE syuname, get_change_information IMPORTING is_version_info TYPE etversinfo RETURNING VALUE(rs_change_information) TYPE ty_last_changed RAISING cx_ecatt_apl zcx_abapgit_exception, clear_attributes CHANGING ci_document TYPE REF TO if_ixml_document, clear_elements CHANGING ci_document TYPE REF TO if_ixml_document, get_version_from_node IMPORTING ii_node TYPE REF TO if_ixml_node RETURNING VALUE(rv_version) TYPE string, deserialize_version IMPORTING ii_version_node TYPE REF TO if_ixml_node iv_package TYPE devclass RAISING zcx_abapgit_exception, serialize_version IMPORTING iv_version TYPE etversinfo-version CHANGING ci_node TYPE REF TO if_ixml_element RAISING cx_ecatt zcx_abapgit_exception, clear_element IMPORTING iv_name TYPE csequence CHANGING ci_document TYPE REF TO if_ixml_document, clear_element_collection IMPORTING iv_name TYPE csequence CHANGING ci_document TYPE REF TO if_ixml_document, serialize_versions IMPORTING it_version_info TYPE etversinfo_tabtype CHANGING ci_document TYPE REF TO if_ixml_document RAISING cx_ecatt zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_ecat DEFINITION INHERITING FROM zcl_abapgit_object_ecatt_super FINAL CREATE PUBLIC . PUBLIC SECTION. PROTECTED SECTION. METHODS: get_object_type REDEFINITION, get_upload REDEFINITION, get_download REDEFINITION, get_lock_object REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_ecsd DEFINITION INHERITING FROM zcl_abapgit_object_ecatt_super FINAL CREATE PUBLIC . PUBLIC SECTION. PROTECTED SECTION. METHODS: get_object_type REDEFINITION, get_upload REDEFINITION, get_download REDEFINITION, get_lock_object REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_ecsp DEFINITION INHERITING FROM zcl_abapgit_object_ecatt_super FINAL CREATE PUBLIC . PUBLIC SECTION. PROTECTED SECTION. METHODS: get_object_type REDEFINITION, get_upload REDEFINITION, get_download REDEFINITION, get_lock_object REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_ectc DEFINITION INHERITING FROM zcl_abapgit_object_ecatt_super FINAL CREATE PUBLIC . PUBLIC SECTION. PROTECTED SECTION. METHODS: get_object_type REDEFINITION, get_upload REDEFINITION, get_download REDEFINITION, get_lock_object REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_ectd DEFINITION INHERITING FROM zcl_abapgit_object_ecatt_super FINAL CREATE PUBLIC . PUBLIC SECTION. PROTECTED SECTION. METHODS: get_object_type REDEFINITION, get_upload REDEFINITION, get_download REDEFINITION, get_lock_object REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_ecvo DEFINITION INHERITING FROM zcl_abapgit_object_ecatt_super FINAL CREATE PUBLIC . PUBLIC SECTION. PROTECTED SECTION. METHODS: get_object_type REDEFINITION, get_upload REDEFINITION, get_download REDEFINITION, get_lock_object REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_enhc DEFINITION INHERITING FROM zcl_abapgit_objects_super. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mv_composite_id TYPE enhcompositename. ENDCLASS. CLASS zcl_abapgit_object_enho DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS: factory IMPORTING iv_tool TYPE enhtooltype RETURNING VALUE(ri_enho) TYPE REF TO zif_abapgit_object_enho RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_enhs DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS: factory IMPORTING iv_tool TYPE enhtooltype RETURNING VALUE(ri_enho) TYPE REF TO zif_abapgit_object_enhs RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_enqu DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_dd27p TYPE STANDARD TABLE OF dd27p WITH DEFAULT KEY. METHODS _clear_dd27p_fields CHANGING ct_dd27p TYPE ty_dd27p. ENDCLASS. CLASS zcl_abapgit_object_ensc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_fdt0 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS check_is_local RETURNING VALUE(rv_is_local) TYPE abap_bool . METHODS get_application_id RETURNING VALUE(rv_application_id) TYPE fdt_admn_0000s-application_id . METHODS before_xml_deserialize IMPORTING !iv_package TYPE devclass EXPORTING !ev_create TYPE abap_bool !ev_is_local TYPE abap_bool CHANGING !co_dom_tree TYPE REF TO if_ixml_document RAISING zcx_abapgit_exception . METHODS filter_xml_serialize CHANGING !co_ixml_element TYPE REF TO if_ixml_element RAISING zcx_abapgit_exception . METHODS set_field IMPORTING !iv_name TYPE string !iv_value TYPE string DEFAULT '' CHANGING !co_ixml_element TYPE REF TO if_ixml_element RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_form DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_objectname_form TYPE thead-tdobject VALUE 'FORM' ##NO_TEXT. CONSTANTS: c_objectname_tdlines TYPE thead-tdobject VALUE 'TDLINES' ##NO_TEXT. CONSTANTS: c_extension_xml TYPE string VALUE 'xml' ##NO_TEXT. DATA: mv_form_name TYPE itcta-tdform. TYPES: BEGIN OF ty_s_form_data, form_header TYPE itcta, text_header TYPE thead, orig_language TYPE sy-langu, pages TYPE STANDARD TABLE OF itctg WITH DEFAULT KEY, page_windows TYPE STANDARD TABLE OF itcth WITH DEFAULT KEY, paragraphs TYPE STANDARD TABLE OF itcdp WITH DEFAULT KEY, strings TYPE STANDARD TABLE OF itcds WITH DEFAULT KEY, tabs TYPE STANDARD TABLE OF itcdq WITH DEFAULT KEY, windows TYPE STANDARD TABLE OF itctw WITH DEFAULT KEY, END OF ty_s_form_data, ty_t_form_data TYPE STANDARD TABLE OF ty_s_form_data WITH DEFAULT KEY, ty_t_form_header TYPE STANDARD TABLE OF itcta WITH DEFAULT KEY, ty_s_form_header TYPE LINE OF ty_t_form_header, ty_t_text_header TYPE STANDARD TABLE OF thead WITH DEFAULT KEY, ty_s_text_header TYPE LINE OF ty_t_text_header, ty_t_lines TYPE tline_tab. METHODS get_last_changes IMPORTING iv_form_name TYPE zif_abapgit_definitions=>ty_item-obj_name RETURNING VALUE(rs_last_changed) TYPE ty_s_form_header. METHODS build_extra_from_header IMPORTING is_header TYPE ty_s_form_header RETURNING VALUE(rv_result) TYPE string. METHODS build_extra_from_header_old IMPORTING is_header TYPE ty_s_form_header RETURNING VALUE(rv_result) TYPE string. METHODS _save_form IMPORTING it_lines TYPE ty_t_lines CHANGING cs_form_data TYPE ty_s_form_data. METHODS extract_tdlines IMPORTING is_form_data TYPE ty_s_form_data RETURNING VALUE(rt_lines) TYPE ty_t_lines RAISING zcx_abapgit_exception. METHODS _clear_changed_fields CHANGING cs_form_data TYPE ty_s_form_data. METHODS compress_lines IMPORTING is_form_data TYPE ty_s_form_data it_lines TYPE ty_t_lines RAISING zcx_abapgit_exception. METHODS find_form IMPORTING iv_object_name TYPE zif_abapgit_definitions=>ty_item-obj_name RETURNING VALUE(rt_text_header) TYPE ty_t_text_header. METHODS _read_form IMPORTING is_text_header TYPE ty_s_text_header EXPORTING ev_form_found TYPE abap_bool es_form_data TYPE ty_s_form_data et_lines TYPE ty_t_lines. METHODS _sort_tdlines_by_windows CHANGING ct_form_windows TYPE ty_s_form_data-windows ct_lines TYPE ty_t_lines. METHODS order_check_and_insert RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_ftgl DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mv_toggle_id TYPE c LENGTH 40, "sftgl_ft_id mr_toggle TYPE REF TO data. METHODS: clear_field IMPORTING iv_fieldname TYPE string CHANGING cg_header TYPE any. ENDCLASS. CLASS zcl_abapgit_object_g4ba DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_g4bs DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_iamu DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_internet_appl_comp_binary, attributes TYPE w3mimeattr, source TYPE w3mimetabtype, length TYPE i, extension TYPE string, END OF ty_internet_appl_comp_binary. DATA: mi_mime_api TYPE REF TO if_w3_api_mime. METHODS: get_extension IMPORTING iv_name TYPE csequence iv_data TYPE xstring RETURNING VALUE(rv_extension) TYPE string, load_mime_api RAISING zcx_abapgit_exception, read RETURNING VALUE(rs_internet_appl_comp_binary) TYPE ty_internet_appl_comp_binary RAISING zcx_abapgit_exception, save IMPORTING is_internet_appl_comp_binary TYPE ty_internet_appl_comp_binary RAISING zcx_abapgit_exception, lock IMPORTING iv_changable TYPE abap_bool RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_iarp DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: ms_name TYPE w3resokey. METHODS: read EXPORTING es_attributes TYPE w3resoattr et_parameters TYPE w3resopara_tabletype RAISING zcx_abapgit_exception, save IMPORTING is_attributes TYPE w3resoattr it_parameters TYPE w3resopara_tabletype RAISING zcx_abapgit_exception, w3_api_load RETURNING VALUE(ri_resource) TYPE REF TO if_w3_api_resource RAISING zcx_abapgit_exception, w3_api_get_attributes IMPORTING ii_resource TYPE REF TO if_w3_api_resource RETURNING VALUE(rs_attributes) TYPE w3resoattr RAISING zcx_abapgit_exception, w3_api_get_parameters IMPORTING ii_resource TYPE REF TO if_w3_api_resource RETURNING VALUE(rt_parameters) TYPE w3resopara_tabletype RAISING zcx_abapgit_exception, w3_api_create_new IMPORTING is_attributes TYPE w3resoattr RETURNING VALUE(ri_resource) TYPE REF TO if_w3_api_resource RAISING zcx_abapgit_exception, w3_api_set_attributes IMPORTING ii_resource TYPE REF TO if_w3_api_resource is_attributes TYPE w3resoattr RAISING zcx_abapgit_exception, w3_api_set_parameters IMPORTING ii_resource TYPE REF TO if_w3_api_resource it_parameters TYPE w3resopara_tabletype RAISING zcx_abapgit_exception, w3_api_save IMPORTING ii_resource TYPE REF TO if_w3_api_resource RAISING zcx_abapgit_exception, w3_api_set_changeable IMPORTING ii_resource TYPE REF TO if_w3_api_resource iv_changeable TYPE abap_bool DEFAULT abap_true RAISING zcx_abapgit_exception, w3_api_delete IMPORTING ii_resource TYPE REF TO if_w3_api_resource RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_iasp DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mv_name TYPE itsappl. METHODS: read EXPORTING es_attr TYPE w3servattr et_parameters TYPE w3servpara_tabletype RAISING zcx_abapgit_exception, save IMPORTING is_attr TYPE w3servattr it_parameters TYPE w3servpara_tabletype RAISING zcx_abapgit_exception, w3_api_load RETURNING VALUE(ri_service) TYPE REF TO if_w3_api_service RAISING zcx_abapgit_exception, w3_api_get_attributes IMPORTING ii_service TYPE REF TO if_w3_api_service RETURNING VALUE(rs_attributes) TYPE w3servattr, w3_api_get_parameters IMPORTING ii_service TYPE REF TO if_w3_api_service RETURNING VALUE(rt_parameters) TYPE w3servpara_tabletype, w3_api_create_new IMPORTING is_attributes TYPE w3servattr RETURNING VALUE(ri_service) TYPE REF TO if_w3_api_service RAISING zcx_abapgit_exception, w3_api_set_attributes IMPORTING ii_service TYPE REF TO if_w3_api_service is_attributes TYPE w3servattr RAISING zcx_abapgit_exception, w3_api_set_parameters IMPORTING ii_service TYPE REF TO if_w3_api_service it_parameters TYPE w3servpara_tabletype RAISING zcx_abapgit_exception, w3_api_save IMPORTING ii_service TYPE REF TO if_w3_api_service RAISING zcx_abapgit_exception, w3_api_set_changeable IMPORTING ii_service TYPE REF TO if_w3_api_service iv_changeable TYPE abap_bool DEFAULT abap_true RAISING zcx_abapgit_exception, w3_api_delete IMPORTING ii_service TYPE REF TO if_w3_api_service RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_iatu DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS: read EXPORTING es_attr TYPE w3tempattr ev_source TYPE string RAISING zcx_abapgit_exception, save IMPORTING is_attr TYPE w3tempattr iv_source TYPE string RAISING zcx_abapgit_exception, w3_api_load IMPORTING is_name TYPE iacikeyt RETURNING VALUE(ri_template) TYPE REF TO if_w3_api_template RAISING zcx_abapgit_exception, w3_api_set_changeable IMPORTING iv_changeable TYPE abap_bool ii_template TYPE REF TO if_w3_api_template RAISING zcx_abapgit_exception, w3_api_delete IMPORTING ii_template TYPE REF TO if_w3_api_template RAISING zcx_abapgit_exception, w3_api_save IMPORTING ii_template TYPE REF TO if_w3_api_template RAISING zcx_abapgit_exception, w3_api_get_attributes IMPORTING ii_template TYPE REF TO if_w3_api_template RETURNING VALUE(rs_attributes) TYPE w3tempattr RAISING zcx_abapgit_exception, w3_api_get_source IMPORTING ii_template TYPE REF TO if_w3_api_template RETURNING VALUE(rt_source) TYPE w3htmltabtype RAISING zcx_abapgit_exception, w3_api_create_new IMPORTING is_template_data TYPE w3tempattr RETURNING VALUE(ri_template) TYPE REF TO if_w3_api_template RAISING zcx_abapgit_exception, w3_api_set_attributes IMPORTING ii_template TYPE REF TO if_w3_api_template is_attr TYPE w3tempattr RAISING zcx_abapgit_exception, w3_api_set_source IMPORTING ii_template TYPE REF TO if_w3_api_template it_source TYPE w3htmltabtype RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_iaxu DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. DATA: mv_source_style_2006 TYPE w3style VALUE 'XML', mv_generator_class TYPE w3styleclass VALUE 'CL_ITS_GENERATE_XML3'. METHODS: read RETURNING VALUE(rs_attr) TYPE w3tempattr RAISING zcx_abapgit_exception, save IMPORTING is_attr TYPE w3tempattr RAISING zcx_abapgit_exception, w3_api_load IMPORTING is_name TYPE iacikeyt EXPORTING eo_xml_api TYPE REF TO object es_attr TYPE w3tempattr RAISING zcx_abapgit_exception, w3_api_set_changeable IMPORTING io_xml_api TYPE REF TO object iv_changeable TYPE abap_bool RAISING zcx_abapgit_exception, w3_api_delete IMPORTING io_xml_api TYPE REF TO object RAISING zcx_abapgit_exception, w3_api_save IMPORTING io_xml_api TYPE REF TO object RAISING zcx_abapgit_exception, w3_api_create_new IMPORTING is_attr TYPE w3tempattr RETURNING VALUE(ro_xml_api) TYPE REF TO object RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_idoc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. CLASS-METHODS clear_idoc_segement_fields CHANGING cg_structure TYPE any. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_idoc, attributes TYPE edi_iapi01, t_syntax TYPE STANDARD TABLE OF edi_iapi02 WITH NON-UNIQUE DEFAULT KEY, END OF ty_idoc. DATA: mv_idoctyp TYPE edi_iapi00-idoctyp. CLASS-METHODS clear_idoc_segement_field IMPORTING iv_fieldname TYPE csequence CHANGING cg_structure TYPE any. METHODS is_closed RETURNING VALUE(rv_closed) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_object_iext DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_extention, attributes TYPE edi_iapi01, t_syntax TYPE STANDARD TABLE OF edi_iapi03 WITH NON-UNIQUE DEFAULT KEY, END OF ty_extention. CONSTANTS c_dataname_iext TYPE string VALUE 'IEXT' ##NO_TEXT. DATA: mv_extension TYPE edi_cimtyp. ENDCLASS. CLASS zcl_abapgit_object_iobj DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS: clear_field IMPORTING iv_fieldname TYPE string CHANGING cg_metadata TYPE any. ENDCLASS. CLASS zcl_abapgit_object_iwmo DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_iwom DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_iwpr DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_iwsg DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_iwsv DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_iwvb DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_jobd DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_jd_name TYPE c LENGTH 32. ENDCLASS. CLASS zcl_abapgit_object_msag DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_t100_text, sprsl TYPE t100-sprsl, msgnr TYPE t100-msgnr, text TYPE t100-text, END OF ty_t100_text . TYPES: ty_t100_texts TYPE STANDARD TABLE OF ty_t100_text . TYPES: ty_t100s TYPE STANDARD TABLE OF t100 WITH NON-UNIQUE DEFAULT KEY . CONSTANTS c_longtext_id_msag TYPE dokil-id VALUE 'NA'. METHODS serialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS serialize_longtexts_msag IMPORTING !it_t100 TYPE ty_t100s !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS delete_msgid IMPORTING !iv_message_id TYPE arbgb . METHODS free_access_permission IMPORTING !iv_message_id TYPE arbgb . METHODS delete_documentation IMPORTING !iv_message_id TYPE arbgb . ENDCLASS. CLASS zcl_abapgit_object_nrob DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS: delete_intervals IMPORTING iv_object TYPE inri-object RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_nspc DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . METHODS constructor IMPORTING is_item TYPE zif_abapgit_definitions=>ty_item iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_nspc, namespace TYPE trnspacet-namespace, replicense TYPE trnspacet-replicense, sscrflag TYPE trnspacet-sscrflag, sapflag TYPE trnspacet-sapflag, gen_only TYPE trnspacet-gen_only, END OF ty_nspc . TYPES: BEGIN OF ty_nspc_text, spras TYPE trnspacett-spras, descriptn TYPE trnspacett-descriptn, owner TYPE trnspacett-owner, END OF ty_nspc_text . TYPES: ty_nspc_texts TYPE STANDARD TABLE OF ty_nspc_text . DATA mv_component TYPE cvers-component. METHODS serialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input !iv_namespace TYPE namespace RAISING zcx_abapgit_exception . METHODS add_to_transport IMPORTING !iv_package TYPE devclass RAISING zcx_abapgit_exception . METHODS serialize_sw_component IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_sw_component IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_oa2p DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mv_profile TYPE c LENGTH 30. ENDCLASS. CLASS zcl_abapgit_object_odso DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS: clear_field IMPORTING iv_fieldname TYPE string CHANGING cg_metadata TYPE any. ENDCLASS. CLASS zcl_abapgit_object_otgr DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_otgr, cls_type_group TYPE cls_type_group, texts TYPE STANDARD TABLE OF cls_type_groupt WITH DEFAULT KEY, elements TYPE STANDARD TABLE OF cls_tygr_element WITH DEFAULT KEY, END OF ty_otgr . METHODS instantiate_and_lock_otgr RETURNING VALUE(ro_otgr) TYPE REF TO cl_cls_object_type_group RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_para DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS unlock IMPORTING !iv_paramid TYPE memoryid . ENDCLASS. CLASS zcl_abapgit_object_pdxx_super DEFINITION INHERITING FROM zcl_abapgit_objects_super ABSTRACT. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. DATA ms_objkey TYPE hrsobject. METHODS check_subrc_for IMPORTING iv_call TYPE clike OPTIONAL RAISING zcx_abapgit_exception. PRIVATE SECTION. ENDCLASS. INTERFACE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa DEFERRED. * renamed: zcl_abapgit_object_pdts :: lif_task_definition INTERFACE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa. TYPES: BEGIN OF ty_task_data, short_text TYPE hr_mcshort, plvar TYPE plvar, wi_text TYPE witext, method TYPE hrs1201, method_binding TYPE hrsmtbind, starting_events TYPE hrsevtab, starting_events_binding TYPE hrsevbind, terminating_events TYPE hrsetmtab, terminating_events_binding TYPE hrsevbind, descriptions TYPE wstexts, END OF ty_task_data. METHODS clear_origin_data. METHODS get_definition RETURNING VALUE(rs_result) TYPE ty_task_data. METHODS get_container RETURNING VALUE(ri_result) TYPE REF TO if_swf_cnt_container. METHODS get_user_container RETURNING VALUE(ri_result) TYPE REF TO if_swf_cnt_container. METHODS import_container IMPORTING iv_xml_string TYPE xstring RAISING zcx_abapgit_exception. METHODS create_task RAISING zcx_abapgit_exception. METHODS save IMPORTING iv_package TYPE devclass OPTIONAL RAISING zcx_abapgit_exception. METHODS change_wi_text RAISING zcx_abapgit_exception. METHODS change_method RAISING zcx_abapgit_exception. METHODS change_start_events RAISING zcx_abapgit_exception. METHODS change_terminating_events RAISING zcx_abapgit_exception. METHODS change_text RAISING zcx_abapgit_exception. ENDINTERFACE. CLASS zcl_abapgit_object_pdts DEFINITION INHERITING FROM zcl_abapgit_object_pdxx_super FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. METHODS zif_abapgit_object~serialize REDEFINITION. METHODS zif_abapgit_object~deserialize REDEFINITION. PROTECTED SECTION. PRIVATE SECTION. DATA mv_objid TYPE hrobjid. METHODS get_container_xml IMPORTING ii_task TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa RETURNING VALUE(ri_first_element) TYPE REF TO if_ixml_element RAISING zcx_abapgit_exception. METHODS extract_container IMPORTING io_xml TYPE REF TO zif_abapgit_xml_input RETURNING VALUE(rv_result) TYPE xstring. ENDCLASS. CLASS zcl_abapgit_object_pers DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_personalization_object, pers_reg TYPE spers_reg, pers_reg_text TYPE spers_regt, END OF ty_personalization_object. DATA: mv_pers_key TYPE spers_key. METHODS: get_personalization_object IMPORTING iv_create TYPE abap_bool OPTIONAL iv_view_only TYPE abap_bool OPTIONAL RETURNING VALUE(ro_personalization_object) TYPE REF TO cl_pers_reg RAISING zcx_abapgit_exception. ENDCLASS. CLASS kHGwlqJyKbsVHldwKaGddDbbHeNaet DEFINITION DEFERRED. INTERFACE iUFTsqJyKbsVHldwKaGdXoRoiJNIwT DEFERRED. * renamed: zcl_abapgit_object_pinf :: lif_package_interface_facade INTERFACE iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. TYPES ty_tpak_package_interf_elem_tt TYPE STANDARD TABLE OF tpak_package_interf_elem_ref WITH DEFAULT KEY. METHODS: get_elements RETURNING VALUE(rt_elements) TYPE ty_tpak_package_interf_elem_tt RAISING zcx_abapgit_exception, set_elements_changeable IMPORTING iv_changeable TYPE abap_bool RAISING zcx_abapgit_exception, save_elements RAISING zcx_abapgit_exception, get_all_attributes RETURNING VALUE(rs_package_interface_data) TYPE scompidtln RAISING zcx_abapgit_exception, set_changeable IMPORTING iv_changeable TYPE abap_bool RAISING zcx_abapgit_exception, delete RAISING zcx_abapgit_exception, save RAISING zcx_abapgit_exception, remove_elements IMPORTING it_elements TYPE tpak_package_interf_elem_list RAISING zcx_abapgit_exception, add_elements IMPORTING it_elements_data TYPE scomeldata RAISING zcx_abapgit_exception, set_all_attributes IMPORTING is_package_interface_data TYPE scompidtln is_data_sign TYPE scompisign RAISING zcx_abapgit_exception, get_changeable RETURNING VALUE(rv_changeable) TYPE abap_bool RAISING zcx_abapgit_exception. ENDINTERFACE. * renamed: zcl_abapgit_object_pinf :: lcl_package_interface_facade CLASS kHGwlqJyKbsVHldwKaGddDbbHeNaet DEFINITION. PUBLIC SECTION. INTERFACES: iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. METHODS: constructor IMPORTING ii_interface TYPE REF TO if_package_interface. PRIVATE SECTION. DATA: mi_interface TYPE REF TO if_package_interface. ENDCLASS. CLASS zcl_abapgit_object_pinf DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_pinf, attributes TYPE scompidtln, elements TYPE STANDARD TABLE OF scomeldtln WITH DEFAULT KEY, END OF ty_pinf . TYPES: ty_elements TYPE STANDARD TABLE OF tpak_package_interf_elem_ref WITH DEFAULT KEY . METHODS create_or_load IMPORTING !is_pinf TYPE ty_pinf !iv_package TYPE devclass RETURNING VALUE(ri_interface) TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT RAISING zcx_abapgit_exception . METHODS delete_elements IMPORTING !ii_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT RAISING zcx_abapgit_exception . METHODS update_attributes IMPORTING !iv_package TYPE devclass !is_pinf TYPE ty_pinf !ii_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT RAISING zcx_abapgit_exception . METHODS update_elements IMPORTING !iv_package TYPE devclass !is_pinf TYPE ty_pinf !ii_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT RAISING zcx_abapgit_exception . METHODS load IMPORTING iv_name TYPE scomifnam RETURNING VALUE(ri_interface) TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. METHODS create_facade IMPORTING ii_interface TYPE REF TO if_package_interface RETURNING VALUE(ri_facade) TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. ENDCLASS. CLASS zcl_abapgit_object_prag DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_pragma, pragma TYPE c LENGTH 40, extension TYPE c LENGTH 1, signature TYPE c LENGTH 10, description TYPE c LENGTH 255, END OF ty_pragma. ENDCLASS. CLASS zcl_abapgit_object_saxx_super DEFINITION INHERITING FROM zcl_abapgit_objects_super ABSTRACT CREATE PUBLIC . * common class for SAPC and SAMC objects PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. METHODS get_persistence_class_name ABSTRACT RETURNING VALUE(rv_persistence_class_name) TYPE seoclsname . METHODS get_data_class_name ABSTRACT RETURNING VALUE(rv_data_class_name) TYPE seoclsname . METHODS get_data_structure_name ABSTRACT RETURNING VALUE(rv_data_structure_name) TYPE string . PRIVATE SECTION. DATA mi_persistence TYPE REF TO if_wb_object_persist . DATA mi_appl_obj_data TYPE REF TO if_wb_object_data_model . DATA mv_data_structure_name TYPE string . DATA mv_appl_obj_cls_name TYPE seoclsname . DATA mv_persistence_cls_name TYPE seoclsname . METHODS create_channel_objects RAISING zcx_abapgit_exception . METHODS get_data EXPORTING !eg_data TYPE any RAISING zcx_abapgit_exception . METHODS lock RAISING zcx_abapgit_exception . METHODS unlock RAISING zcx_abapgit_exception . METHODS get_names . ENDCLASS. CLASS zcl_abapgit_object_samc DEFINITION INHERITING FROM zcl_abapgit_object_saxx_super FINAL CREATE PUBLIC . PUBLIC SECTION. PROTECTED SECTION. METHODS get_data_class_name REDEFINITION . METHODS get_data_structure_name REDEFINITION . METHODS get_persistence_class_name REDEFINITION . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_sapc DEFINITION INHERITING FROM zcl_abapgit_object_saxx_super FINAL CREATE PUBLIC . PUBLIC SECTION. PROTECTED SECTION. METHODS get_data_class_name REDEFINITION . METHODS get_data_structure_name REDEFINITION . METHODS get_persistence_class_name REDEFINITION . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_scp1 DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. TYPES: BEGIN OF ty_scp1, scprattr TYPE scprattr, scprtext TYPE STANDARD TABLE OF scprtext WITH DEFAULT KEY, scprvals TYPE STANDARD TABLE OF scprvals WITH DEFAULT KEY, scprvall TYPE STANDARD TABLE OF scprvall WITH DEFAULT KEY, scprreca TYPE STANDARD TABLE OF scprreca WITH DEFAULT KEY, scprfldv TYPE STANDARD TABLE OF scprfldv WITH DEFAULT KEY, subprofs TYPE STANDARD TABLE OF scprpprl WITH DEFAULT KEY, END OF ty_scp1 . METHODS dequeue . METHODS enqueue RAISING zcx_abapgit_exception . METHODS save IMPORTING !is_scp1 TYPE ty_scp1 RAISING zcx_abapgit_exception . METHODS save_hier IMPORTING !is_scp1 TYPE ty_scp1 RAISING zcx_abapgit_exception . METHODS adjust_inbound CHANGING !cs_scp1 TYPE ty_scp1 . METHODS adjust_outbound CHANGING !cs_scp1 TYPE ty_scp1 . METHODS load CHANGING !cs_scp1 TYPE ty_scp1 . METHODS load_hier CHANGING !cs_scp1 TYPE ty_scp1 . METHODS call_delete_fms IMPORTING !iv_profile_id TYPE scpr_id RAISING zcx_abapgit_exception . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_scvi DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_screen_variant, shdsvci TYPE shdsvci, shdsvtxci TYPE STANDARD TABLE OF shdsvtxci WITH DEFAULT KEY, shdsvfvci TYPE STANDARD TABLE OF shdsvfvci WITH DEFAULT KEY, shdguixt TYPE STANDARD TABLE OF shdguixt WITH DEFAULT KEY, shdgxtcode TYPE STANDARD TABLE OF shdgxtcode WITH DEFAULT KEY, END OF ty_screen_variant . ENDCLASS. CLASS zcl_abapgit_object_sfbf DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_longtext_id_sfbf TYPE dokil-id VALUE 'BF'. DATA mv_bf TYPE sfw_bfunction. METHODS: unlock, activate RAISING zcx_abapgit_exception, create RETURNING VALUE(ro_bf) TYPE REF TO cl_sfw_bf RAISING zcx_abapgit_exception, get RETURNING VALUE(ro_bf) TYPE REF TO cl_sfw_bf RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_sfbs DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_longtext_id_sfbs TYPE dokil-id VALUE 'BS'. DATA mv_bfset TYPE sfw_bset. METHODS: unlock, activate RAISING zcx_abapgit_exception, create RETURNING VALUE(ro_bfs) TYPE REF TO cl_sfw_bfs RAISING zcx_abapgit_exception, get RETURNING VALUE(ro_bfs) TYPE REF TO cl_sfw_bfs RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_sfpf DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . CLASS-METHODS fix_oref IMPORTING !ii_document TYPE REF TO if_ixml_document RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_layout_file_ext TYPE string VALUE 'xdp'. METHODS: load RETURNING VALUE(ri_wb_form) TYPE REF TO if_fp_wb_form RAISING zcx_abapgit_exception, form_to_xstring RETURNING VALUE(rv_xstr) TYPE xstring RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_sfpi DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS: load RETURNING VALUE(ri_wb_interface) TYPE REF TO if_fp_wb_interface RAISING zcx_abapgit_exception, interface_to_xstring RETURNING VALUE(rv_xstr) TYPE xstring RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_sfsw DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_longtext_id_sfsw TYPE dokil-id VALUE 'SW'. DATA mv_switch TYPE sfw_switch_id. METHODS: unlock, activate RAISING zcx_abapgit_exception, create RETURNING VALUE(ro_switch) TYPE REF TO cl_sfw_sw RAISING zcx_abapgit_exception, get RETURNING VALUE(ro_switch) TYPE REF TO cl_sfw_sw RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_shi3 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. METHODS has_authorization IMPORTING !iv_devclass TYPE devclass !iv_structure_id TYPE hier_guid !iv_activity TYPE activ_auth RAISING zcx_abapgit_exception . METHODS is_used IMPORTING !iv_structure_id TYPE hier_guid RAISING zcx_abapgit_exception . METHODS delete_tree_structure IMPORTING !iv_structure_id TYPE hier_guid . PRIVATE SECTION. DATA mv_tree_id TYPE ttree-id. METHODS insert_transport IMPORTING !iv_transport TYPE trkorr RAISING zcx_abapgit_exception. METHODS jump_se43 RAISING zcx_abapgit_exception. METHODS jump_sbach04 RAISING zcx_abapgit_exception. METHODS clear_fields CHANGING !cs_head TYPE ttree !ct_nodes TYPE hier_iface_t. ENDCLASS. CLASS zcl_abapgit_object_shi5 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_ttree_extt TYPE STANDARD TABLE OF ttree_extt WITH NON-UNIQUE DEFAULT KEY, BEGIN OF ty_extension, header TYPE ttree_ext, texts TYPE ty_ttree_extt, sequences TYPE STANDARD TABLE OF ttrees WITH NON-UNIQUE DEFAULT KEY, END OF ty_extension. DATA: mv_extension TYPE hier_names. ENDCLASS. CLASS zcl_abapgit_object_shi8 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mv_assignment_id TYPE hier_sfw_id. ENDCLASS. CLASS zcl_abapgit_object_shlp DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS handle_dependencies IMPORTING !iv_step TYPE zif_abapgit_definitions=>ty_deserialization_step CHANGING !cv_exit TYPE dd30v-selmexit !cv_done TYPE abap_bool. METHODS adjust_exit CHANGING !cv_exit TYPE dd30v-selmexit. METHODS check_exit IMPORTING !iv_exit TYPE dd30v-selmexit RETURNING VALUE(rv_done) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_object_shma DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_sicf DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. TYPES ty_hash TYPE c LENGTH 25. TYPES: ty_icfhandler_tt TYPE STANDARD TABLE OF icfhandler WITH DEFAULT KEY . TYPES: BEGIN OF ty_sicf_key, icf_name TYPE icfservice-icf_name, icfparguid TYPE icfservice-icfparguid, END OF ty_sicf_key . METHODS serialize_otr IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_otr IMPORTING !iv_package TYPE devclass !io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS read IMPORTING !iv_clear TYPE abap_bool DEFAULT abap_true EXPORTING !es_icfservice TYPE icfservice !es_icfdocu TYPE icfdocu !et_icfhandler TYPE ty_icfhandler_tt !ev_url TYPE string RAISING zcx_abapgit_exception . METHODS insert_sicf IMPORTING !is_icfservice TYPE icfservice !is_icfdocu TYPE icfdocu !it_icfhandler TYPE ty_icfhandler_tt !iv_package TYPE devclass !iv_url TYPE string RAISING zcx_abapgit_exception . METHODS change_sicf IMPORTING !is_icfservice TYPE icfservice !is_icfdocu TYPE icfdocu !it_icfhandler TYPE ty_icfhandler_tt !iv_package TYPE devclass !iv_parent TYPE icfparguid RAISING zcx_abapgit_exception . METHODS to_icfhndlist IMPORTING !it_list TYPE ty_icfhandler_tt RETURNING VALUE(rt_list) TYPE icfhndlist . METHODS find_parent IMPORTING !iv_url TYPE string RETURNING VALUE(rv_parent) TYPE icfparguid RAISING zcx_abapgit_exception . CLASS-METHODS get_hash_from_object IMPORTING !iv_obj_name TYPE tadir-obj_name RETURNING VALUE(rv_hash) TYPE ty_hash RAISING zcx_abapgit_exception. CLASS-METHODS get_icfaltname IMPORTING !is_icfservice TYPE icfservice RETURNING VALUE(rv_icfaltnme) TYPE icfservice-icfaltnme. ENDCLASS. CLASS zcl_abapgit_object_sktd DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mr_data TYPE REF TO data . DATA mv_object_key TYPE seu_objkey . DATA mi_persistence TYPE REF TO if_wb_object_persist . DATA mi_wb_object_operator TYPE REF TO object . METHODS clear_fields CHANGING !cs_data TYPE any . METHODS clear_field IMPORTING !iv_fieldname TYPE csequence CHANGING !cs_data TYPE any . METHODS get_wb_object_operator RETURNING VALUE(ri_wb_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_smim DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS get_filename IMPORTING iv_url TYPE string RETURNING VALUE(rv_filename) TYPE string. METHODS find_content IMPORTING iv_url TYPE string RETURNING VALUE(rv_content) TYPE xstring RAISING zcx_abapgit_exception. METHODS build_filename IMPORTING iv_filename TYPE string RETURNING VALUE(rv_filename) TYPE string. METHODS get_url_for_io EXPORTING ev_url TYPE string ev_is_folder TYPE abap_bool RAISING zcx_abapgit_not_found zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_smtg DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mv_template_id TYPE c LENGTH 30, mo_structdescr TYPE REF TO cl_abap_structdescr. METHODS: clear_field IMPORTING iv_fieldname TYPE string CHANGING cg_header TYPE any, get_structure RETURNING VALUE(ro_structdescr) TYPE REF TO cl_abap_structdescr RAISING zcx_abapgit_exception, add_component IMPORTING iv_fielname TYPE string iv_structure_name TYPE string CHANGING ct_components TYPE abap_component_tab RAISING zcx_abapgit_exception, get_template EXPORTING es_template TYPE any RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_sobj DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS get_field_rules RETURNING VALUE(ri_rules) TYPE REF TO zif_abapgit_field_rules. METHODS is_locked RETURNING VALUE(rv_is_locked) TYPE abap_bool. METHODS is_objtype_locked RETURNING VALUE(rv_is_locked) TYPE abap_bool. METHODS is_program_locked RETURNING VALUE(rv_is_locked) TYPE abap_bool. METHODS get_program RETURNING VALUE(rv_program) TYPE tojtb-progname. ENDCLASS. CLASS zcl_abapgit_object_sod1 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_xml_transformation_name TYPE string VALUE 'SOD1', c_data_model_class_name TYPE string VALUE 'CL_APS_ODA_WBI_SOD1_DATA_MODEL'. METHODS create_wb_object_operator IMPORTING !is_object_type TYPE wbobjtype !iv_object_key TYPE seu_objkey !iv_transport_request TYPE trkorr OPTIONAL !iv_do_commits TYPE abap_bool DEFAULT abap_true !iv_run_in_test_mode TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_wb_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception. METHODS get_wb_object_operator IMPORTING !is_object_type TYPE wbobjtype !iv_object_key TYPE seu_objkey !iv_transport_request TYPE trkorr OPTIONAL RETURNING VALUE(ro_wb_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception. METHODS clear_metadata_fields CHANGING !cs_data TYPE any. METHODS clear_content_fields CHANGING !cs_data TYPE any. METHODS clear_field IMPORTING !iv_fieldname TYPE csequence CHANGING !cs_metadata TYPE any. ENDCLASS. CLASS zcl_abapgit_object_sod2 DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_xml_transformation_name TYPE string VALUE 'SOD2', c_data_model_class_name TYPE string VALUE 'CL_APS_ODA_WBI_SOD2_DATA_MODEL'. METHODS create_wb_object_operator IMPORTING !is_object_type TYPE wbobjtype !iv_object_key TYPE seu_objkey !iv_transport_request TYPE trkorr OPTIONAL !iv_do_commits TYPE abap_bool DEFAULT abap_true !iv_run_in_test_mode TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_wb_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception. METHODS get_wb_object_operator IMPORTING !is_object_type TYPE wbobjtype !iv_object_key TYPE seu_objkey !iv_transport_request TYPE trkorr OPTIONAL RETURNING VALUE(ro_wb_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception. METHODS clear_metadata_fields CHANGING !cs_data TYPE any. METHODS clear_content_fields CHANGING !cs_data TYPE any. METHODS clear_field IMPORTING !iv_fieldname TYPE csequence CHANGING !cs_metadata TYPE any. ENDCLASS. CLASS zcl_abapgit_object_sots DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES: zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_sots, header TYPE sotr_headu, entries TYPE sotr_textl_tt, END OF ty_sots, ty_sots_tt TYPE STANDARD TABLE OF ty_sots WITH NON-UNIQUE DEFAULT KEY. METHODS: read_sots RETURNING VALUE(rt_sots) TYPE ty_sots_tt, create_sots IMPORTING is_sots TYPE ty_sots iv_package TYPE devclass iv_object TYPE trobjtype RAISING zcx_abapgit_exception, get_raw_text_filename IMPORTING is_entry TYPE sotr_textl RETURNING VALUE(rv_filename) TYPE string. ENDCLASS. CLASS zcl_abapgit_object_splo DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_sppf DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_sprx DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES: zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_proxy, data TYPE string VALUE 'PROXY_DATA' ##NO_TEXT, header TYPE string VALUE 'PROXY_HEADER' ##NO_TEXT, END OF c_proxy . DATA mv_object TYPE sproxhdr-object . DATA mv_obj_name TYPE sproxhdr-obj_name . METHODS load_db RETURNING VALUE(rs_data) TYPE sprx_db_data . METHODS get_object_and_name EXPORTING !ev_object TYPE sproxhdr-object !ev_obj_name TYPE sproxhdr-obj_name . METHODS delta_handling IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input EXPORTING !et_sproxhdr_new TYPE sprx_hdr_t !et_sproxdat_new TYPE sprx_dat_t RAISING zcx_abapgit_exception . METHODS check_sprx_tadir RAISING zcx_abapgit_exception . METHODS save IMPORTING !it_sproxhdr_new TYPE sprx_hdr_t !it_sproxdat_new TYPE sprx_dat_t . ENDCLASS. CLASS zcl_abapgit_object_sqsc DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. " Downport original structures from " - IF_DBPROC_PROXY_UI " - IF_DBPROC_PROXY_BASIC_TYPES TYPES: ty_db_name TYPE c LENGTH 256, ty_abap_name TYPE c LENGTH 30, ty_param_direction TYPE c LENGTH 10, ty_param_kind TYPE c LENGTH 10, ty_ddic_name TYPE ddobjname, BEGIN OF ty_db_simple_type_s, name TYPE ty_db_name, length TYPE i, decs TYPE i, END OF ty_db_simple_type_s, BEGIN OF ty_abap_simple_type_s, name TYPE ty_abap_name, length TYPE i, decs TYPE i, END OF ty_abap_simple_type_s, BEGIN OF ty_abap_simple_type_ui_s, typ TYPE ty_abap_simple_type_s, text TYPE string, END OF ty_abap_simple_type_ui_s, BEGIN OF ty_header_ui_s, db_repository_package TYPE ty_db_name, db_repository_proc_name TYPE ty_db_name, db_catalog_schema TYPE ty_db_name, db_catalog_proc_name TYPE ty_db_name, read_only TYPE abap_bool, interface_pool TYPE ty_abap_name, END OF ty_header_ui_s, BEGIN OF ty_param_ui_s, position TYPE i, db_name TYPE ty_db_name, direction TYPE ty_param_direction, kind TYPE ty_param_kind, db_table_type_schema TYPE ty_db_name, db_table_type_name TYPE ty_db_name, db_table_type_is_ddic TYPE abap_bool, transfer_table_schema TYPE ty_db_name, transfer_table_name TYPE ty_db_name, abap_name TYPE ty_abap_name, abap_name_is_ro TYPE abap_bool, ddic_table TYPE ty_ddic_name, ddic_table_is_ro TYPE abap_bool, END OF ty_param_ui_s, ty_param_ui_t TYPE STANDARD TABLE OF ty_param_ui_s WITH KEY position, ty_abap_simple_type_ui_t TYPE STANDARD TABLE OF ty_abap_simple_type_ui_s WITH DEFAULT KEY, BEGIN OF ty_param_type_ui_s, param_position TYPE i, comp_index TYPE i, db_comp_name TYPE ty_db_name, abap_comp_name TYPE ty_abap_name, abap_comp_name_is_ro TYPE abap_bool, db_type TYPE ty_db_simple_type_s, db_type_text TYPE string, abap_type TYPE ty_abap_simple_type_ui_s, abap_type_is_ro TYPE abap_bool, abap_type_selection TYPE ty_abap_simple_type_ui_t, ddic_type TYPE ty_ddic_name, ddic_type_is_ro TYPE abap_bool, END OF ty_param_type_ui_s , ty_param_type_ui_t TYPE STANDARD TABLE OF ty_param_type_ui_s WITH KEY param_position comp_index, BEGIN OF ty_proxy, description TYPE ddtext, header TYPE ty_header_ui_s, parameters TYPE ty_param_ui_t, parameter_types TYPE ty_param_type_ui_t, END OF ty_proxy. DATA: mo_proxy TYPE REF TO object. METHODS: delete_interface_if_it_exists IMPORTING iv_package TYPE devclass iv_transport TYPE trkorr iv_interface TYPE ty_abap_name RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_srfc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_srvb DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. METHODS: clear_fields CHANGING cs_service_binding TYPE any, clear_field IMPORTING iv_fieldname TYPE csequence CHANGING cs_service_binding TYPE any. METHODS get_wb_object_operator RETURNING VALUE(ro_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception . METHODS merge_object_data IMPORTING !io_object_data TYPE REF TO object RETURNING VALUE(ro_object_data_merged) TYPE REF TO if_wb_object_data_model RAISING zcx_abapgit_exception . METHODS get_object_data IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input RETURNING VALUE(ro_object_data) TYPE REF TO if_wb_object_data_model RAISING zcx_abapgit_exception . METHODS is_ai_supported RETURNING VALUE(rv_ai_supported) TYPE abap_bool. DATA: mi_persistence TYPE REF TO if_wb_object_persist, mv_is_inactive_supported TYPE abap_bool, mv_service_binding_key TYPE seu_objkey, mr_service_binding TYPE REF TO data, mr_srvb_svrs_config TYPE REF TO object, mo_object_operator TYPE REF TO object. ENDCLASS. CLASS zcl_abapgit_object_srvd DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mv_service_definition_key TYPE seu_objkey . DATA mr_service_definition TYPE REF TO data . CONSTANTS c_source_file TYPE string VALUE 'srvdsrv' ##NO_TEXT. CONSTANTS c_xml_parent_name TYPE string VALUE 'SRVD' ##NO_TEXT. DATA mo_object_operator TYPE REF TO object . METHODS clear_fields CHANGING !cs_metadata TYPE any . METHODS clear_field IMPORTING !iv_fieldname TYPE csequence CHANGING !cs_metadata TYPE any . METHODS get_object_data IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input RETURNING VALUE(ro_object_data) TYPE REF TO if_wb_object_data_model RAISING zcx_abapgit_exception . METHODS get_wb_object_operator RETURNING VALUE(ro_object_operator) TYPE REF TO object RAISING zcx_abapgit_exception . METHODS merge_object_data IMPORTING !io_object_data TYPE REF TO object RETURNING VALUE(ro_object_data_merged) TYPE REF TO if_wb_object_data_model RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_ssfo DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_string_range TYPE RANGE OF string . CLASS-DATA gt_range_node_codes TYPE ty_string_range . CONSTANTS c_attrib_abapgit_leadig_spaces TYPE string VALUE 'abapgit-leadig-spaces' ##NO_TEXT. METHODS fix_ids IMPORTING !ii_xml_doc TYPE REF TO if_ixml_document . METHODS sort_texts IMPORTING !ii_xml_doc TYPE REF TO if_ixml_document RAISING zcx_abapgit_exception . METHODS handle_attrib_leading_spaces IMPORTING !iv_name TYPE string !ii_node TYPE REF TO if_ixml_node CHANGING !cv_within_code_section TYPE abap_bool . METHODS get_range_node_codes RETURNING VALUE(rt_range_node_codes) TYPE ty_string_range . METHODS code_item_section_handling IMPORTING !iv_name TYPE string !ii_node TYPE REF TO if_ixml_node EXPORTING !ei_code_item_element TYPE REF TO if_ixml_element CHANGING !cv_within_code_section TYPE abap_bool RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_ssst DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. CONSTANTS: c_style_active TYPE tdactivate VALUE 'A'. PROTECTED SECTION. PRIVATE SECTION. METHODS validate_font IMPORTING iv_tdfamily TYPE tdfamily RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_stvi DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_transaction_variant, shdtvciu TYPE shdtvciu, shdttciu TYPE STANDARD TABLE OF shdttciu WITH DEFAULT KEY, shdfvguicu TYPE STANDARD TABLE OF shdfvguicu WITH DEFAULT KEY, shdtvsvciu TYPE STANDARD TABLE OF shdtvsvciu WITH DEFAULT KEY, END OF ty_transaction_variant. ENDCLASS. CLASS zcl_abapgit_object_styl DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_style, header TYPE itcda, paragraphs TYPE STANDARD TABLE OF itcdp WITH DEFAULT KEY, strings TYPE STANDARD TABLE OF itcds WITH DEFAULT KEY, tabs TYPE STANDARD TABLE OF itcdq WITH DEFAULT KEY, END OF ty_style. ENDCLASS. CLASS zcl_abapgit_object_sucu DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_susc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. CONSTANTS c_transobjecttype_class TYPE c LENGTH 1 VALUE 'C' ##NO_TEXT. METHODS has_authorization IMPORTING !iv_class TYPE tobc-oclss !iv_activity TYPE activ_auth RAISING zcx_abapgit_exception . METHODS is_used IMPORTING !iv_auth_object_class TYPE tobc-oclss RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS delete_class IMPORTING !iv_auth_object_class TYPE tobc-oclss . METHODS put_delete_to_transport RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_sush DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. METHODS clear_metadata CHANGING cs_data_head TYPE any ct_usobx TYPE table ct_usobt TYPE table ct_usobx_ext TYPE table ct_usobt_ext TYPE table. ENDCLASS. CLASS zcl_abapgit_object_suso DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_longtext_id_suso TYPE dokil-id VALUE 'UO'. DATA: mv_objectname TYPE tobj-objct. METHODS: delete_documentation RAISING zcx_abapgit_exception, pre_check RAISING zcx_abapgit_exception, regenerate_sap_all. ENDCLASS. CLASS zcl_abapgit_object_sxci DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_classic_badi_implementation, implementation_data TYPE impl_data, function_codes TYPE seex_fcode_table, control_composites TYPE seex_coco_table, customer_includes TYPE seex_table_table, screens TYPE seex_screen_table, filters TYPE seex_filter_table, END OF ty_classic_badi_implementation. ENDCLASS. CLASS zcl_abapgit_object_tobj DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_tobj, tddat TYPE tddat, tvdir TYPE tvdir, tvimf TYPE STANDARD TABLE OF tvimf WITH DEFAULT KEY, END OF ty_tobj. METHODS: read_extra IMPORTING iv_tabname TYPE vim_name RETURNING VALUE(rs_tobj) TYPE ty_tobj, update_extra IMPORTING is_tobj TYPE ty_tobj, delete_extra IMPORTING iv_tabname TYPE vim_name. ENDCLASS. CLASS zcl_abapgit_object_tran DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_param_values TYPE STANDARD TABLE OF rsparam WITH NON-UNIQUE DEFAULT KEY , ty_tstca TYPE STANDARD TABLE OF tstca WITH DEFAULT KEY. CONSTANTS: c_oo_program TYPE c LENGTH 9 VALUE '\PROGRAM=' ##NO_TEXT, c_oo_class TYPE c LENGTH 7 VALUE '\CLASS=' ##NO_TEXT, c_oo_method TYPE c LENGTH 8 VALUE '\METHOD=' ##NO_TEXT, c_oo_tcode TYPE tcode VALUE 'OS_APPLICATION' ##NO_TEXT, c_oo_frclass TYPE c LENGTH 30 VALUE 'CLASS' ##NO_TEXT, c_oo_frmethod TYPE c LENGTH 30 VALUE 'METHOD' ##NO_TEXT, c_oo_frupdtask TYPE c LENGTH 30 VALUE 'UPDATE_MODE' ##NO_TEXT, c_oo_synchron TYPE c VALUE 'S' ##NO_TEXT, c_oo_asynchron TYPE c VALUE 'U' ##NO_TEXT, c_true TYPE c VALUE 'X' ##NO_TEXT, c_false TYPE c VALUE space ##NO_TEXT, BEGIN OF c_variant_type, dialog TYPE rglif-docutype VALUE 'D' ##NO_TEXT, report TYPE rglif-docutype VALUE 'R' ##NO_TEXT, variant TYPE rglif-docutype VALUE 'V' ##NO_TEXT, parameters TYPE rglif-docutype VALUE 'P' ##NO_TEXT, object TYPE rglif-docutype VALUE 'O' ##NO_TEXT, END OF c_variant_type. DATA: mt_bcdata TYPE STANDARD TABLE OF bdcdata . METHODS transaction_read IMPORTING iv_transaction TYPE tcode EXPORTING es_transaction TYPE tstc es_gui_attr TYPE tstcc RAISING zcx_abapgit_exception. METHODS shift_param CHANGING !ct_rsparam TYPE s_param !cs_tstcp TYPE tstcp . METHODS add_data IMPORTING !iv_fnam TYPE bdcdata-fnam !iv_fval TYPE clike . METHODS call_se93 RAISING zcx_abapgit_exception . METHODS set_oo_parameters IMPORTING !it_rsparam TYPE s_param CHANGING !cs_rsstcd TYPE rsstcd . METHODS split_parameters CHANGING !ct_rsparam TYPE s_param !cs_rsstcd TYPE rsstcd !cs_tstcp TYPE tstcp !cs_tstc TYPE tstc . METHODS split_parameters_comp IMPORTING !ig_type TYPE any !ig_param TYPE any CHANGING !cg_value TYPE any . METHODS serialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS deserialize_oo_transaction IMPORTING !iv_package TYPE devclass !is_tstc TYPE tstc !is_tstcc TYPE tstcc !is_tstct TYPE tstct !is_rsstcd TYPE rsstcd RAISING zcx_abapgit_exception . METHODS save_authorizations IMPORTING iv_transaction TYPE tstc-tcode it_authorizations TYPE ty_tstca RAISING zcx_abapgit_exception. METHODS clear_functiongroup_globals. METHODS is_variant_transaction IMPORTING is_tstcp TYPE tstcp RETURNING VALUE(rv_variant_transaction) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_object_ttyp DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_longtext_id_ttyp TYPE dokil-id VALUE 'TT'. ENDCLASS. CLASS zcl_abapgit_object_type DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_prefix TYPE c LENGTH 3 VALUE '%_C'. METHODS read EXPORTING ev_ddtext TYPE ddtypet-ddtext et_source TYPE abaptxt255_tab RAISING zcx_abapgit_exception. METHODS create IMPORTING iv_ddtext TYPE ddtypet-ddtext it_source TYPE abaptxt255_tab iv_devclass TYPE devclass RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_ucsa DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_version, active TYPE r3state VALUE 'A', inactive TYPE r3state VALUE 'I', END OF c_version . TYPES: ty_id TYPE c LENGTH 30. METHODS: get_persistence IMPORTING iv_id TYPE ty_id RETURNING VALUE(ro_persistence) TYPE REF TO object, clear_dynamic_fields CHANGING cg_complete_comm_assembly TYPE any, clear_field IMPORTING iv_fieldname TYPE csequence CHANGING cg_header TYPE any. ENDCLASS. CLASS zcl_abapgit_object_udmo DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. METHODS corr_insert REDEFINITION . PRIVATE SECTION. TYPES: " You are reminded that the text serialisation / de-serialisation methods depend upon a common type. " To make the dependency explicit, there is one common definition. BEGIN OF ty_udmo_text_type. TYPES sprache TYPE dm40t-sprache. TYPES dmoid TYPE dm40t-dmoid. TYPES langbez TYPE dm40t-langbez. TYPES as4local TYPE dm40t-as4local. TYPES END OF ty_udmo_text_type . DATA mv_data_model TYPE uddmodl . DATA mv_text_object TYPE doku_obj . DATA mv_lxe_text_name TYPE lxeobjname . DATA mv_activation_state TYPE as4local . DATA ms_object_type TYPE rsdeo . CONSTANTS c_transport_object_class TYPE trobjtype VALUE 'SUDM' ##NO_TEXT. CONSTANTS c_lxe_text_type TYPE lxeobjtype VALUE 'IM' ##NO_TEXT. CONSTANTS c_correction_object_type TYPE rsdeo-objtype VALUE 'UDMO' ##NO_TEXT. CONSTANTS c_active_state TYPE as4local VALUE 'A' ##NO_TEXT. METHODS is_name_permitted RAISING zcx_abapgit_exception . METHODS update_tree . METHODS serialize_short_texts IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_short_texts IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS serialize_long_texts IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_long_texts IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS serialize_entities IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_entities IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS access_modify RETURNING VALUE(rv_result) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS access_free RETURNING VALUE(rv_result) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS deserialize_model IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS serialize_model IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_ueno DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES BEGIN OF ty_docu. TYPES language TYPE dm40t-sprache. TYPES header TYPE thead. TYPES content TYPE xstring. TYPES itf TYPE tsftext. TYPES END OF ty_docu. TYPES ty_docu_lines TYPE STANDARD TABLE OF ty_docu WITH DEFAULT KEY. DATA mv_entity_id TYPE udentity. CONSTANTS c_text_object_type TYPE lxeobjtype VALUE 'IM' ##NO_TEXT. CONSTANTS c_active_state TYPE as4local VALUE 'A' ##NO_TEXT. METHODS build_text_name IMPORTING iv_id TYPE tdid RETURNING VALUE(rv_result) TYPE doku_obj. METHODS is_name_permitted RAISING zcx_abapgit_exception. METHODS delete_docu_uen RAISING zcx_abapgit_exception. METHODS delete_docu_url RAISING zcx_abapgit_exception. METHODS delete_docu_usp RAISING zcx_abapgit_exception. METHODS deserialize_docu_uen IMPORTING io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception. METHODS deserialize_docu_url IMPORTING io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception. METHODS deserialize_docu_usp IMPORTING io_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception. METHODS serialize_docu_uen IMPORTING io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception. METHODS serialize_docu_url IMPORTING io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception. METHODS serialize_docu_xxxx IMPORTING iv_id TYPE tdid RETURNING VALUE(rt_result) TYPE ty_docu_lines. METHODS serialize_docu_usp IMPORTING io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception. METHODS deserialize_docu_xxxx IMPORTING it_docu TYPE ty_docu_lines RAISING zcx_abapgit_exception. METHODS get_generic RETURNING VALUE(ro_generic) TYPE REF TO zcl_abapgit_objects_generic RAISING zcx_abapgit_exception . METHODS get_field_rules RETURNING VALUE(ro_result) TYPE REF TO zif_abapgit_field_rules. ENDCLASS. CLASS zcl_abapgit_object_vcls DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. * See include MTOBJCON: CONSTANTS c_cluster_type TYPE c VALUE 'C' ##NO_TEXT. CONSTANTS c_mode_insert TYPE obj_para-maint_mode VALUE 'I' ##NO_TEXT. METHODS is_locked IMPORTING !iv_tabname TYPE tabname !iv_argument TYPE seqg3-garg RETURNING VALUE(rv_is_locked) TYPE abap_bool RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_view DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_dd26v TYPE STANDARD TABLE OF dd26v WITH NON-UNIQUE DEFAULT KEY, ty_dd27p TYPE STANDARD TABLE OF dd27p WITH NON-UNIQUE DEFAULT KEY, ty_dd28j TYPE STANDARD TABLE OF dd28j WITH NON-UNIQUE DEFAULT KEY, ty_dd28v TYPE STANDARD TABLE OF dd28v WITH NON-UNIQUE DEFAULT KEY, BEGIN OF ty_dd25_text, ddlanguage TYPE dd25t-ddlanguage, ddtext TYPE dd25t-ddtext, END OF ty_dd25_text , ty_dd25_texts TYPE STANDARD TABLE OF ty_dd25_text. CONSTANTS c_longtext_id_view TYPE dokil-id VALUE 'VW'. METHODS: read_view IMPORTING iv_language TYPE sy-langu EXPORTING ev_state TYPE ddgotstate es_dd25v TYPE dd25v es_dd09l TYPE dd09l et_dd26v TYPE ty_dd26v et_dd27p TYPE ty_dd27p et_dd28j TYPE ty_dd28j et_dd28v TYPE ty_dd28v RAISING zcx_abapgit_exception, serialize_texts IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception, deserialize_texts IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input is_dd25v TYPE dd25v RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_w3xx_super DEFINITION INHERITING FROM zcl_abapgit_objects_super ABSTRACT CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . TYPES: ty_wwwparams_tt TYPE STANDARD TABLE OF wwwparams WITH DEFAULT KEY . CONSTANTS: BEGIN OF c_param_names, version TYPE w3_name VALUE 'version', fileext TYPE w3_name VALUE 'fileextension', filesize TYPE w3_name VALUE 'filesize', filename TYPE w3_name VALUE 'filename', mimetype TYPE w3_name VALUE 'mimetype', END OF c_param_names . METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. TYPES ty_bdcdata TYPE STANDARD TABLE OF bdcdata WITH NON-UNIQUE DEFAULT KEY. METHODS change_bdc_jump_data ABSTRACT CHANGING ct_bdcdata TYPE ty_bdcdata. PRIVATE SECTION. DATA ms_key TYPE wwwdatatab. METHODS get_ext IMPORTING it_params TYPE ty_wwwparams_tt RETURNING VALUE(rv_ext) TYPE string RAISING zcx_abapgit_exception. METHODS normalize_params IMPORTING iv_size TYPE i CHANGING ct_params TYPE ty_wwwparams_tt " Param table to patch RAISING zcx_abapgit_exception. METHODS strip_params CHANGING ct_params TYPE ty_wwwparams_tt RAISING zcx_abapgit_exception. METHODS find_param IMPORTING it_params TYPE ty_wwwparams_tt iv_name TYPE w3_name RETURNING VALUE(rv_value) TYPE string RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_w3ht DEFINITION INHERITING FROM zcl_abapgit_object_w3xx_super FINAL. PROTECTED SECTION. METHODS: change_bdc_jump_data REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_w3mi DEFINITION INHERITING FROM zcl_abapgit_object_w3xx_super FINAL. PROTECTED SECTION. METHODS: change_bdc_jump_data REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_wapa DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_page, attributes TYPE o2pagattr, event_handlers TYPE o2pagevh_tabletype, parameters TYPE o2pagpar_tabletype, types TYPE rswsourcet, END OF ty_page. TYPES: ty_pages_tt TYPE STANDARD TABLE OF ty_page WITH DEFAULT KEY. CONSTANTS: c_active TYPE so2_version VALUE 'A'. METHODS: get_page_content IMPORTING io_page TYPE REF TO cl_o2_api_pages RETURNING VALUE(rv_content) TYPE xstring RAISING zcx_abapgit_exception, to_page_content IMPORTING iv_content TYPE xstring RETURNING VALUE(rt_content) TYPE o2pageline_table RAISING zcx_abapgit_exception, read_page IMPORTING is_page TYPE o2pagattr iv_no_files_add TYPE abap_bool OPTIONAL RETURNING VALUE(rs_page) TYPE ty_page RAISING zcx_abapgit_exception, create_new_application IMPORTING is_attributes TYPE o2applattr it_nodes TYPE o2applnode_table it_navgraph TYPE o2applgrap_table RETURNING VALUE(ro_bsp) TYPE REF TO cl_o2_api_application RAISING zcx_abapgit_exception, create_new_page IMPORTING is_page_attributes TYPE o2pagattr RETURNING VALUE(ro_page) TYPE REF TO cl_o2_api_pages RAISING zcx_abapgit_exception, delete_superfluous_pages IMPORTING it_local_pages TYPE o2pagelist it_remote_pages TYPE ty_pages_tt RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_wdca DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. METHODS read EXPORTING !es_outline TYPE wdy_cfg_outline_data !et_data TYPE wdy_cfg_persist_data_appl_tab RAISING zcx_abapgit_exception . METHODS save IMPORTING !is_outline TYPE wdy_cfg_outline_data !it_data TYPE wdy_cfg_persist_data_appl_tab !iv_package TYPE devclass !iv_transport TYPE trkorr RAISING zcx_abapgit_exception . METHODS delete IMPORTING !iv_package TYPE devclass !iv_transport TYPE trkorr RAISING zcx_abapgit_exception . METHODS check IMPORTING !it_messages TYPE cts_messages RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_wdcc DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_object_wdya DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_longtext_id_wdya TYPE dokil-id VALUE 'WA'. METHODS read EXPORTING es_app TYPE wdy_application et_properties TYPE wdy_app_property_table RAISING zcx_abapgit_exception. METHODS save IMPORTING is_app TYPE wdy_application it_properties TYPE wdy_app_property_table iv_package TYPE devclass RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_wdyn DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_longtext_id_wc TYPE dokil-id VALUE 'WC' ##NO_TEXT. CONSTANTS c_longtext_id_wd TYPE dokil-id VALUE 'WD' ##NO_TEXT. CONSTANTS c_longtext_name_wc TYPE string VALUE 'LONGTEXTS_WC' ##NO_TEXT. DATA: mt_components TYPE TABLE OF wdy_ctlr_compo_vrs, mt_sources TYPE TABLE OF wdy_ctlr_compo_source_vrs. METHODS: get_limu_objects RETURNING VALUE(rt_objects) TYPE wdy_md_transport_keys, read RETURNING VALUE(rs_component) TYPE wdy_component_metadata RAISING zcx_abapgit_exception, read_controller IMPORTING is_key TYPE wdy_md_controller_key RETURNING VALUE(rs_controller) TYPE wdy_md_controller_meta_data RAISING zcx_abapgit_exception, read_definition IMPORTING is_key TYPE wdy_md_component_key RETURNING VALUE(rs_definition) TYPE wdy_md_component_meta_data RAISING zcx_abapgit_exception, read_view IMPORTING is_key TYPE wdy_md_view_key RETURNING VALUE(rs_view) TYPE wdy_md_view_meta_data RAISING zcx_abapgit_exception, recover_controller IMPORTING is_controller TYPE wdy_md_controller_meta_data RAISING zcx_abapgit_exception, recover_definition IMPORTING is_definition TYPE wdy_md_component_meta_data iv_package TYPE devclass RAISING zcx_abapgit_exception, recover_view IMPORTING is_view TYPE wdy_md_view_meta_data RAISING zcx_abapgit_exception, delta_controller IMPORTING is_controller TYPE wdy_md_controller_meta_data RETURNING VALUE(rs_delta) TYPE svrs2_xversionable_object RAISING zcx_abapgit_exception, delta_definition IMPORTING is_definition TYPE wdy_md_component_meta_data VALUE(iv_package) TYPE devclass RETURNING VALUE(rs_delta) TYPE svrs2_xversionable_object RAISING zcx_abapgit_exception, delta_view IMPORTING is_view TYPE wdy_md_view_meta_data RETURNING VALUE(rs_delta) TYPE svrs2_xversionable_object RAISING zcx_abapgit_exception, add_fm_param_exporting IMPORTING iv_name TYPE string ig_value TYPE any CHANGING ct_param TYPE abap_func_parmbind_tab, add_fm_param_tables IMPORTING iv_name TYPE string CHANGING ct_value TYPE ANY TABLE ct_param TYPE abap_func_parmbind_tab, add_fm_exception IMPORTING iv_name TYPE string iv_value TYPE i CHANGING ct_exception TYPE abap_func_excpbind_tab, add_with_inactive_parts RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_webi DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_webi, veptext TYPE veptext, pvepheader TYPE STANDARD TABLE OF vepheader WITH DEFAULT KEY, pvepfunction TYPE STANDARD TABLE OF vepfunction WITH DEFAULT KEY, pvepfault TYPE STANDARD TABLE OF vepfault WITH DEFAULT KEY, pvepparameter TYPE STANDARD TABLE OF vepparameter WITH DEFAULT KEY, pveptype TYPE STANDARD TABLE OF veptype WITH DEFAULT KEY, pvepelemtype TYPE STANDARD TABLE OF vepelemtype WITH DEFAULT KEY, pveptabletype TYPE STANDARD TABLE OF veptabletype WITH DEFAULT KEY, pvepstrutype TYPE STANDARD TABLE OF vepstrutype WITH DEFAULT KEY, pveptypesoapext TYPE STANDARD TABLE OF veptypesoapext WITH DEFAULT KEY, pvepeletypsoap TYPE STANDARD TABLE OF vepeletypsoap WITH DEFAULT KEY, pveptabtypsoap TYPE STANDARD TABLE OF veptabtypsoap WITH DEFAULT KEY, pvepfuncsoapext TYPE STANDARD TABLE OF vepfuncsoapext WITH DEFAULT KEY, pvepfieldref TYPE STANDARD TABLE OF vepfieldref WITH DEFAULT KEY, pvependpoint TYPE STANDARD TABLE OF vependpoint WITH DEFAULT KEY, pvepvisoapext TYPE STANDARD TABLE OF vepvisoapext WITH DEFAULT KEY, pvepparasoapext TYPE STANDARD TABLE OF vepparasoapext WITH DEFAULT KEY, pwsheader TYPE STANDARD TABLE OF wsheader WITH DEFAULT KEY, pwssoapprop TYPE STANDARD TABLE OF wssoapprop WITH DEFAULT KEY, END OF ty_webi. DATA: mi_vi TYPE REF TO if_ws_md_vif. METHODS: handle_endpoint IMPORTING is_webi TYPE ty_webi RAISING zcx_abapgit_exception cx_ws_md_exception, handle_types IMPORTING is_webi TYPE ty_webi RAISING zcx_abapgit_exception cx_ws_md_exception, handle_soap IMPORTING is_webi TYPE ty_webi RAISING zcx_abapgit_exception cx_ws_md_exception, handle_function IMPORTING is_webi TYPE ty_webi RAISING zcx_abapgit_exception cx_ws_md_exception. METHODS handle_single_parameter IMPORTING iv_parameter_type TYPE vepparamtype iv_name TYPE vepparameter-vepparam ii_function TYPE REF TO if_ws_md_vif_func RETURNING VALUE(ri_parameter) TYPE REF TO if_ws_md_vif_param RAISING zcx_abapgit_exception cx_ws_md_exception. METHODS sort CHANGING cs_webi TYPE ty_webi. ENDCLASS. CLASS zcl_abapgit_object_xinx DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_extension_index, dd12v TYPE dd12v, t_dd17v TYPE STANDARD TABLE OF dd17v WITH NON-UNIQUE DEFAULT KEY, END OF ty_extension_index. CONSTANTS: c_objtype_extension_index TYPE trobjtype VALUE 'XINX'. CONSTANTS c_longtext_id_xinx TYPE dokil-id VALUE 'XI'. DATA: mv_name TYPE ddobjname, mv_id TYPE ddobjectid. METHODS: xinx_delete_docu IMPORTING iv_objname TYPE ddobjname iv_id TYPE ddobjectid. ENDCLASS. CLASS zcl_abapgit_object_xslt DEFINITION INHERITING FROM zcl_abapgit_objects_super FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. METHODS: get RETURNING VALUE(ro_xslt) TYPE REF TO cl_o2_api_xsltdesc RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_objects_bridge DEFINITION FINAL CREATE PUBLIC INHERITING FROM zcl_abapgit_objects_super. PUBLIC SECTION. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING cx_sy_create_object_error zcx_abapgit_exception. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. DATA mo_plugin TYPE REF TO object. CLASS-METHODS initialize. " Metadata flags (late_deser, delete_tadir, and ddic) are not required by abapGit anymore " We keep them to stay compatible with old bridge implementation TYPES: BEGIN OF ty_metadata, class TYPE string, version TYPE string, late_deser TYPE abap_bool, delete_tadir TYPE abap_bool, ddic TYPE abap_bool, END OF ty_metadata . TYPES: BEGIN OF ty_s_objtype_map, obj_typ TYPE tadir-object, plugin_class TYPE seoclsname, END OF ty_s_objtype_map, ty_t_objtype_map TYPE SORTED TABLE OF ty_s_objtype_map WITH UNIQUE KEY obj_typ. CLASS-DATA gv_init TYPE abap_bool. CLASS-DATA gt_objtype_map TYPE ty_t_objtype_map. ENDCLASS. CLASS zcl_abapgit_objects_program DEFINITION INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_cua, adm TYPE rsmpe_adm, sta TYPE STANDARD TABLE OF rsmpe_stat WITH DEFAULT KEY, fun TYPE STANDARD TABLE OF rsmpe_funt WITH DEFAULT KEY, men TYPE STANDARD TABLE OF rsmpe_men WITH DEFAULT KEY, mtx TYPE STANDARD TABLE OF rsmpe_mnlt WITH DEFAULT KEY, act TYPE STANDARD TABLE OF rsmpe_act WITH DEFAULT KEY, but TYPE STANDARD TABLE OF rsmpe_but WITH DEFAULT KEY, pfk TYPE STANDARD TABLE OF rsmpe_pfk WITH DEFAULT KEY, set TYPE STANDARD TABLE OF rsmpe_staf WITH DEFAULT KEY, doc TYPE STANDARD TABLE OF rsmpe_atrt WITH DEFAULT KEY, tit TYPE STANDARD TABLE OF rsmpe_titt WITH DEFAULT KEY, biv TYPE STANDARD TABLE OF rsmpe_buts WITH DEFAULT KEY, END OF ty_cua. METHODS serialize_program IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output OPTIONAL !is_item TYPE zif_abapgit_definitions=>ty_item !io_files TYPE REF TO zcl_abapgit_objects_files !iv_program TYPE syrepid OPTIONAL !iv_extra TYPE clike OPTIONAL RAISING zcx_abapgit_exception. METHODS deserialize_program IMPORTING !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir !it_source TYPE abaptxt255_tab !it_tpool TYPE textpool_table !iv_package TYPE devclass RAISING zcx_abapgit_exception. PROTECTED SECTION. TYPES: ty_spaces_tt TYPE STANDARD TABLE OF i WITH DEFAULT KEY . TYPES: BEGIN OF ty_dynpro, header TYPE rpy_dyhead, containers TYPE dycatt_tab, fields TYPE dyfatc_tab, flow_logic TYPE swydyflow, spaces TYPE ty_spaces_tt, END OF ty_dynpro . TYPES: ty_dynpro_tt TYPE STANDARD TABLE OF ty_dynpro WITH DEFAULT KEY . METHODS strip_generation_comments CHANGING ct_source TYPE STANDARD TABLE. " tab of string or charX METHODS serialize_dynpros IMPORTING !iv_program_name TYPE syrepid RETURNING VALUE(rt_dynpro) TYPE ty_dynpro_tt RAISING zcx_abapgit_exception . METHODS serialize_cua IMPORTING !iv_program_name TYPE syrepid RETURNING VALUE(rs_cua) TYPE ty_cua RAISING zcx_abapgit_exception . METHODS deserialize_dynpros IMPORTING !it_dynpros TYPE ty_dynpro_tt RAISING zcx_abapgit_exception . METHODS deserialize_textpool IMPORTING !iv_program TYPE syrepid !it_tpool TYPE textpool_table !iv_language TYPE sy-langu OPTIONAL !iv_is_include TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . METHODS deserialize_cua IMPORTING !iv_program_name TYPE syrepid !is_cua TYPE ty_cua RAISING zcx_abapgit_exception . METHODS is_any_dynpro_locked IMPORTING !iv_program TYPE syrepid RETURNING VALUE(rv_is_any_dynpro_locked) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS is_cua_locked IMPORTING !iv_program TYPE syrepid RETURNING VALUE(rv_is_cua_locked) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS is_text_locked IMPORTING !iv_program TYPE syrepid RETURNING VALUE(rv_is_text_locked) TYPE abap_bool RAISING zcx_abapgit_exception . CLASS-METHODS add_tpool IMPORTING !it_tpool TYPE textpool_table RETURNING VALUE(rt_tpool) TYPE zif_abapgit_definitions=>ty_tpool_tt . CLASS-METHODS read_tpool IMPORTING !it_tpool TYPE zif_abapgit_definitions=>ty_tpool_tt RETURNING VALUE(rt_tpool) TYPE zif_abapgit_definitions=>ty_tpool_tt . PRIVATE SECTION. CONSTANTS: BEGIN OF c_state, active TYPE r3state VALUE 'A', inactive TYPE r3state VALUE 'I', END OF c_state. METHODS: uncondense_flow IMPORTING it_flow TYPE swydyflow it_spaces TYPE ty_spaces_tt RETURNING VALUE(rt_flow) TYPE swydyflow. CLASS-METHODS auto_correct_cua_adm IMPORTING is_cua TYPE ty_cua CHANGING cs_adm TYPE rsmpe_adm. METHODS get_program_title IMPORTING !it_tpool TYPE textpool_table RETURNING VALUE(rv_title) TYPE repti . METHODS insert_program IMPORTING !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir !it_source TYPE abaptxt255_tab !iv_title TYPE repti !iv_package TYPE devclass RAISING zcx_abapgit_exception . METHODS update_program IMPORTING !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir !it_source TYPE abaptxt255_tab !iv_title TYPE repti RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_clas DEFINITION INHERITING FROM zcl_abapgit_objects_program CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_object . METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. DATA: mi_object_oriented_object_fct TYPE REF TO zif_abapgit_oo_object_fnc, mv_skip_testclass TYPE abap_bool, mv_classpool_name TYPE progname. METHODS: deserialize_abap IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input iv_package TYPE devclass RAISING zcx_abapgit_exception, deserialize_docu IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception, deserialize_tpool IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception, deserialize_tpool_i18n IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception, deserialize_sotr IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input iv_package TYPE devclass RAISING zcx_abapgit_exception, deserialize_exceptions IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception, serialize_xml IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception, serialize_attr IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output !iv_clsname TYPE seoclsname RAISING zcx_abapgit_exception, serialize_descr IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output !iv_clsname TYPE seoclsname RAISING zcx_abapgit_exception, serialize_descr_sub IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output !iv_clsname TYPE seoclsname RAISING zcx_abapgit_exception, serialize_docu IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output !it_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus OPTIONAL !iv_clsname TYPE seoclsname RAISING zcx_abapgit_exception, serialize_tpool IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output !iv_clsname TYPE seoclsname RETURNING VALUE(rt_tpool) TYPE textpool_table RAISING zcx_abapgit_exception, serialize_tpool_i18n IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output !it_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus OPTIONAL !iv_clsname TYPE seoclsname !it_tpool_main TYPE textpool_table RAISING zcx_abapgit_exception, serialize_sotr IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception, source_apack_replacement CHANGING !ct_source TYPE seop_source_string RAISING zcx_abapgit_exception, repo_apack_replacement CHANGING !ct_source TYPE seop_source_string RAISING zcx_abapgit_exception. PRIVATE SECTION. CONSTANTS: BEGIN OF c_longtext_name, attributes TYPE string VALUE 'LONGTEXTS_CA', methods TYPE string VALUE 'LONGTEXTS_CO', events TYPE string VALUE 'LONGTEXTS_CE', types TYPE string VALUE 'LONGTEXTS_CT', END OF c_longtext_name. CONSTANTS: BEGIN OF c_longtext_id, class TYPE dokil-id VALUE 'CL', attributes TYPE dokil-id VALUE 'CA', methods TYPE dokil-id VALUE 'CO', events TYPE dokil-id VALUE 'CE', types TYPE dokil-id VALUE 'CT', END OF c_longtext_id. METHODS deserialize_pre_ddic IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input !iv_package TYPE devclass RAISING zcx_abapgit_exception. METHODS is_class_locked RETURNING VALUE(rv_is_class_locked) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS interface_replacement IMPORTING !iv_from_interface TYPE seoclsname !iv_to_interface TYPE seoclsname CHANGING !ct_source TYPE seop_source_string. ENDCLASS. CLASS zcl_abapgit_object_fugr DEFINITION INHERITING FROM zcl_abapgit_objects_program FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: c_longtext_id_prog TYPE dokil-id VALUE 'RE', c_longtext_id_func TYPE dokil-id VALUE 'FU', c_longtext_id_func_exc TYPE dokil-id VALUE 'FX'. TYPES: ty_rs38l_incl_tt TYPE STANDARD TABLE OF rs38l_incl WITH DEFAULT KEY . TYPES: BEGIN OF ty_function, funcname TYPE rs38l_fnam, global_flag TYPE rs38l-global, remote_call TYPE rs38l-remote, update_task TYPE rs38l-utask, short_text TYPE tftit-stext, remote_basxml TYPE rs38l-basxml_enabled, import TYPE STANDARD TABLE OF rsimp WITH DEFAULT KEY, changing TYPE STANDARD TABLE OF rscha WITH DEFAULT KEY, export TYPE STANDARD TABLE OF rsexp WITH DEFAULT KEY, tables TYPE STANDARD TABLE OF rstbl WITH DEFAULT KEY, exception TYPE STANDARD TABLE OF rsexc WITH DEFAULT KEY, documentation TYPE STANDARD TABLE OF rsfdo WITH DEFAULT KEY, exception_classes TYPE abap_bool, END OF ty_function . TYPES: ty_function_tt TYPE STANDARD TABLE OF ty_function WITH DEFAULT KEY . TYPES: ty_sobj_name_tt TYPE STANDARD TABLE OF sobj_name WITH DEFAULT KEY . TYPES: BEGIN OF ty_tpool_i18n, language TYPE langu, textpool TYPE zif_abapgit_definitions=>ty_tpool_tt, END OF ty_tpool_i18n . TYPES: ty_tpools_i18n TYPE STANDARD TABLE OF ty_tpool_i18n . DATA mt_includes_cache TYPE ty_sobj_name_tt . DATA mt_includes_all TYPE ty_sobj_name_tt . METHODS check_rfc_parameters IMPORTING !is_function TYPE ty_function RAISING zcx_abapgit_exception . METHODS update_where_used IMPORTING !it_includes TYPE ty_sobj_name_tt . METHODS main_name RETURNING VALUE(rv_program) TYPE program RAISING zcx_abapgit_exception . METHODS functions RETURNING VALUE(rt_functab) TYPE ty_rs38l_incl_tt RAISING zcx_abapgit_exception . METHODS includes RETURNING VALUE(rt_includes) TYPE ty_sobj_name_tt RAISING zcx_abapgit_exception . METHODS serialize_functions RETURNING VALUE(rt_functions) TYPE ty_function_tt RAISING zcx_abapgit_exception . METHODS deserialize_functions IMPORTING !it_functions TYPE ty_function_tt !ii_log TYPE REF TO zif_abapgit_log !iv_version TYPE uccheck !iv_package TYPE devclass !iv_transport TYPE trkorr RAISING zcx_abapgit_exception . METHODS serialize_function_docs IMPORTING !iv_prog_name TYPE syrepid !it_functions TYPE ty_function_tt !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_function_docs IMPORTING !iv_prog_name TYPE syrepid !it_functions TYPE ty_function_tt !ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS serialize_xml IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_xml IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input !iv_version TYPE uccheck !iv_package TYPE devclass !iv_transport TYPE trkorr RAISING zcx_abapgit_exception . METHODS serialize_includes RAISING zcx_abapgit_exception . METHODS deserialize_includes IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input !iv_package TYPE devclass !ii_log TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . METHODS is_function_group_locked RETURNING VALUE(rv_is_functions_group_locked) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS is_any_include_locked RETURNING VALUE(rv_is_any_include_locked) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS is_any_function_module_locked RETURNING VALUE(rv_any_function_module_locked) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS get_abap_version IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input RETURNING VALUE(rv_abap_version) TYPE progdir-uccheck RAISING zcx_abapgit_exception . METHODS update_func_group_short_text IMPORTING !iv_group TYPE rs38l-area !iv_short_text TYPE tftit-stext . METHODS serialize_texts IMPORTING !iv_prog_name TYPE syrepid !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_texts IMPORTING !iv_prog_name TYPE syrepid !ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS is_part_of_other_fugr IMPORTING !iv_include TYPE sobj_name RETURNING VALUE(rv_belongs_to_other_fugr) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_object_intf DEFINITION FINAL INHERITING FROM zcl_abapgit_objects_program. PUBLIC SECTION. INTERFACES zif_abapgit_object. TYPES: BEGIN OF ty_docu, lines TYPE tlinetab, i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_lines, END OF ty_docu. TYPES: BEGIN OF ty_intf, vseointerf TYPE vseointerf, docu TYPE ty_docu, description TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, description_sub TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt, END OF ty_intf. METHODS constructor IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !iv_language TYPE spras !io_files TYPE REF TO zcl_abapgit_objects_files OPTIONAL !io_i18n_params TYPE REF TO zcl_abapgit_i18n_params OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. METHODS deserialize_proxy IMPORTING iv_transport TYPE trkorr RAISING zcx_abapgit_exception . METHODS deserialize_docu IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input !is_docu TYPE ty_docu RAISING zcx_abapgit_exception . METHODS serialize_docu IMPORTING !it_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus OPTIONAL !iv_clsname TYPE seoclsname RETURNING VALUE(rs_docu) TYPE ty_docu RAISING zcx_abapgit_exception. METHODS serialize_descr IMPORTING !iv_clsname TYPE seoclsname RETURNING VALUE(rs_description) TYPE ty_intf-description RAISING zcx_abapgit_exception. METHODS serialize_descr_sub IMPORTING !iv_clsname TYPE seoclsname RETURNING VALUE(rs_description) TYPE ty_intf-description_sub RAISING zcx_abapgit_exception. METHODS serialize_xml IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . PRIVATE SECTION. CONSTANTS: BEGIN OF c_longtext_name, attributes TYPE string VALUE 'LONGTEXTS_IA', methods TYPE string VALUE 'LONGTEXTS_IO', events TYPE string VALUE 'LONGTEXTS_IE', END OF c_longtext_name. CONSTANTS: BEGIN OF c_longtext_id, interface TYPE dokil-id VALUE 'IF', attributes TYPE dokil-id VALUE 'IA', methods TYPE dokil-id VALUE 'IO', events TYPE dokil-id VALUE 'IE', END OF c_longtext_id. DATA mv_aff_enabled TYPE abap_bool. DATA mi_object_oriented_object_fct TYPE REF TO zif_abapgit_oo_object_fnc . METHODS deserialize_pre_ddic IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input iv_package TYPE devclass RAISING zcx_abapgit_exception. METHODS deserialize_descriptions IMPORTING it_description TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt OPTIONAL. METHODS deserialize_descr_sub IMPORTING it_description TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt OPTIONAL. METHODS read_xml IMPORTING ii_xml TYPE REF TO zif_abapgit_xml_input RETURNING VALUE(rs_intf) TYPE ty_intf RAISING zcx_abapgit_exception. METHODS read_json RETURNING VALUE(rs_intf) TYPE ty_intf RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_object_prog DEFINITION INHERITING FROM zcl_abapgit_objects_program FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_tpool_i18n, language TYPE langu, textpool TYPE zif_abapgit_definitions=>ty_tpool_tt, END OF ty_tpool_i18n . TYPES: ty_tpools_i18n TYPE STANDARD TABLE OF ty_tpool_i18n . CONSTANTS c_longtext_id_prog TYPE dokil-id VALUE 'RE' ##NO_TEXT. METHODS deserialize_with_ext IMPORTING !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir !it_source TYPE abaptxt255_tab !iv_package TYPE devclass RAISING zcx_abapgit_exception . METHODS serialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_output RAISING zcx_abapgit_exception . METHODS deserialize_texts IMPORTING !ii_xml TYPE REF TO zif_abapgit_xml_input RAISING zcx_abapgit_exception . METHODS is_program_locked RETURNING VALUE(rv_is_program_locked) TYPE abap_bool RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_migrations DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS run RAISING zcx_abapgit_exception zcx_abapgit_not_found. PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS migrate_offline_repos. ENDCLASS. CLASS zcl_abapgit_persist_background DEFINITION CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_xml, method TYPE string, username TYPE string, password TYPE string, settings TYPE zif_abapgit_background=>ty_settings_tt, END OF ty_xml . TYPES: BEGIN OF ty_background, key TYPE zif_abapgit_persistence=>ty_value. INCLUDE TYPE ty_xml. TYPES: END OF ty_background . TYPES: ty_background_keys TYPE STANDARD TABLE OF ty_background WITH DEFAULT KEY . METHODS constructor . METHODS list RETURNING VALUE(rt_list) TYPE ty_background_keys RAISING zcx_abapgit_exception . METHODS get_by_key IMPORTING !iv_key TYPE ty_background-key RETURNING VALUE(rs_data) TYPE ty_background RAISING zcx_abapgit_exception zcx_abapgit_not_found . METHODS modify IMPORTING !is_data TYPE ty_background RAISING zcx_abapgit_exception . METHODS delete IMPORTING !iv_key TYPE ty_background-key RAISING zcx_abapgit_exception . METHODS exists IMPORTING !iv_key TYPE ty_background-key RETURNING VALUE(rv_yes) TYPE abap_bool RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. DATA mo_db TYPE REF TO zcl_abapgit_persistence_db . METHODS from_xml IMPORTING !iv_string TYPE string RETURNING VALUE(rs_xml) TYPE ty_xml RAISING zcx_abapgit_exception . METHODS to_xml IMPORTING !is_background TYPE ty_background RETURNING VALUE(rv_string) TYPE string . ENDCLASS. CLASS zcl_abapgit_persist_factory DEFINITION CREATE PRIVATE . PUBLIC SECTION. CLASS-METHODS get_repo RETURNING VALUE(ri_repo) TYPE REF TO zif_abapgit_persist_repo . CLASS-METHODS get_repo_cs RETURNING VALUE(ri_repo_cs) TYPE REF TO zif_abapgit_persist_repo_cs . CLASS-METHODS get_settings RETURNING VALUE(ri_settings) TYPE REF TO zif_abapgit_persist_settings . PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gi_repo TYPE REF TO zif_abapgit_persist_repo . CLASS-DATA gi_repo_cs TYPE REF TO zif_abapgit_persist_repo_cs . CLASS-DATA gi_settings TYPE REF TO zif_abapgit_persist_settings . ENDCLASS. CLASS zcl_abapgit_persist_migrate DEFINITION CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS: run RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_text TYPE string VALUE 'Generated by abapGit' ##NO_TEXT. CLASS-METHODS table_create RAISING zcx_abapgit_exception. CLASS-METHODS table_exists RETURNING VALUE(rv_exists) TYPE abap_bool. CLASS-METHODS lock_create RAISING zcx_abapgit_exception. CLASS-METHODS lock_exists RETURNING VALUE(rv_exists) TYPE abap_bool. CLASS-METHODS gui_status_create RAISING zcx_abapgit_exception. CLASS-METHODS gui_status_exists RETURNING VALUE(rv_exists) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_persist_packages DEFINITION CREATE PRIVATE . PUBLIC SECTION. TYPES: BEGIN OF ty_package, devclass TYPE scompkdtln-devclass, component TYPE scompkdtln-component, comp_posid TYPE scompkdtln-comp_posid, END OF ty_package . TYPES: ty_packages TYPE HASHED TABLE OF ty_package WITH UNIQUE KEY devclass . METHODS init . METHODS modify IMPORTING !iv_package TYPE scompkdtln-devclass !iv_component TYPE scompkdtln-component OPTIONAL !iv_comp_posid TYPE scompkdtln-comp_posid OPTIONAL RAISING zcx_abapgit_exception . METHODS read IMPORTING !iv_package TYPE scompkdtln-devclass RETURNING VALUE(rs_package) TYPE ty_package . CLASS-METHODS get_instance RETURNING VALUE(ro_persist) TYPE REF TO zcl_abapgit_persist_packages . PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA go_persist TYPE REF TO zcl_abapgit_persist_packages. DATA mt_packages TYPE ty_packages. METHODS from_xml IMPORTING iv_xml TYPE string RETURNING VALUE(rt_packages) TYPE ty_packages RAISING zcx_abapgit_exception. METHODS to_xml IMPORTING it_packages TYPE ty_packages RETURNING VALUE(rv_xml) TYPE string RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_persist_settings DEFINITION CREATE PRIVATE FRIENDS ZCL_ABAPGIT_persist_factory . PUBLIC SECTION. INTERFACES zif_abapgit_persist_settings . PROTECTED SECTION. PRIVATE SECTION. DATA mo_settings TYPE REF TO zcl_abapgit_settings . ENDCLASS. CLASS zcl_abapgit_persistence_db DEFINITION CREATE PRIVATE . PUBLIC SECTION. CONSTANTS c_tabname TYPE c LENGTH 30 VALUE 'ZABAPGIT' ##NO_TEXT. CONSTANTS c_lock TYPE c LENGTH 30 VALUE 'EZABAPGIT' ##NO_TEXT. CONSTANTS: c_type_settings TYPE zif_abapgit_persistence=>ty_type VALUE 'SETTINGS' ##NO_TEXT, c_type_repo TYPE zif_abapgit_persistence=>ty_type VALUE 'REPO' ##NO_TEXT, c_type_repo_csum TYPE zif_abapgit_persistence=>ty_type VALUE 'REPO_CS' ##NO_TEXT, c_type_background TYPE zif_abapgit_persistence=>ty_type VALUE 'BACKGROUND' ##NO_TEXT, c_type_packages TYPE zif_abapgit_persistence=>ty_type VALUE 'PACKAGES' ##NO_TEXT, c_type_user TYPE zif_abapgit_persistence=>ty_type VALUE 'USER' ##NO_TEXT. CLASS-METHODS get_instance RETURNING VALUE(ro_db) TYPE REF TO zcl_abapgit_persistence_db . METHODS add IMPORTING !iv_type TYPE zif_abapgit_persistence=>ty_type !iv_value TYPE zif_abapgit_persistence=>ty_content-value !iv_data TYPE zif_abapgit_persistence=>ty_content-data_str RAISING zcx_abapgit_exception . METHODS delete IMPORTING !iv_type TYPE zif_abapgit_persistence=>ty_type !iv_value TYPE zif_abapgit_persistence=>ty_content-value RAISING zcx_abapgit_exception . METHODS list RETURNING VALUE(rt_content) TYPE zif_abapgit_persistence=>ty_contents . METHODS list_by_type IMPORTING !iv_type TYPE zif_abapgit_persistence=>ty_type RETURNING VALUE(rt_content) TYPE zif_abapgit_persistence=>ty_contents . METHODS list_by_keys IMPORTING it_keys TYPE zif_abapgit_persistence=>ty_repo_keys iv_type TYPE zif_abapgit_persistence=>ty_type RETURNING VALUE(rt_contents) TYPE zif_abapgit_persistence=>ty_contents. METHODS lock IMPORTING !iv_mode TYPE enqmode DEFAULT 'E' !iv_type TYPE zif_abapgit_persistence=>ty_type !iv_value TYPE zif_abapgit_persistence=>ty_content-value RAISING zcx_abapgit_exception . METHODS modify IMPORTING !iv_type TYPE zif_abapgit_persistence=>ty_type !iv_value TYPE zif_abapgit_persistence=>ty_content-value !iv_data TYPE zif_abapgit_persistence=>ty_content-data_str RAISING zcx_abapgit_exception . METHODS read IMPORTING !iv_type TYPE zif_abapgit_persistence=>ty_type !iv_value TYPE zif_abapgit_persistence=>ty_content-value RETURNING VALUE(rv_data) TYPE zif_abapgit_persistence=>ty_content-data_str RAISING zcx_abapgit_not_found . METHODS update IMPORTING !iv_type TYPE zif_abapgit_persistence=>ty_type !iv_value TYPE zif_abapgit_persistence=>ty_content-value !iv_data TYPE zif_abapgit_persistence=>ty_content-data_str RAISING zcx_abapgit_exception . CLASS-METHODS validate_entry_type IMPORTING !iv_type TYPE zif_abapgit_persistence=>ty_type RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA go_db TYPE REF TO zcl_abapgit_persistence_db . DATA mv_update_function TYPE funcname . METHODS get_update_function RETURNING VALUE(rv_funcname) TYPE funcname . METHODS validate_and_unprettify_xml IMPORTING !iv_xml TYPE string RETURNING VALUE(rv_xml) TYPE string RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_persistence_repo DEFINITION CREATE PROTECTED FRIENDS ZCL_ABAPGIT_persist_factory . PUBLIC SECTION. INTERFACES zif_abapgit_persist_repo . INTERFACES zif_abapgit_persist_repo_cs . METHODS constructor . METHODS rewrite_repo_meta IMPORTING !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception zcx_abapgit_not_found. PROTECTED SECTION. PRIVATE SECTION. DATA mt_meta_fields TYPE STANDARD TABLE OF abap_compname. DATA mo_db TYPE REF TO zcl_abapgit_persistence_db . METHODS from_xml IMPORTING !iv_repo_xml_string TYPE string RETURNING VALUE(rs_repo) TYPE zif_abapgit_persistence=>ty_repo_xml RAISING zcx_abapgit_exception . METHODS to_xml IMPORTING !is_repo TYPE zif_abapgit_persistence=>ty_repo RETURNING VALUE(rv_repo_xml_string) TYPE string . METHODS get_next_id RETURNING VALUE(rv_next_repo_id) TYPE zif_abapgit_persistence=>ty_content-value RAISING zcx_abapgit_exception . METHODS get_repo_from_content IMPORTING is_content TYPE zif_abapgit_persistence=>ty_content RETURNING VALUE(rs_result) TYPE zif_abapgit_persistence=>ty_repo RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_persistence_user DEFINITION CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_persist_user . CLASS-METHODS get_instance IMPORTING !iv_user TYPE sy-uname DEFAULT sy-uname RETURNING VALUE(ri_user) TYPE REF TO zif_abapgit_persist_user RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !iv_user TYPE sy-uname DEFAULT sy-uname RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_repo_config, url TYPE zif_abapgit_persistence=>ty_repo-url, login TYPE string, git_user TYPE zif_abapgit_git_definitions=>ty_git_user, last_change_seen TYPE string, END OF ty_repo_config . TYPES: ty_repo_configs TYPE STANDARD TABLE OF ty_repo_config WITH DEFAULT KEY . TYPES: BEGIN OF ty_user, default_git_user TYPE zif_abapgit_git_definitions=>ty_git_user, repo_show TYPE zif_abapgit_persistence=>ty_repo-key, hide_files TYPE abap_bool, changes_only TYPE abap_bool, order_by TYPE string, order_descending TYPE abap_bool, diff_first TYPE abap_bool, diff_unified TYPE abap_bool, favorites TYPE zif_abapgit_persist_user=>ty_favorites, repo_config TYPE ty_repo_configs, settings TYPE zif_abapgit_definitions=>ty_s_user_settings, show_folders TYPE abap_bool, list_settings TYPE zif_abapgit_definitions=>ty_list_settings, END OF ty_user . DATA mv_user TYPE sy-uname . DATA ms_user TYPE ty_user. CLASS-DATA gi_current_user TYPE REF TO zif_abapgit_persist_user . METHODS from_xml IMPORTING !iv_xml TYPE string RETURNING VALUE(rs_user) TYPE ty_user RAISING zcx_abapgit_exception . METHODS read RAISING zcx_abapgit_exception . METHODS read_repo_config IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url RETURNING VALUE(rs_repo_config) TYPE ty_repo_config RAISING zcx_abapgit_exception . METHODS to_xml IMPORTING !is_user TYPE ty_user RETURNING VALUE(rv_xml) TYPE string . METHODS update RAISING zcx_abapgit_exception . METHODS update_repo_config IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url !is_repo_config TYPE ty_repo_config RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_object_filter_tran DEFINITION CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_object_filter. METHODS set_filter_values IMPORTING iv_package TYPE tadir-devclass it_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt RAISING zcx_abapgit_exception . METHODS get_filter_values EXPORTING ev_package TYPE tadir-devclass et_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt. PROTECTED SECTION. TYPES: BEGIN OF ty_e071_filter, pgmid TYPE tadir-pgmid, object TYPE tadir-object, obj_name TYPE trobj_name, END OF ty_e071_filter, ty_e071_filter_tt TYPE STANDARD TABLE OF ty_e071_filter. METHODS adjust_local_filter IMPORTING it_e071_filter TYPE ty_e071_filter_tt iv_package TYPE tadir-devclass RETURNING VALUE(rt_filter) TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception. PRIVATE SECTION. DATA mt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt . DATA mt_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt . DATA mv_package TYPE tadir-devclass. METHODS generate_local_filter IMPORTING iv_package TYPE tadir-devclass it_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt RETURNING VALUE(rt_filter) TYPE zif_abapgit_definitions=>ty_tadir_tt RAISING zcx_abapgit_exception . METHODS init . METHODS get_all_sub_packages IMPORTING iv_package TYPE tadir-devclass RETURNING VALUE(rt_filter) TYPE zif_abapgit_definitions=>ty_tadir_tt. ENDCLASS. CLASS zcl_abapgit_repo_filter DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS apply IMPORTING it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt CHANGING ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt . METHODS apply_object_filter IMPORTING it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt io_dot TYPE REF TO zcl_abapgit_dot_abapgit OPTIONAL iv_devclass TYPE devclass OPTIONAL CHANGING ct_files TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception. PROTECTED SECTION. METHODS filter_generated_tadir CHANGING !ct_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_merge DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_merge. METHODS constructor IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online !iv_source_branch TYPE string RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_ancestor_tt TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_ancestor WITH DEFAULT KEY . TYPES: ty_visit_tt TYPE STANDARD TABLE OF zif_abapgit_git_definitions=>ty_sha1 WITH DEFAULT KEY . DATA mo_repo TYPE REF TO zcl_abapgit_repo_online . DATA ms_merge TYPE zif_abapgit_merge=>ty_merge . DATA mt_conflicts TYPE zif_abapgit_merge=>ty_merge_conflict_tt . DATA mt_objects TYPE zif_abapgit_definitions=>ty_objects_tt . DATA mv_source_branch TYPE string . METHODS visit IMPORTING !iv_parent TYPE zif_abapgit_git_definitions=>ty_sha1 CHANGING !ct_visit TYPE ty_visit_tt . METHODS all_files RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_expanded_tt . METHODS calculate_result RAISING zcx_abapgit_exception . METHODS fetch_git RETURNING VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception . METHODS find_ancestors IMPORTING !iv_commit TYPE zif_abapgit_git_definitions=>ty_sha1 RETURNING VALUE(rt_ancestors) TYPE ty_ancestor_tt RAISING zcx_abapgit_exception . METHODS find_first_common IMPORTING !it_list1 TYPE ty_ancestor_tt !it_list2 TYPE ty_ancestor_tt RETURNING VALUE(rs_common) TYPE zif_abapgit_definitions=>ty_ancestor RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_stage DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS method_description IMPORTING !iv_method TYPE zif_abapgit_definitions=>ty_method RETURNING VALUE(rv_description) TYPE string RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !iv_merge_source TYPE zif_abapgit_git_definitions=>ty_sha1 OPTIONAL . METHODS add IMPORTING !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename !iv_data TYPE xstring !is_status TYPE zif_abapgit_definitions=>ty_result OPTIONAL RAISING zcx_abapgit_exception . METHODS reset IMPORTING !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename RAISING zcx_abapgit_exception . METHODS rm IMPORTING !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename !is_status TYPE zif_abapgit_definitions=>ty_result OPTIONAL RAISING zcx_abapgit_exception . METHODS ignore IMPORTING !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename RAISING zcx_abapgit_exception . METHODS get_merge_source RETURNING VALUE(rv_source) TYPE zif_abapgit_git_definitions=>ty_sha1 . METHODS count RETURNING VALUE(rv_count) TYPE i . METHODS get_all RETURNING VALUE(rt_stage) TYPE zif_abapgit_definitions=>ty_stage_tt . PROTECTED SECTION. PRIVATE SECTION. DATA mt_stage TYPE zif_abapgit_definitions=>ty_stage_tt . DATA mv_merge_source TYPE zif_abapgit_git_definitions=>ty_sha1 . METHODS append IMPORTING !iv_path TYPE zif_abapgit_git_definitions=>ty_file-path !iv_filename TYPE zif_abapgit_git_definitions=>ty_file-filename !iv_method TYPE zif_abapgit_definitions=>ty_method !is_status TYPE zif_abapgit_definitions=>ty_result OPTIONAL !iv_data TYPE xstring OPTIONAL RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_stage_logic DEFINITION CREATE PRIVATE FRIENDS ZCL_ABAPGIT_factory . PUBLIC SECTION. INTERFACES zif_abapgit_stage_logic . PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS: remove_ignored IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online CHANGING cs_files TYPE zif_abapgit_definitions=>ty_stage_files, remove_identical CHANGING cs_files TYPE zif_abapgit_definitions=>ty_stage_files. ENDCLASS. CLASS zcl_abapgit_repo_item_state DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS local RETURNING VALUE(rv_state) TYPE zif_abapgit_git_definitions=>ty_item_state. METHODS remote RETURNING VALUE(rv_state) TYPE zif_abapgit_git_definitions=>ty_item_state. METHODS is_reassigned RETURNING VALUE(rv_is_reassigned) TYPE abap_bool. METHODS is_unchanged RETURNING VALUE(rv_is_unchanged) TYPE abap_bool. METHODS sum_with_repo_item IMPORTING !is_repo_item TYPE zif_abapgit_definitions=>ty_repo_item. METHODS sum_with_status_item IMPORTING !is_status_item TYPE zif_abapgit_definitions=>ty_result. PROTECTED SECTION. PRIVATE SECTION. DATA mv_lstate TYPE zif_abapgit_git_definitions=>ty_item_state. DATA mv_rstate TYPE zif_abapgit_git_definitions=>ty_item_state. DATA mv_is_reassigned TYPE abap_bool. CLASS-METHODS reduce IMPORTING iv_prev TYPE zif_abapgit_git_definitions=>ty_item_state iv_cur TYPE zif_abapgit_git_definitions=>ty_item_state RETURNING VALUE(rv_new) TYPE zif_abapgit_git_definitions=>ty_item_state. ENDCLASS. CLASS zcl_abapgit_repo_labels DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_label_color, label TYPE string, color TYPE string, END OF ty_label_color, ty_label_colors TYPE STANDARD TABLE OF ty_label_color WITH KEY label. TYPES: BEGIN OF ty_color, cls TYPE string, fg TYPE string, bg TYPE string, border TYPE string, END OF ty_color. CONSTANTS c_allowed_chars TYPE string VALUE `-_. a-zA-Z0-9` ##NO_TEXT. " it is easier to allow chars, though potentially other chars can be added later if needed CLASS-METHODS class_constructor. CLASS-METHODS validate IMPORTING !iv_labels TYPE string RAISING zcx_abapgit_exception. CLASS-METHODS split IMPORTING !iv_labels TYPE string RETURNING VALUE(rt_labels) TYPE string_table. CLASS-METHODS normalize IMPORTING !iv_labels TYPE string RETURNING VALUE(rv_labels) TYPE string. CLASS-METHODS validate_colors IMPORTING !iv_config TYPE string RAISING zcx_abapgit_exception. CLASS-METHODS split_colors IMPORTING !iv_config TYPE string RETURNING VALUE(rt_label_colors) TYPE ty_label_colors. CLASS-METHODS split_colors_into_map IMPORTING !iv_config TYPE string RETURNING VALUE(ro_map) TYPE REF TO zcl_abapgit_string_map. CLASS-METHODS normalize_colors IMPORTING !iv_config TYPE string RETURNING VALUE(rv_config) TYPE string. CLASS-METHODS parse_color IMPORTING iv_color TYPE string RETURNING VALUE(rs_parsed) TYPE ty_color. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gv_regex TYPE string. CLASS-METHODS validate_one_label_color IMPORTING !is_lc TYPE ty_label_color !iv_index TYPE i DEFAULT 0 RAISING zcx_abapgit_exception. CLASS-METHODS validate_rgb_color IMPORTING !iv_color TYPE string !iv_index TYPE i DEFAULT 0 RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_repo_news DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. TYPES: BEGIN OF ty_log, version TYPE string, pos_to_cur TYPE i, is_header TYPE abap_bool, is_important TYPE abap_bool, text TYPE string, END OF ty_log. TYPES: ty_logs TYPE STANDARD TABLE OF ty_log WITH DEFAULT KEY. CONSTANTS c_tail_length TYPE i VALUE 5 ##NO_TEXT. " Number of versions to display if no updates CLASS-METHODS create " TODO REFACTOR IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_repo_news RAISING zcx_abapgit_exception. METHODS get_log RETURNING VALUE(rt_log) TYPE ty_logs. METHODS has_news RETURNING VALUE(rv_boolean) TYPE abap_bool. METHODS has_important RETURNING VALUE(rv_boolean) TYPE abap_bool. METHODS has_updates RETURNING VALUE(rv_boolean) TYPE abap_bool. METHODS has_unseen RETURNING VALUE(rv_boolean) TYPE abap_bool. METHODS constructor IMPORTING !iv_rawdata TYPE xstring !iv_lastseen_version TYPE string !iv_current_version TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mt_log TYPE ty_logs . DATA mv_current_version TYPE string . DATA mv_lastseen_version TYPE string . DATA mv_latest_version TYPE string . METHODS latest_version RETURNING VALUE(rv_version) TYPE string . CLASS-METHODS parse_line IMPORTING !iv_line TYPE string !iv_current_version TYPE string RETURNING VALUE(rs_log) TYPE ty_log . CLASS-METHODS parse IMPORTING !it_lines TYPE string_table !iv_current_version TYPE string RETURNING VALUE(rt_log) TYPE ty_logs . ENDCLASS. CLASS zcl_abapgit_repo_requirements DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. TYPES ty_cvers TYPE STANDARD TABLE OF cvers WITH DEFAULT KEY. CLASS-METHODS requirements_popup IMPORTING !it_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt RAISING zcx_abapgit_exception. CLASS-METHODS is_requirements_met IMPORTING !it_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt RETURNING VALUE(rv_status) TYPE zif_abapgit_definitions=>ty_yes_no RAISING zcx_abapgit_exception. CLASS-METHODS inject_cvers IMPORTING !it_cvers TYPE ty_cvers. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_requirement_status, met TYPE abap_bool, component TYPE tdevc-dlvunit, description TYPE string, installed_release TYPE saprelease, installed_patch TYPE sappatchlv, required_release TYPE saprelease, required_patch TYPE sappatchlv, END OF ty_requirement_status . TYPES: ty_requirement_status_tt TYPE STANDARD TABLE OF ty_requirement_status WITH DEFAULT KEY . CLASS-DATA gt_cvers TYPE ty_cvers. CLASS-METHODS get_cvers RETURNING VALUE(rt_cvers) TYPE ty_cvers RAISING zcx_abapgit_exception. CLASS-METHODS show_requirement_popup IMPORTING !it_requirements TYPE ty_requirement_status_tt RAISING zcx_abapgit_exception . CLASS-METHODS get_requirement_met_status IMPORTING !it_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt RETURNING VALUE(rt_status) TYPE ty_requirement_status_tt RAISING zcx_abapgit_exception . CLASS-METHODS is_version_greater_or_equal IMPORTING !is_status TYPE ty_requirement_status RETURNING VALUE(rv_true) TYPE abap_bool . ENDCLASS. CLASS zcl_abapgit_version DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS normalize IMPORTING !iv_version TYPE string RETURNING VALUE(rv_version) TYPE string . CLASS-METHODS conv_str_to_version IMPORTING !iv_version TYPE csequence RETURNING VALUE(rs_version) TYPE zif_abapgit_definitions=>ty_version RAISING zcx_abapgit_exception . CLASS-METHODS check_dependant_version IMPORTING !is_current TYPE zif_abapgit_definitions=>ty_version !is_dependant TYPE zif_abapgit_definitions=>ty_version RAISING zcx_abapgit_exception . CLASS-METHODS compare IMPORTING !iv_a TYPE string OPTIONAL !iv_b TYPE string OPTIONAL !is_a TYPE zif_abapgit_definitions=>ty_version OPTIONAL !is_b TYPE zif_abapgit_definitions=>ty_version OPTIONAL RETURNING VALUE(rv_result) TYPE i . CLASS-METHODS get_version_constant_value IMPORTING iv_version_constant TYPE string RETURNING VALUE(rv_version) TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS version_to_numeric IMPORTING !iv_version TYPE string RETURNING VALUE(rv_version) TYPE i. ENDCLASS. CLASS zcl_abapgit_zip DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS encode_files IMPORTING !it_files TYPE zif_abapgit_definitions=>ty_files_item_tt RETURNING VALUE(rv_xstr) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS export IMPORTING !is_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings !iv_package TYPE devclass !io_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit !iv_show_log TYPE abap_bool DEFAULT abap_true !it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt OPTIONAL RETURNING VALUE(rv_xstr) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS export_object IMPORTING !iv_object_type TYPE trobjtype !iv_object_name TYPE sobj_name !iv_main_language_only TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . CLASS-METHODS export_package IMPORTING !iv_package TYPE devclass !iv_folder_logic TYPE string !iv_main_lang_only TYPE abap_bool !iv_ign_subpkg TYPE abap_bool OPTIONAL RAISING zcx_abapgit_exception . CLASS-METHODS load IMPORTING !iv_xstr TYPE xstring RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . CLASS-METHODS save_binstring_to_localfile IMPORTING !iv_filename TYPE string !iv_binstring TYPE xstring RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS filename IMPORTING !iv_str TYPE string EXPORTING !ev_path TYPE string !ev_filename TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS normalize_path CHANGING !ct_files TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . CLASS-METHODS unzip_file IMPORTING !iv_xstr TYPE xstring RETURNING VALUE(rt_files) TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_dot_abapgit DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS build_default RETURNING VALUE(ro_dot_abapgit) TYPE REF TO zcl_abapgit_dot_abapgit . CLASS-METHODS deserialize IMPORTING !iv_xstr TYPE xstring RETURNING VALUE(ro_dot_abapgit) TYPE REF TO zcl_abapgit_dot_abapgit RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !is_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit . METHODS serialize RETURNING VALUE(rv_xstr) TYPE xstring RAISING zcx_abapgit_exception . METHODS to_file RETURNING VALUE(rs_file) TYPE zif_abapgit_git_definitions=>ty_file RAISING zcx_abapgit_exception . METHODS get_data RETURNING VALUE(rs_data) TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit . METHODS add_ignore IMPORTING !iv_path TYPE string !iv_filename TYPE string . METHODS is_ignored IMPORTING !iv_path TYPE string !iv_filename TYPE string RETURNING VALUE(rv_ignored) TYPE abap_bool . METHODS remove_ignore IMPORTING !iv_path TYPE string !iv_filename TYPE string . METHODS get_starting_folder RETURNING VALUE(rv_path) TYPE string . METHODS get_folder_logic RETURNING VALUE(rv_logic) TYPE string . METHODS set_folder_logic IMPORTING !iv_logic TYPE string . METHODS set_starting_folder IMPORTING !iv_path TYPE string . METHODS get_main_language RETURNING VALUE(rv_language) TYPE spras . METHODS get_i18n_languages RETURNING VALUE(rt_languages) TYPE zif_abapgit_definitions=>ty_languages RAISING zcx_abapgit_exception . METHODS set_i18n_languages IMPORTING it_languages TYPE zif_abapgit_definitions=>ty_languages RAISING zcx_abapgit_exception . METHODS determine_i18n_parameters IMPORTING !iv_main_language_only TYPE abap_bool RETURNING VALUE(rs_i18n_params) TYPE zif_abapgit_definitions=>ty_i18n_params RAISING zcx_abapgit_exception. METHODS get_signature RETURNING VALUE(rs_signature) TYPE zif_abapgit_git_definitions=>ty_file_signature RAISING zcx_abapgit_exception . METHODS use_lxe IMPORTING !iv_yes TYPE abap_bool DEFAULT abap_undefined RETURNING VALUE(rv_yes) TYPE abap_bool . METHODS get_requirements RETURNING VALUE(rt_requirements) TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt . METHODS set_requirements IMPORTING !it_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt . METHODS get_name RETURNING VALUE(rv_name) TYPE string. METHODS set_name IMPORTING !iv_name TYPE csequence. METHODS get_version_constant RETURNING VALUE(rv_version_constant) TYPE string . METHODS set_version_constant IMPORTING !iv_version_constant TYPE csequence . METHODS get_abap_language_version RETURNING VALUE(rv_abap_language_version) TYPE string . METHODS set_abap_language_version IMPORTING !iv_abap_language_version TYPE string . METHODS get_original_system RETURNING VALUE(rv_original_system) TYPE string . METHODS set_original_system IMPORTING !iv_original_system TYPE csequence . PROTECTED SECTION. PRIVATE SECTION. DATA ms_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit . CLASS-METHODS to_xml IMPORTING !is_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit RETURNING VALUE(rv_xml) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS from_xml IMPORTING !iv_xml TYPE string RETURNING VALUE(rs_data) TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit . ENDCLASS. CLASS zcl_abapgit_repo DEFINITION ABSTRACT CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_repo . ALIASES ms_data FOR zif_abapgit_repo~ms_data . ALIASES deserialize FOR zif_abapgit_repo~deserialize . ALIASES deserialize_checks FOR zif_abapgit_repo~deserialize_checks . ALIASES get_dot_abapgit FOR zif_abapgit_repo~get_dot_abapgit . ALIASES get_tadir_objects FOR zif_abapgit_repo~get_tadir_objects . ALIASES get_files_local FOR zif_abapgit_repo~get_files_local . ALIASES get_files_local_filtered FOR zif_abapgit_repo~get_files_local_filtered . ALIASES get_files_remote FOR zif_abapgit_repo~get_files_remote . ALIASES get_key FOR zif_abapgit_repo~get_key . ALIASES get_local_settings FOR zif_abapgit_repo~get_local_settings . ALIASES get_name FOR zif_abapgit_repo~get_name . ALIASES get_package FOR zif_abapgit_repo~get_package . ALIASES is_offline FOR zif_abapgit_repo~is_offline . ALIASES refresh FOR zif_abapgit_repo~refresh . ALIASES set_dot_abapgit FOR zif_abapgit_repo~set_dot_abapgit . ALIASES find_remote_dot_abapgit FOR zif_abapgit_repo~find_remote_dot_abapgit . ALIASES has_remote_source FOR zif_abapgit_repo~has_remote_source . METHODS bind_listener IMPORTING !ii_listener TYPE REF TO zif_abapgit_repo_listener . METHODS constructor IMPORTING !is_data TYPE zif_abapgit_persistence=>ty_repo . METHODS create_new_log IMPORTING !iv_title TYPE string OPTIONAL RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log . METHODS delete_checks RETURNING VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_delete_checks RAISING zcx_abapgit_exception . METHODS get_data_config RETURNING VALUE(ri_config) TYPE REF TO zif_abapgit_data_config RAISING zcx_abapgit_exception . METHODS get_dot_apack RETURNING VALUE(ro_dot_apack) TYPE REF TO zcl_abapgit_apack_reader RAISING zcx_abapgit_exception. METHODS get_log RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log . METHODS get_unsupported_objects_local RETURNING VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_items_tt RAISING zcx_abapgit_exception . METHODS refresh_local_object IMPORTING !iv_obj_type TYPE tadir-object !iv_obj_name TYPE tadir-obj_name RAISING zcx_abapgit_exception . METHODS refresh_local_objects RAISING zcx_abapgit_exception . METHODS remove_ignored_files CHANGING !ct_files TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . METHODS set_files_remote IMPORTING !it_files TYPE zif_abapgit_git_definitions=>ty_files_tt . METHODS set_local_settings IMPORTING !is_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings RAISING zcx_abapgit_exception . METHODS switch_repo_type IMPORTING !iv_offline TYPE abap_bool RAISING zcx_abapgit_exception . PROTECTED SECTION. DATA mt_local TYPE zif_abapgit_definitions=>ty_files_item_tt . DATA mt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt . DATA mv_request_local_refresh TYPE abap_bool . DATA mv_request_remote_refresh TYPE abap_bool . DATA mi_log TYPE REF TO zif_abapgit_log . DATA mi_listener TYPE REF TO zif_abapgit_repo_listener . DATA mo_apack_reader TYPE REF TO zcl_abapgit_apack_reader . DATA mi_data_config TYPE REF TO zif_abapgit_data_config . METHODS find_remote_dot_apack RETURNING VALUE(ro_dot) TYPE REF TO zcl_abapgit_apack_reader RAISING zcx_abapgit_exception . METHODS reset_remote . METHODS set IMPORTING !iv_url TYPE zif_abapgit_persistence=>ty_repo-url OPTIONAL !iv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name OPTIONAL !iv_selected_commit TYPE zif_abapgit_persistence=>ty_repo-selected_commit OPTIONAL !iv_head_branch TYPE zif_abapgit_persistence=>ty_repo-head_branch OPTIONAL !iv_offline TYPE zif_abapgit_persistence=>ty_repo-offline OPTIONAL !is_dot_abapgit TYPE zif_abapgit_persistence=>ty_repo-dot_abapgit OPTIONAL !is_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings OPTIONAL !iv_deserialized_at TYPE zif_abapgit_persistence=>ty_repo-deserialized_at OPTIONAL !iv_deserialized_by TYPE zif_abapgit_persistence=>ty_repo-deserialized_by OPTIONAL !iv_switched_origin TYPE zif_abapgit_persistence=>ty_repo-switched_origin OPTIONAL RAISING zcx_abapgit_exception . METHODS set_dot_apack IMPORTING !io_dot_apack TYPE REF TO zcl_abapgit_apack_reader RAISING zcx_abapgit_exception . PRIVATE SECTION. METHODS check_language RAISING zcx_abapgit_exception . METHODS check_write_protect RAISING zcx_abapgit_exception . METHODS deserialize_data IMPORTING !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks CHANGING !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt RAISING zcx_abapgit_exception . METHODS deserialize_dot_abapgit CHANGING !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt RAISING zcx_abapgit_exception . METHODS deserialize_objects IMPORTING !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks !ii_log TYPE REF TO zif_abapgit_log CHANGING !ct_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt RAISING zcx_abapgit_exception . METHODS normalize_local_settings CHANGING !cs_local_settings TYPE zif_abapgit_persistence=>ty_local_settings . METHODS notify_listener IMPORTING !is_change_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask RAISING zcx_abapgit_exception . METHODS update_last_deserialize RAISING zcx_abapgit_exception . METHODS check_abap_language_version RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_repo_checksums DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_repo_checksums. METHODS constructor IMPORTING !iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception. METHODS force_write IMPORTING it_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_local_files_by_item_tt TYPE SORTED TABLE OF zif_abapgit_definitions=>ty_file_item WITH NON-UNIQUE KEY item. DATA mv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key. DATA mi_repo TYPE REF TO zif_abapgit_repo. METHODS remove_non_code_related_files CHANGING !ct_local_files TYPE ty_local_files_by_item_tt. METHODS build_checksums_from_files IMPORTING it_local TYPE ty_local_files_by_item_tt RETURNING VALUE(rt_checksums) TYPE zif_abapgit_persistence=>ty_local_checksum_tt. METHODS save_checksums IMPORTING it_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt RAISING zcx_abapgit_exception. METHODS add_meta CHANGING cv_cs_blob TYPE string RAISING zcx_abapgit_exception. METHODS extract_meta CHANGING * co_string_map - return string map with meta when it is needed cv_cs_blob TYPE string. ENDCLASS. CLASS zcl_abapgit_repo_content_list DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING io_repo TYPE REF TO zcl_abapgit_repo. METHODS list IMPORTING iv_path TYPE string iv_by_folders TYPE abap_bool OPTIONAL iv_changes_only TYPE abap_bool OPTIONAL iv_transports TYPE abap_bool OPTIONAL RETURNING VALUE(rt_repo_items) TYPE zif_abapgit_definitions=>ty_repo_item_tt RAISING zcx_abapgit_exception. METHODS get_log RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_sortkey, default TYPE i VALUE 9999, parent_dir TYPE i VALUE 0, dir TYPE i VALUE 1, orphan TYPE i VALUE 2, changed TYPE i VALUE 3, inactive TYPE i VALUE 4, END OF c_sortkey. DATA: mo_repo TYPE REF TO zcl_abapgit_repo, mi_log TYPE REF TO zif_abapgit_log. METHODS build_repo_items RETURNING VALUE(rt_repo_items) TYPE zif_abapgit_definitions=>ty_repo_item_tt RAISING zcx_abapgit_exception. METHODS build_folders IMPORTING iv_cur_dir TYPE string CHANGING ct_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt RAISING zcx_abapgit_exception. METHODS determine_transports CHANGING ct_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt. METHODS filter_changes CHANGING ct_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt. METHODS check_repo_size RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_repo_cs_migration DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS run RAISING zcx_abapgit_exception zcx_abapgit_not_found. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_repo_ids TYPE SORTED TABLE OF zif_abapgit_persistence=>ty_repo-key WITH UNIQUE KEY table_line. CLASS-METHODS get_unconverted_repo_ids RETURNING VALUE(rt_repo_ids) TYPE ty_repo_ids. CLASS-METHODS clear_repo_metadata IMPORTING iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception zcx_abapgit_not_found. CLASS-METHODS convert_checksums IMPORTING iv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception zcx_abapgit_not_found. ENDCLASS. CLASS zcl_abapgit_repo_offline DEFINITION INHERITING FROM zcl_abapgit_repo FINAL CREATE PUBLIC . PUBLIC SECTION. PROTECTED SECTION. METHODS reset_remote REDEFINITION . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_repo_online DEFINITION INHERITING FROM zcl_abapgit_repo FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_repo_online . ALIASES create_branch FOR zif_abapgit_repo_online~create_branch . ALIASES get_current_remote FOR zif_abapgit_repo_online~get_current_remote . ALIASES get_selected_branch FOR zif_abapgit_repo_online~get_selected_branch . ALIASES get_selected_commit FOR zif_abapgit_repo_online~get_selected_commit . ALIASES get_url FOR zif_abapgit_repo_online~get_url . ALIASES push FOR zif_abapgit_repo_online~push . ALIASES select_branch FOR zif_abapgit_repo_online~select_branch . ALIASES select_commit FOR zif_abapgit_repo_online~select_commit . ALIASES set_url FOR zif_abapgit_repo_online~set_url . ALIASES switch_origin FOR zif_abapgit_repo_online~switch_origin . ALIASES get_switched_origin FOR zif_abapgit_repo_online~get_switched_origin. METHODS zif_abapgit_repo~get_files_remote REDEFINITION . METHODS zif_abapgit_repo~get_name REDEFINITION . PROTECTED SECTION. PRIVATE SECTION. DATA mt_objects TYPE zif_abapgit_definitions=>ty_objects_tt . DATA mv_current_commit TYPE zif_abapgit_git_definitions=>ty_sha1 . METHODS handle_stage_ignore IMPORTING !io_stage TYPE REF TO zcl_abapgit_stage RAISING zcx_abapgit_exception . METHODS set_objects IMPORTING !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception . METHODS fetch_remote RAISING zcx_abapgit_exception . METHODS get_objects RETURNING VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt RAISING zcx_abapgit_exception . METHODS raise_error_if_branch_exists IMPORTING iv_name TYPE string RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_repo_srv DEFINITION FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_repo_srv . INTERFACES zif_abapgit_repo_listener . CLASS-METHODS get_instance RETURNING VALUE(ri_srv) TYPE REF TO zif_abapgit_repo_srv . CLASS-METHODS inject_instance IMPORTING ii_srv TYPE REF TO zif_abapgit_repo_srv. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gi_ref TYPE REF TO zif_abapgit_repo_srv . DATA mv_init TYPE abap_bool. DATA mv_only_favorites TYPE abap_bool. DATA mt_list TYPE zif_abapgit_repo_srv=>ty_repo_list . METHODS determine_branch_name IMPORTING !iv_name TYPE string !iv_url TYPE string RETURNING VALUE(rv_name) TYPE string RAISING zcx_abapgit_exception . METHODS refresh_all RAISING zcx_abapgit_exception . METHODS refresh_favorites RAISING zcx_abapgit_exception . METHODS instantiate_and_add IMPORTING !is_repo_meta TYPE zif_abapgit_persistence=>ty_repo RETURNING VALUE(ri_repo) TYPE REF TO zif_abapgit_repo RAISING zcx_abapgit_exception . METHODS add IMPORTING !ii_repo TYPE REF TO zif_abapgit_repo RAISING zcx_abapgit_exception . METHODS reinstantiate_repo IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !is_meta TYPE zif_abapgit_persistence=>ty_repo_xml RAISING zcx_abapgit_exception . METHODS validate_sub_super_packages IMPORTING !iv_package TYPE devclass !it_repos TYPE zif_abapgit_persistence=>ty_repos !iv_ign_subpkg TYPE abap_bool DEFAULT abap_false EXPORTING VALUE(ei_repo) TYPE REF TO zif_abapgit_repo !ev_reason TYPE string RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_repo_status DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS calculate IMPORTING !ii_repo TYPE REF TO zif_abapgit_repo !ii_log TYPE REF TO zif_abapgit_log OPTIONAL !ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL RETURNING VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !iv_root_package TYPE devclass !io_dot TYPE REF TO zcl_abapgit_dot_abapgit. PROTECTED SECTION. PRIVATE SECTION. DATA mv_root_package TYPE devclass. DATA mo_dot TYPE REF TO zcl_abapgit_dot_abapgit. METHODS calculate_status IMPORTING !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt !it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt !it_cur_state TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt RETURNING VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception. METHODS process_local IMPORTING !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt !it_state_idx TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts CHANGING !ct_remote TYPE zif_abapgit_git_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. METHODS process_items IMPORTING !it_unprocessed_remote TYPE zif_abapgit_git_definitions=>ty_files_tt CHANGING !ct_items TYPE zif_abapgit_definitions=>ty_items_tt RAISING zcx_abapgit_exception. METHODS process_remote IMPORTING !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt !it_unprocessed_remote TYPE zif_abapgit_git_definitions=>ty_files_tt !it_state_idx TYPE zif_abapgit_git_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 build_existing IMPORTING !is_local TYPE zif_abapgit_definitions=>ty_file_item !is_remote TYPE zif_abapgit_git_definitions=>ty_file !it_state TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts RETURNING VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_result. CLASS-METHODS build_new_local IMPORTING !is_local TYPE zif_abapgit_definitions=>ty_file_item RETURNING VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_result. METHODS build_new_remote IMPORTING !is_remote TYPE zif_abapgit_git_definitions=>ty_file !it_items_idx TYPE zif_abapgit_definitions=>ty_items_ts !it_state_idx TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts RETURNING VALUE(rs_result) TYPE zif_abapgit_definitions=>ty_result RAISING zcx_abapgit_exception. CLASS-METHODS get_object_package IMPORTING !iv_object TYPE tadir-object !iv_obj_name TYPE tadir-obj_name RETURNING VALUE(rv_devclass) TYPE devclass RAISING zcx_abapgit_exception. CLASS-METHODS check_local_remote_consistency IMPORTING !is_local TYPE zif_abapgit_definitions=>ty_file_item !is_remote TYPE zif_abapgit_git_definitions=>ty_file RAISING zcx_abapgit_exception. CLASS-METHODS ensure_state IMPORTING !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt !it_cur_state TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt RETURNING VALUE(rt_state) TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt. ENDCLASS. CLASS zcl_abapgit_syntax_factory DEFINITION ABSTRACT CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS create IMPORTING !iv_filename TYPE string !iv_hidden_chars TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_syntax_highlighter . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_syntax_highlighter DEFINITION ABSTRACT CREATE PUBLIC . PUBLIC SECTION. METHODS process_line IMPORTING !iv_line TYPE string RETURNING VALUE(rv_line) TYPE string . METHODS set_hidden_chars IMPORTING !iv_hidden_chars TYPE abap_bool . PROTECTED SECTION. TYPES: BEGIN OF ty_match, token TYPE c LENGTH 1, " Type of matches offset TYPE i, " Beginning position of the string that should be formatted length TYPE i, " Length of the string that should be formatted text_tag TYPE string, " Type of text tag END OF ty_match . TYPES: ty_match_tt TYPE STANDARD TABLE OF ty_match WITH DEFAULT KEY . TYPES: BEGIN OF ty_rule, regex TYPE REF TO cl_abap_regex, token TYPE c LENGTH 1, style TYPE string, relevant_submatch TYPE i, END OF ty_rule . CONSTANTS c_token_none TYPE c VALUE '.' ##NO_TEXT. DATA: mt_rules TYPE STANDARD TABLE OF ty_rule . DATA mv_hidden_chars TYPE abap_bool . METHODS add_rule IMPORTING !iv_regex TYPE string !iv_token TYPE c !iv_style TYPE string !iv_submatch TYPE i OPTIONAL . METHODS parse_line IMPORTING !iv_line TYPE string RETURNING VALUE(rt_matches) TYPE ty_match_tt . METHODS order_matches IMPORTING !iv_line TYPE string CHANGING !ct_matches TYPE ty_match_tt . METHODS extend_matches IMPORTING !iv_line TYPE string CHANGING !ct_matches TYPE ty_match_tt . METHODS format_line IMPORTING !iv_line TYPE string !it_matches TYPE ty_match_tt RETURNING VALUE(rv_line) TYPE string . METHODS apply_style IMPORTING !iv_line TYPE string !iv_class TYPE string RETURNING VALUE(rv_line) TYPE string . METHODS is_whitespace IMPORTING !iv_string TYPE string RETURNING VALUE(rv_result) TYPE abap_bool . METHODS show_hidden_chars IMPORTING !iv_line TYPE string RETURNING VALUE(rv_line) TYPE string . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_syntax_abap DEFINITION INHERITING FROM zcl_abapgit_syntax_highlighter CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS class_constructor. METHODS constructor. CONSTANTS: BEGIN OF c_css, keyword TYPE string VALUE 'keyword', text TYPE string VALUE 'text', comment TYPE string VALUE 'comment', END OF c_css, BEGIN OF c_token, keyword TYPE c VALUE 'K', text TYPE c VALUE 'T', comment TYPE c VALUE 'C', END OF c_token, BEGIN OF c_regex, comment TYPE string VALUE '##|"|^\*', text TYPE string VALUE '`|''|\||\{|\}', keyword TYPE string VALUE '&&|\b[-_a-z0-9]+\b', END OF c_regex. PROTECTED SECTION. CLASS-DATA gt_keywords TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line. CLASS-METHODS init_keywords. CLASS-METHODS is_keyword IMPORTING iv_chunk TYPE string RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS order_matches REDEFINITION. METHODS parse_line REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_syntax_css DEFINITION INHERITING FROM zcl_abapgit_syntax_highlighter CREATE PUBLIC . PUBLIC SECTION. " CSS Standard https://www.w3.org/TR/css-2018/ " CSS Reference https://www.w3schools.com/cssref/default.asp " We used a mixture of above as reference for the keyword list " 1) CSS Properties https://www.w3schools.com/cssref/default.asp " 2) CSS Values & Units https://www.w3schools.com/cssref/css_units.asp " 3) CSS Selectors https://www.w3.org/TR/css-2018/#selectors " 4) CSS Functions https://www.w3schools.com/cssref/css_functions.asp " 5) CSS Colors https://www.w3schools.com/colors/colors_names.asp " 6) CSS Extensions " 7) CSS At-Rules https://www.w3.org/TR/css-2018/#at-rules " 8) HTML Tags CONSTANTS: BEGIN OF c_css, keyword TYPE string VALUE 'keyword', text TYPE string VALUE 'text', comment TYPE string VALUE 'comment', selectors TYPE string VALUE 'selectors', units TYPE string VALUE 'units', properties TYPE string VALUE 'properties', values TYPE string VALUE 'values', functions TYPE string VALUE 'functions', colors TYPE string VALUE 'colors', extensions TYPE string VALUE 'extensions', at_rules TYPE string VALUE 'at_rules', html TYPE string VALUE 'html', END OF c_css . CONSTANTS: BEGIN OF c_token, keyword TYPE c VALUE 'K', text TYPE c VALUE 'T', comment TYPE c VALUE 'C', selectors TYPE c VALUE 'S', units TYPE c VALUE 'U', properties TYPE c VALUE 'P', values TYPE c VALUE 'V', functions TYPE c VALUE 'F', colors TYPE c VALUE 'Z', extensions TYPE c VALUE 'E', at_rules TYPE c VALUE 'A', html TYPE c VALUE 'H', END OF c_token . CONSTANTS: BEGIN OF c_regex, " comments /* ... */ comment TYPE string VALUE '\/\*.*\*\/|\/\*|\*\/', " single or double quoted strings text TYPE string VALUE '("[^"]*")|(''[^'']*'')|(`[^`]*`)', " in general keywords don't contain numbers (except -ms-scrollbar-3dlight-color) keyword TYPE string VALUE '\b[a-z3@\-]+\b', " selectors begin with : selectors TYPE string VALUE ':[:a-z]+\b', " units units TYPE string VALUE '\b[0-9\. ]+(ch|cm|em|ex|in|mm|pc|pt|px|vh|vmax|vmin|vw)\b|\b[0-9\. ]+%', END OF c_regex . CLASS-METHODS class_constructor . METHODS constructor . PROTECTED SECTION. TYPES: ty_token TYPE c LENGTH 1. TYPES: BEGIN OF ty_keyword, keyword TYPE string, token TYPE ty_token, END OF ty_keyword. CLASS-DATA gt_keywords TYPE HASHED TABLE OF ty_keyword WITH UNIQUE KEY keyword. CLASS-DATA gv_comment TYPE abap_bool. CLASS-METHODS init_keywords. CLASS-METHODS insert_keywords IMPORTING iv_keywords TYPE string iv_token TYPE ty_token. CLASS-METHODS is_keyword IMPORTING iv_chunk TYPE string RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS order_matches REDEFINITION. METHODS parse_line REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_syntax_js DEFINITION INHERITING FROM zcl_abapgit_syntax_highlighter CREATE PUBLIC . PUBLIC SECTION. CONSTANTS: " JavaScript " 1) General keywords " 2) Variable types " 3) HTML Tags BEGIN OF c_css, keyword TYPE string VALUE 'keyword', text TYPE string VALUE 'text', comment TYPE string VALUE 'comment', variables TYPE string VALUE 'variables', END OF c_css . CONSTANTS: BEGIN OF c_token, keyword TYPE c VALUE 'K', text TYPE c VALUE 'T', comment TYPE c VALUE 'C', variables TYPE c VALUE 'V', END OF c_token . CONSTANTS: BEGIN OF c_regex, " comments /* ... */ or // comment TYPE string VALUE '\/\*.*\*\/|\/\*|\*\/|\/\/', " single or double quoted strings text TYPE string VALUE '"|''|`', " in general keywords don't contain numbers (except -ms-scrollbar-3dlight-color) keyword TYPE string VALUE '\b[a-z-]+\b', END OF c_regex . CLASS-METHODS class_constructor . METHODS constructor . PROTECTED SECTION. TYPES: ty_token TYPE c LENGTH 1. TYPES: BEGIN OF ty_keyword, keyword TYPE string, token TYPE ty_token, END OF ty_keyword. CLASS-DATA gt_keywords TYPE HASHED TABLE OF ty_keyword WITH UNIQUE KEY keyword. CLASS-DATA gv_comment TYPE abap_bool. CLASS-METHODS init_keywords. CLASS-METHODS insert_keywords IMPORTING iv_keywords TYPE string iv_token TYPE ty_token. CLASS-METHODS is_keyword IMPORTING iv_chunk TYPE string RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS order_matches REDEFINITION. METHODS parse_line REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_syntax_json DEFINITION INHERITING FROM zcl_abapgit_syntax_highlighter CREATE PUBLIC. PUBLIC SECTION. CONSTANTS: " JSON... This was easy :-) " JSONC... With comments BEGIN OF c_css, keyword TYPE string VALUE 'selectors', "#EC NOTEXT text TYPE string VALUE 'text', "#EC NOTEXT values TYPE string VALUE 'properties', "#EC NOTEXT comment TYPE string VALUE 'comment', "#EC NOTEXT END OF c_css. CONSTANTS: BEGIN OF c_token, keyword TYPE c VALUE 'K', "#EC NOTEXT text TYPE c VALUE 'T', "#EC NOTEXT values TYPE c VALUE 'V', "#EC NOTEXT comment TYPE c VALUE 'C', "#EC NOTEXT END OF c_token. CONSTANTS: BEGIN OF c_regex, " comments /* ... */ or // comment TYPE string VALUE '\/\*.*\*\/|\/\*|\*\/|\/\/', "#EC NOTEXT " not much here keyword TYPE string VALUE 'true|false|null', "#EC NOTEXT " double quoted strings text TYPE string VALUE '"', "#EC NOTEXT END OF c_regex. METHODS constructor. PROTECTED SECTION. METHODS order_matches REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_syntax_txt DEFINITION INHERITING FROM zcl_abapgit_syntax_highlighter CREATE PUBLIC . PUBLIC SECTION. METHODS constructor . METHODS process_line REDEFINITION . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_syntax_xml DEFINITION INHERITING FROM zcl_abapgit_syntax_highlighter CREATE PUBLIC . PUBLIC SECTION. CONSTANTS: BEGIN OF c_css, xml_tag TYPE string VALUE 'xml_tag', attr TYPE string VALUE 'attr', attr_val TYPE string VALUE 'attr_val', comment TYPE string VALUE 'comment', END OF c_css . CONSTANTS: BEGIN OF c_token, xml_tag TYPE c VALUE 'X', attr TYPE c VALUE 'A', attr_val TYPE c VALUE 'V', comment TYPE c VALUE 'C', END OF c_token . CONSTANTS: BEGIN OF c_regex, "for XML tags, we will use a submatch " main pattern includes quoted strings so we can ignore < and > in attr values xml_tag TYPE string VALUE '(?:"[^"]*")|(?:''[^'']*'')|(?:`[^`]*`)|([<>])', attr TYPE string VALUE '(?:^|\s)[-a-z:_0-9]+\s*(?==\s*["|''|`])', attr_val TYPE string VALUE '("[^"]*")|(''[^'']*'')|(`[^`]*`)', " comments comment TYPE string VALUE '[\<]!--.*--[\>]|[\<]!--|--[\>]', END OF c_regex . METHODS constructor . PROTECTED SECTION. CLASS-DATA gv_comment TYPE abap_bool. METHODS order_matches REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_gui DEFINITION CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_services . CONSTANTS: BEGIN OF c_event_state, not_handled TYPE i VALUE 0, re_render TYPE i VALUE 1, new_page TYPE i VALUE 2, go_back TYPE i VALUE 3, no_more_act TYPE i VALUE 4, new_page_w_bookmark TYPE i VALUE 5, go_back_to_bookmark TYPE i VALUE 6, new_page_replacing TYPE i VALUE 7, END OF c_event_state . METHODS go_home IMPORTING iv_action TYPE string RAISING zcx_abapgit_exception . METHODS back IMPORTING !iv_to_bookmark TYPE abap_bool DEFAULT abap_false !iv_graceful TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_exit) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS back_graceful RETURNING VALUE(rv_handled) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS on_event FOR EVENT sapevent OF zif_abapgit_html_viewer IMPORTING !action !frame !getdata !postdata !query_table . METHODS constructor IMPORTING !io_component TYPE REF TO object OPTIONAL !ii_asset_man TYPE REF TO zif_abapgit_gui_asset_manager OPTIONAL !ii_hotkey_ctl TYPE REF TO zif_abapgit_gui_hotkey_ctl OPTIONAL !ii_html_processor TYPE REF TO zif_abapgit_gui_html_processor OPTIONAL !iv_rollback_on_error TYPE abap_bool DEFAULT abap_true RAISING zcx_abapgit_exception . METHODS free . METHODS set_focus RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_page_stack, page TYPE REF TO zif_abapgit_gui_renderable, bookmark TYPE abap_bool, END OF ty_page_stack . DATA mv_rollback_on_error TYPE abap_bool . DATA mi_cur_page TYPE REF TO zif_abapgit_gui_renderable . DATA mt_stack TYPE STANDARD TABLE OF ty_page_stack . DATA mt_event_handlers TYPE STANDARD TABLE OF REF TO zif_abapgit_gui_event_handler . DATA mi_router TYPE REF TO zif_abapgit_gui_event_handler . DATA mi_asset_man TYPE REF TO zif_abapgit_gui_asset_manager . DATA mi_hotkey_ctl TYPE REF TO zif_abapgit_gui_hotkey_ctl . DATA mi_html_processor TYPE REF TO zif_abapgit_gui_html_processor . DATA mi_html_viewer TYPE REF TO zif_abapgit_html_viewer . DATA mo_html_parts TYPE REF TO zcl_abapgit_html_parts . DATA mi_common_log TYPE REF TO zif_abapgit_log . METHODS cache_html IMPORTING !iv_text TYPE string RETURNING VALUE(rv_url) TYPE string RAISING zcx_abapgit_exception . METHODS startup RAISING zcx_abapgit_exception . METHODS render RAISING zcx_abapgit_exception . METHODS call_page IMPORTING !ii_page TYPE REF TO zif_abapgit_gui_renderable !iv_with_bookmark TYPE abap_bool DEFAULT abap_false !iv_replacing TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . METHODS handle_action IMPORTING !iv_action TYPE c !iv_getdata TYPE c OPTIONAL !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data OPTIONAL . METHODS handle_error IMPORTING !ix_exception TYPE REF TO zcx_abapgit_exception . METHODS is_page_modal IMPORTING !ii_page TYPE REF TO zif_abapgit_gui_renderable RETURNING VALUE(rv_yes) TYPE abap_bool . ENDCLASS. CLASS zcl_abapgit_gui_asset_manager DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_asset_manager. CLASS-METHODS create RETURNING VALUE(ri_asset_manager) TYPE REF TO zif_abapgit_gui_asset_manager. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_asset_entry. INCLUDE TYPE zif_abapgit_gui_asset_manager~ty_web_asset. TYPES: mime_name TYPE wwwdatatab-objid, END OF ty_asset_entry. TYPES: ty_asset_register TYPE STANDARD TABLE OF ty_asset_entry WITH KEY url. DATA mt_asset_register TYPE ty_asset_register. METHODS get_mime_asset IMPORTING iv_mime_name TYPE c RETURNING VALUE(rv_xdata) TYPE xstring RAISING zcx_abapgit_exception. METHODS load_asset IMPORTING is_asset_entry TYPE ty_asset_entry RETURNING VALUE(rs_asset) TYPE zif_abapgit_gui_asset_manager~ty_web_asset RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_css_processor DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS: constructor IMPORTING ii_asset_manager TYPE REF TO zif_abapgit_gui_asset_manager, add_file IMPORTING iv_url TYPE string, process RETURNING VALUE(rv_result) TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_css_var, name TYPE string, value TYPE string, END OF ty_css_var, ty_css_vars TYPE SORTED TABLE OF ty_css_var WITH UNIQUE KEY name. METHODS: get_css_vars_in_string IMPORTING iv_string TYPE string RETURNING VALUE(rt_variables) TYPE ty_css_vars, resolve_var_recursively IMPORTING iv_variable_name TYPE string CHANGING ct_variables TYPE ty_css_vars RAISING zcx_abapgit_exception. DATA: mi_asset_manager TYPE REF TO zif_abapgit_gui_asset_manager, mt_files TYPE string_table. ENDCLASS. CLASS zcl_abapgit_gui_event DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event . CLASS-METHODS class_constructor . CLASS-METHODS new IMPORTING !ii_gui_services TYPE REF TO zif_abapgit_gui_services OPTIONAL !iv_action TYPE clike !iv_getdata TYPE clike OPTIONAL !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data OPTIONAL RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_gui_event. METHODS constructor IMPORTING !ii_gui_services TYPE REF TO zif_abapgit_gui_services OPTIONAL !iv_action TYPE clike !iv_getdata TYPE clike OPTIONAL !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data OPTIONAL . PROTECTED SECTION. PRIVATE SECTION. DATA mo_query TYPE REF TO zcl_abapgit_string_map. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. CLASS-DATA gv_non_breaking_space TYPE string . TYPES: BEGIN OF ty_name_value, name TYPE string, value TYPE string, END OF ty_name_value. TYPES ty_name_value_tt TYPE STANDARD TABLE OF ty_name_value WITH DEFAULT KEY. METHODS fields_to_map IMPORTING it_fields TYPE ty_name_value_tt RETURNING VALUE(ro_string_map) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. CLASS-METHODS parse_post_form_data IMPORTING !it_post_data TYPE zif_abapgit_html_viewer=>ty_post_data !iv_upper_cased TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rt_fields) TYPE ty_name_value_tt . CLASS-METHODS parse_fields IMPORTING !iv_string TYPE clike !iv_upper_cased TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rt_fields) TYPE ty_name_value_tt . CLASS-METHODS parse_fields_upper_case_name IMPORTING !iv_string TYPE clike RETURNING VALUE(rt_fields) TYPE ty_name_value_tt . CLASS-METHODS translate_postdata IMPORTING !it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data RETURNING VALUE(rv_string) TYPE string . CLASS-METHODS field_keys_to_upper CHANGING !ct_fields TYPE ty_name_value_tt . CLASS-METHODS unescape IMPORTING !iv_string TYPE string RETURNING VALUE(rv_string) TYPE string . ENDCLASS. CLASS zcl_abapgit_gui_html_processor DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CONSTANTS c_css_build_name TYPE string VALUE 'css/bundle.css'. CONSTANTS c_preprocess_marker TYPE string VALUE ``. CONSTANTS c_comment_start TYPE string VALUE ``. INTERFACES zif_abapgit_gui_html_processor . METHODS constructor IMPORTING ii_asset_man TYPE REF TO zif_abapgit_gui_asset_manager. METHODS preserve_css IMPORTING !iv_css_url TYPE string . PROTECTED SECTION. PRIVATE SECTION. DATA mt_preserve_css TYPE string_table. DATA mi_asset_man TYPE REF TO zif_abapgit_gui_asset_manager. METHODS patch_html IMPORTING iv_html TYPE string EXPORTING ev_html TYPE string et_css_urls TYPE string_table RAISING zcx_abapgit_exception. METHODS is_preserved IMPORTING !iv_css_url TYPE string RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS find_head_offset IMPORTING iv_html TYPE string RETURNING VALUE(rv_head_end) TYPE i RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_utils DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS is_renderable IMPORTING !io_obj TYPE REF TO object RETURNING VALUE(rv_yes) TYPE abap_bool . CLASS-METHODS is_event_handler IMPORTING !io_obj TYPE REF TO object RETURNING VALUE(rv_yes) TYPE abap_bool . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_html DEFINITION CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_html . CONSTANTS c_indent_size TYPE i VALUE 2 ##NO_TEXT. CLASS-METHODS class_constructor . CLASS-METHODS create IMPORTING !iv_initial_chunk TYPE any OPTIONAL RETURNING VALUE(ri_instance) TYPE REF TO zif_abapgit_html. CLASS-METHODS icon IMPORTING !iv_name TYPE string !iv_hint TYPE string OPTIONAL !iv_class TYPE string OPTIONAL !iv_onclick TYPE string OPTIONAL RETURNING VALUE(rv_str) TYPE string . CLASS-METHODS checkbox IMPORTING iv_id TYPE string OPTIONAL iv_checked TYPE abap_bool OPTIONAL RETURNING VALUE(rv_html) TYPE string . CLASS-METHODS parse_data_attr IMPORTING iv_str TYPE string OPTIONAL RETURNING VALUE(rs_data_attr) TYPE zif_abapgit_html=>ty_data_attr . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_max_indent TYPE i VALUE 200. TYPES: BEGIN OF ty_indent_context, no_indent_jscss TYPE abap_bool, within_style TYPE abap_bool, within_js TYPE abap_bool, within_textarea TYPE abap_bool, indent TYPE i, indent_str TYPE string, END OF ty_indent_context . TYPES: BEGIN OF ty_study_result, style_open TYPE abap_bool, style_close TYPE abap_bool, script_open TYPE abap_bool, script_close TYPE abap_bool, textarea_open TYPE abap_bool, textarea_close TYPE abap_bool, tag_close TYPE abap_bool, curly_close TYPE abap_bool, openings TYPE i, closings TYPE i, singles TYPE i, END OF ty_study_result . CLASS-DATA go_single_tags_re TYPE REF TO cl_abap_regex . DATA mt_buffer TYPE string_table . CLASS-DATA gv_spaces TYPE string . CLASS-DATA gv_debug_mode TYPE abap_bool . METHODS indent_line CHANGING !cs_context TYPE ty_indent_context !cv_line TYPE string . METHODS study_line IMPORTING !iv_line TYPE string !is_context TYPE ty_indent_context RETURNING VALUE(rs_result) TYPE ty_study_result . ENDCLASS. CLASS zcl_abapgit_html_parts DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS add_part IMPORTING !iv_collection TYPE string !ii_part TYPE REF TO zif_abapgit_html . METHODS get_parts IMPORTING !iv_collection TYPE string RETURNING VALUE(rt_parts) TYPE zif_abapgit_html=>ty_table_of . METHODS get_collection_names RETURNING VALUE(rt_list) TYPE string_table . METHODS get_collection_size IMPORTING !iv_collection TYPE string RETURNING VALUE(rv_size) TYPE i . METHODS clear. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_named_collection, name TYPE string, pile TYPE zif_abapgit_html=>ty_table_of, END OF ty_named_collection. TYPES: ty_named_collections TYPE STANDARD TABLE OF ty_named_collection WITH KEY name. DATA mt_part_collections TYPE ty_named_collections. METHODS get_collection IMPORTING !iv_collection TYPE string !iv_create_if_missing TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rr_collection) TYPE REF TO ty_named_collection . ENDCLASS. CLASS zcl_abapgit_html_viewer_gui DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_html_viewer . METHODS constructor IMPORTING !io_container TYPE REF TO cl_gui_container DEFAULT cl_gui_container=>screen0 !iv_disable_query_table TYPE abap_bool DEFAULT abap_true . PROTECTED SECTION. DATA mo_html_viewer TYPE REF TO cl_gui_html_viewer . METHODS on_event FOR EVENT sapevent OF cl_gui_html_viewer IMPORTING !action !frame !getdata !postdata !query_table . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_flow_exit DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_flow_exit . CLASS-METHODS get_instance RETURNING VALUE(ri_exit) TYPE REF TO zif_abapgit_flow_exit. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gi_global_exit TYPE REF TO zif_abapgit_flow_exit. CLASS-DATA gi_exit TYPE REF TO zif_abapgit_flow_exit. ENDCLASS. CLASS zcl_abapgit_exception_viewer DEFINITION CREATE PUBLIC. PUBLIC SECTION. METHODS: constructor IMPORTING ix_error TYPE REF TO zcx_abapgit_exception, goto_source RAISING zcx_abapgit_exception, goto_message RAISING zcx_abapgit_exception, show_callstack RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mx_error TYPE REF TO zcx_abapgit_exception, mt_callstack TYPE abap_callstack. METHODS: build_top_of_list IMPORTING is_top_of_stack TYPE abap_callstack_line RETURNING VALUE(ro_form) TYPE REF TO cl_salv_form_element, add_row IMPORTING io_grid TYPE REF TO cl_salv_form_layout_grid iv_col_1 TYPE csequence iv_col_2 TYPE csequence, on_double_click FOR EVENT double_click OF cl_salv_events_table IMPORTING row column, set_text IMPORTING io_columns TYPE REF TO cl_salv_columns_table iv_column TYPE lvc_fname iv_text TYPE string RAISING cx_static_check, goto_source_code IMPORTING is_callstack TYPE abap_callstack_line RAISING zcx_abapgit_exception, extract_classname IMPORTING iv_mainprogram TYPE abap_callstack_line-mainprogram RETURNING VALUE(rv_classname) TYPE tadir-obj_name, get_top_of_callstack RETURNING VALUE(rs_top_of_callstack) TYPE abap_callstack_line RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_buttons DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS new_online RETURNING VALUE(rv_html_string) TYPE string. CLASS-METHODS flow RETURNING VALUE(rv_html_string) TYPE string. CLASS-METHODS new_offline RETURNING VALUE(rv_html_string) TYPE string. CLASS-METHODS advanced RETURNING VALUE(rv_html_string) TYPE string. CLASS-METHODS help RETURNING VALUE(rv_html_string) TYPE string. CLASS-METHODS repo_list RETURNING VALUE(rv_html_string) TYPE string. CLASS-METHODS settings RETURNING VALUE(rv_html_string) TYPE string. CLASS-METHODS experimental RETURNING VALUE(rv_html_string) TYPE string. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_gui_chunk_lib DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_event_signature, method TYPE string, name TYPE string, END OF ty_event_signature . CLASS-METHODS class_constructor . CLASS-METHODS render_error IMPORTING !ix_error TYPE REF TO zcx_abapgit_exception OPTIONAL !iv_error TYPE string OPTIONAL !iv_extra_style TYPE string OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . CLASS-METHODS render_success IMPORTING iv_message TYPE string RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . CLASS-METHODS render_repo_top IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo !iv_show_package TYPE abap_bool DEFAULT abap_true !iv_show_branch TYPE abap_bool DEFAULT abap_true !iv_show_commit TYPE abap_bool DEFAULT abap_true !iv_show_edit TYPE abap_bool DEFAULT abap_false !iv_interactive_branch TYPE abap_bool DEFAULT abap_false !io_news TYPE REF TO zcl_abapgit_repo_news OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_item_state IMPORTING !iv_lstate TYPE char1 !iv_rstate TYPE char1 RETURNING VALUE(rv_html) TYPE string . CLASS-METHODS render_js_error_banner RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_news IMPORTING !io_news TYPE REF TO zcl_abapgit_repo_news RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_error_message_box IMPORTING !ix_error TYPE REF TO zcx_abapgit_exception RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . CLASS-METHODS render_table_header IMPORTING !it_col_spec TYPE zif_abapgit_definitions=>ty_col_spec_tt !iv_order_by TYPE string !iv_order_descending TYPE abap_bool RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . CLASS-METHODS render_table_footer IMPORTING !iv_message TYPE string RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . CLASS-METHODS render_warning_banner IMPORTING !iv_text TYPE string RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . CLASS-METHODS render_infopanel IMPORTING !iv_div_id TYPE string !iv_title TYPE string !iv_hide TYPE abap_bool DEFAULT abap_true !iv_hint TYPE string OPTIONAL !iv_scrollable TYPE abap_bool DEFAULT abap_true !io_content TYPE REF TO zif_abapgit_html RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_event_as_form IMPORTING !is_event TYPE ty_event_signature RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . CLASS-METHODS render_repo_palette IMPORTING iv_action TYPE string RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_branch_name IMPORTING !iv_branch TYPE string OPTIONAL !iv_repo_key TYPE zif_abapgit_persistence=>ty_value OPTIONAL !io_repo TYPE REF TO zcl_abapgit_repo_online OPTIONAL !iv_interactive TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_repo_url IMPORTING iv_url TYPE zif_abapgit_persistence=>ty_repo-url iv_render_remote_edit_for_key TYPE zif_abapgit_persistence=>ty_repo-key OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_package_name IMPORTING !iv_package TYPE devclass !iv_interactive TYPE abap_bool DEFAULT abap_true !iv_suppress_title TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_user_name IMPORTING !iv_username TYPE syuname !iv_interactive TYPE abap_bool DEFAULT abap_true !iv_icon_only TYPE abap_bool DEFAULT abap_false !iv_suppress_title TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_transport IMPORTING !iv_transport TYPE trkorr !iv_interactive TYPE abap_bool DEFAULT abap_true !iv_icon_only TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_sci_result IMPORTING ii_html TYPE REF TO zif_abapgit_html iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result. CLASS-METHODS render_path IMPORTING !iv_path TYPE string !iv_interactive TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . CLASS-METHODS render_timestamp IMPORTING iv_timestamp TYPE timestampl RETURNING VALUE(rv_rendered) TYPE string. CLASS-METHODS render_text_input IMPORTING iv_name TYPE string iv_label TYPE string iv_value TYPE string OPTIONAL iv_max_length TYPE string OPTIONAL iv_autofocus TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html. CLASS-METHODS render_label_list IMPORTING it_labels TYPE string_table io_label_colors TYPE REF TO zcl_abapgit_string_map iv_clickable_action TYPE string OPTIONAL iv_unlisted TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_html) TYPE string. CLASS-METHODS render_help_hint IMPORTING iv_text_to_wrap TYPE string iv_add_class TYPE string OPTIONAL RETURNING VALUE(rv_html) TYPE string. CLASS-METHODS get_item_icon IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item RETURNING VALUE(rv_html) TYPE string. CLASS-METHODS get_item_link IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item OPTIONAL !iv_obj_type TYPE zif_abapgit_definitions=>ty_repo_item-obj_type OPTIONAL !iv_obj_name TYPE zif_abapgit_definitions=>ty_repo_item-obj_name OPTIONAL PREFERRED PARAMETER is_item RETURNING VALUE(rv_html) TYPE string. PROTECTED SECTION. CLASS-METHODS render_repo_top_commit_hash IMPORTING !ii_html TYPE REF TO zif_abapgit_html !io_repo_online TYPE REF TO zcl_abapgit_repo_online RAISING zcx_abapgit_exception . PRIVATE SECTION. CLASS-DATA gv_time_zone TYPE timezone . CLASS-METHODS get_t100_text IMPORTING !iv_msgid TYPE scx_t100key-msgid !iv_msgno TYPE scx_t100key-msgno RETURNING VALUE(rv_text) TYPE string . CLASS-METHODS normalize_program_name IMPORTING !iv_program_name TYPE sy-repid RETURNING VALUE(rv_normalized_program_name) TYPE string . CLASS-METHODS shorten_repo_url IMPORTING iv_full_url TYPE string iv_max_length TYPE i DEFAULT 60 RETURNING VALUE(rv_shortened) TYPE string. ENDCLASS. CLASS zcl_abapgit_gui_component DEFINITION ABSTRACT CREATE PUBLIC . PUBLIC SECTION. CONSTANTS: BEGIN OF c_html_parts, scripts TYPE string VALUE 'scripts', hidden_forms TYPE string VALUE 'hidden_forms', END OF c_html_parts. PROTECTED SECTION. METHODS register_deferred_script IMPORTING ii_part TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS gui_services RETURNING VALUE(ri_gui_services) TYPE REF TO zif_abapgit_gui_services RAISING zcx_abapgit_exception. METHODS register_handlers RAISING zcx_abapgit_exception. PRIVATE SECTION. DATA mi_gui_services TYPE REF TO zif_abapgit_gui_services. METHODS register_event_handler IMPORTING ii_event_handler TYPE REF TO zif_abapgit_gui_event_handler OPTIONAL RAISING zcx_abapgit_exception. METHODS register_hotkeys IMPORTING ii_hotkey_provider TYPE REF TO zif_abapgit_gui_hotkeys OPTIONAL RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_template DEFINITION FINAL INHERITING FROM zcl_abapgit_gui_component CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_gui_page_title, zif_abapgit_gui_event_handler, zif_abapgit_gui_hotkeys, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable, " TODO: remove table interface if not used on the page zif_abapgit_html_table. CLASS-METHODS create " TODO: page parameters, e.g. ref to repo * IMPORTING * ii_repo TYPE REF TO zif_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor * IMPORTING * ii_repo TYPE REF TO zif_abapgit_repo RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_action, " TODO: List of in-page actions refresh TYPE string VALUE 'refresh', END OF c_action. CONSTANTS c_title TYPE string VALUE 'Page Template'. " TODO: define page title ENDCLASS. CLASS zcl_abapgit_gui_hotkey_ctl DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_gui_hotkeys. INTERFACES zif_abapgit_gui_hotkey_ctl. INTERFACES zif_abapgit_gui_renderable. CONSTANTS c_showhotkeys_action TYPE string VALUE `showHotkeys` ##NO_TEXT. CLASS-METHODS should_show_hint RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS constructor RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA: mt_hotkeys TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr, ms_user_settings TYPE zif_abapgit_definitions=>ty_s_user_settings, mv_visible TYPE abap_bool. CLASS-DATA gv_hint_was_shown TYPE abap_bool . METHODS render_scripts IMPORTING !it_hotkeys TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . ENDCLASS. CLASS zcl_abapgit_gui_page_flow DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler . INTERFACES zif_abapgit_gui_renderable . INTERFACES zif_abapgit_gui_menu_provider . CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS constructor RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_action, refresh TYPE string VALUE 'refresh', pull TYPE string VALUE 'pull', stage TYPE string VALUE 'stage', END OF c_action . DATA mt_features TYPE zif_abapgit_gui_page_flow=>ty_features . METHODS refresh RAISING zcx_abapgit_exception . METHODS set_branch IMPORTING !iv_branch TYPE string !iv_key TYPE zif_abapgit_persistence=>ty_value RAISING zcx_abapgit_exception . METHODS render_table IMPORTING !is_feature TYPE zif_abapgit_gui_page_flow=>ty_feature RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_toolbar IMPORTING !iv_index TYPE i !is_feature TYPE zif_abapgit_gui_page_flow=>ty_feature RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . ENDCLASS. CLASS zcl_abapgit_gui_in_page_modal DEFINITION CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING !ii_child TYPE REF TO zif_abapgit_gui_renderable !iv_width TYPE i OPTIONAL !iv_height TYPE i OPTIONAL RETURNING VALUE(ro_wrap) TYPE REF TO zcl_abapgit_gui_in_page_modal RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !ii_child TYPE REF TO zif_abapgit_gui_renderable !iv_width TYPE i OPTIONAL !iv_height TYPE i OPTIONAL. PROTECTED SECTION. PRIVATE SECTION. DATA mi_child TYPE REF TO zif_abapgit_gui_renderable. DATA: BEGIN OF ms_attrs, width TYPE i, height TYPE i, END OF ms_attrs. ENDCLASS. CLASS zcl_abapgit_gui_menus DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS advanced RETURNING VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. CLASS-METHODS help RETURNING VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. CLASS-METHODS back RETURNING VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. CLASS-METHODS settings IMPORTING !iv_act TYPE string RETURNING VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. CLASS-METHODS repo_settings IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !iv_act TYPE string RETURNING VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. CLASS-METHODS experimental IMPORTING io_menu TYPE REF TO zcl_abapgit_html_toolbar. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_gui_page DEFINITION ABSTRACT INHERITING FROM zcl_abapgit_gui_component CREATE PUBLIC. PUBLIC SECTION. INTERFACES: zif_abapgit_gui_modal, zif_abapgit_gui_renderable, zif_abapgit_gui_event_handler, zif_abapgit_gui_error_handler. TYPES: BEGIN OF ty_control, page_layout TYPE string, page_title TYPE string, page_menu TYPE REF TO zcl_abapgit_html_toolbar, page_menu_provider TYPE REF TO zif_abapgit_gui_menu_provider, page_title_provider TYPE REF TO zif_abapgit_gui_page_title, extra_css_url TYPE string, extra_js_url TYPE string, show_as_modal TYPE abap_bool, END OF ty_control . METHODS constructor RAISING zcx_abapgit_exception. CONSTANTS: BEGIN OF c_page_layout, centered TYPE string VALUE `centered`, full_width TYPE string VALUE `full_width`, END OF c_page_layout. PROTECTED SECTION. DATA ms_control TYPE ty_control . METHODS render_content " TODO refactor, render child directly ABSTRACT RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . PRIVATE SECTION. DATA mo_settings TYPE REF TO zcl_abapgit_settings . DATA mx_error TYPE REF TO zcx_abapgit_exception . DATA mo_exception_viewer TYPE REF TO zcl_abapgit_exception_viewer . METHODS render_deferred_parts IMPORTING !ii_html TYPE REF TO zif_abapgit_html !iv_part_category TYPE string RAISING zcx_abapgit_exception . METHODS html_head RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS header_stylesheet_links IMPORTING ii_html TYPE REF TO zif_abapgit_html . METHODS header_script_links IMPORTING ii_html TYPE REF TO zif_abapgit_html . METHODS title RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS footer IMPORTING !iv_time TYPE string RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_link_hints IMPORTING !ii_html TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_browser_control_warning IMPORTING !ii_html TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_command_palettes IMPORTING !ii_html TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_hotkey_overview RETURNING VALUE(ro_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_error_message_box RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS scripts RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS get_version_details RETURNING VALUE(rv_version) TYPE string. METHODS is_edge_control_warning_needed RETURNING VALUE(rv_result) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_gui_page_hoc DEFINITION INHERITING FROM zcl_abapgit_gui_page FINAL CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS create IMPORTING !ii_child_component TYPE REF TO zif_abapgit_gui_renderable !iv_page_title TYPE string OPTIONAL !iv_page_layout TYPE string DEFAULT zcl_abapgit_gui_page=>c_page_layout-centered !io_page_menu TYPE REF TO zcl_abapgit_html_toolbar OPTIONAL !ii_page_menu_provider TYPE REF TO zif_abapgit_gui_menu_provider OPTIONAL !ii_page_title_provider TYPE REF TO zif_abapgit_gui_page_title OPTIONAL !iv_extra_css_url TYPE string OPTIONAL !iv_extra_js_url TYPE string OPTIONAL !iv_show_as_modal TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_page_wrap) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS get_child RETURNING VALUE(ri_child) TYPE REF TO zif_abapgit_gui_renderable. METHODS constructor IMPORTING !ii_child_component TYPE REF TO zif_abapgit_gui_renderable !is_control TYPE zcl_abapgit_gui_page=>ty_control RAISING zcx_abapgit_exception. PROTECTED SECTION. METHODS render_content REDEFINITION. PRIVATE SECTION. DATA mi_child TYPE REF TO zif_abapgit_gui_renderable . METHODS detect_modal RETURNING VALUE(rv_is_modal) TYPE abap_bool. METHODS detect_menu_provider RETURNING VALUE(ri_ref) TYPE REF TO zif_abapgit_gui_menu_provider. METHODS detect_title_provider RETURNING VALUE(ri_ref) TYPE REF TO zif_abapgit_gui_page_title. ENDCLASS. CLASS zcl_abapgit_gui_picklist DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. INTERFACES zif_abapgit_gui_page_title. METHODS constructor IMPORTING !it_list TYPE STANDARD TABLE !iv_id TYPE string OPTIONAL !iv_in_page TYPE abap_bool DEFAULT abap_false !iv_title TYPE string DEFAULT 'Choose from list' !iv_attr_name TYPE abap_compname OPTIONAL !ii_item_renderer TYPE REF TO zif_abapgit_gui_render_item OPTIONAL RAISING zcx_abapgit_exception. METHODS get_result_idx RETURNING VALUE(rv_index) TYPE i. METHODS get_result_item CHANGING !cs_selected TYPE any. METHODS was_cancelled RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS is_fulfilled RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS id RETURNING VALUE(rv_id) TYPE string. METHODS is_in_page RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS set_id IMPORTING iv_id TYPE string RETURNING VALUE(ro_me) TYPE REF TO zcl_abapgit_gui_picklist. METHODS set_in_page IMPORTING iv_in_page TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ro_me) TYPE REF TO zcl_abapgit_gui_picklist. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_event, back TYPE string VALUE 'back', choose TYPE string VALUE 'choose', END OF c_event. CONSTANTS c_radio_name TYPE string VALUE 'radio'. DATA mo_form TYPE REF TO zcl_abapgit_html_form. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. DATA mr_list TYPE REF TO data. DATA mv_selected TYPE i. DATA mv_cancelled TYPE abap_bool. DATA mv_fulfilled TYPE abap_bool. DATA mv_attr_name TYPE abap_compname. DATA mi_item_renderer TYPE REF TO zif_abapgit_gui_render_item. DATA mv_in_page TYPE abap_bool. DATA mv_id TYPE string. DATA mv_title TYPE string. METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form RAISING zcx_abapgit_exception. METHODS return_state RETURNING VALUE(rv_state) TYPE zif_abapgit_gui_event_handler=>ty_handling_result-state. ENDCLASS. CLASS zcl_abapgit_html_action_utils DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS jump_encode IMPORTING !iv_obj_type TYPE tadir-object !iv_obj_name TYPE tadir-obj_name !iv_filename TYPE string OPTIONAL RETURNING VALUE(rv_string) TYPE string . CLASS-METHODS dir_encode IMPORTING !iv_path TYPE string RETURNING VALUE(rv_string) TYPE string . CLASS-METHODS file_encode IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !ig_file TYPE any !iv_extra TYPE clike OPTIONAL RETURNING VALUE(rv_string) TYPE string . CLASS-METHODS obj_encode IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !ig_object TYPE any RETURNING VALUE(rv_string) TYPE string . CLASS-METHODS dbkey_encode IMPORTING !is_key TYPE zif_abapgit_persistence=>ty_content RETURNING VALUE(rv_string) TYPE string . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_name_value, name TYPE string, value TYPE string, END OF ty_name_value. TYPES ty_name_value_tt TYPE STANDARD TABLE OF ty_name_value WITH DEFAULT KEY. CLASS-METHODS add_field IMPORTING !iv_name TYPE string !ig_field TYPE any CHANGING !ct_field TYPE ty_name_value_tt . CLASS-METHODS fields_to_string IMPORTING !it_fields TYPE ty_name_value_tt RETURNING VALUE(rv_string) TYPE string. ENDCLASS. CLASS zcl_abapgit_html_form DEFINITION FINAL INHERITING FROM zcl_abapgit_gui_component CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_html_form . INTERFACES zif_abapgit_gui_hotkeys . CLASS-METHODS create IMPORTING !iv_form_id TYPE csequence OPTIONAL !iv_help_page TYPE csequence OPTIONAL RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form . METHODS render IMPORTING !iv_form_class TYPE csequence DEFAULT 'dialog-form' !io_values TYPE REF TO zcl_abapgit_string_map !io_validation_log TYPE REF TO zcl_abapgit_string_map OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS command IMPORTING !iv_label TYPE csequence !iv_action TYPE csequence !iv_cmd_type TYPE i DEFAULT zif_abapgit_html_form=>c_cmd_type-input RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS text IMPORTING !iv_label TYPE csequence !iv_name TYPE csequence !iv_hint TYPE csequence OPTIONAL !iv_required TYPE abap_bool DEFAULT abap_false !iv_upper_case TYPE abap_bool DEFAULT abap_false !iv_readonly TYPE abap_bool DEFAULT abap_false !iv_password TYPE abap_bool DEFAULT abap_false !iv_condense TYPE abap_bool OPTIONAL !iv_placeholder TYPE csequence OPTIONAL !iv_side_action TYPE csequence OPTIONAL !iv_min TYPE i DEFAULT cl_abap_math=>min_int4 !iv_max TYPE i DEFAULT cl_abap_math=>max_int4 RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS textarea IMPORTING !iv_label TYPE csequence !iv_name TYPE csequence !iv_hint TYPE csequence OPTIONAL !iv_required TYPE abap_bool DEFAULT abap_false !iv_readonly TYPE abap_bool DEFAULT abap_false !iv_placeholder TYPE csequence OPTIONAL !iv_rows TYPE i OPTIONAL !iv_cols TYPE i OPTIONAL !iv_upper_case TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS number IMPORTING !iv_label TYPE csequence !iv_name TYPE csequence !iv_hint TYPE csequence OPTIONAL !iv_required TYPE abap_bool DEFAULT abap_false !iv_readonly TYPE abap_bool DEFAULT abap_false !iv_min TYPE i DEFAULT cl_abap_math=>min_int4 !iv_max TYPE i DEFAULT cl_abap_math=>max_int4 RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS checkbox IMPORTING !iv_label TYPE csequence !iv_name TYPE csequence !iv_hint TYPE csequence OPTIONAL !iv_readonly TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS radio IMPORTING !iv_label TYPE csequence !iv_name TYPE csequence !iv_default_value TYPE csequence OPTIONAL !iv_hint TYPE csequence OPTIONAL !iv_condense TYPE abap_bool DEFAULT abap_false !iv_action TYPE csequence OPTIONAL RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS option IMPORTING !iv_label TYPE csequence !iv_value TYPE csequence RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS table IMPORTING !iv_label TYPE csequence !iv_name TYPE csequence !iv_hint TYPE csequence OPTIONAL RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS column IMPORTING !iv_label TYPE csequence !iv_width TYPE csequence OPTIONAL !iv_readonly TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS start_group IMPORTING !iv_label TYPE csequence !iv_name TYPE csequence !iv_hint TYPE csequence OPTIONAL RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS hidden IMPORTING !iv_name TYPE csequence RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_form . METHODS get_fields RETURNING VALUE(rt_fields) TYPE zif_abapgit_html_form=>ty_fields . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_attr, value TYPE string, error TYPE string, hint TYPE string, readonly TYPE string, placeholder TYPE string, required TYPE string, autofocus TYPE string, END OF ty_attr . DATA mv_webgui TYPE abap_bool. DATA mt_fields TYPE zif_abapgit_html_form=>ty_fields . DATA: mt_commands TYPE STANDARD TABLE OF zif_abapgit_html_form=>ty_command . DATA mv_form_id TYPE string . DATA mv_help_page TYPE string . METHODS render_field IMPORTING !ii_html TYPE REF TO zif_abapgit_html !io_values TYPE REF TO zcl_abapgit_string_map !io_validation_log TYPE REF TO zcl_abapgit_string_map !is_field TYPE zif_abapgit_html_form=>ty_field !iv_autofocus TYPE abap_bool . METHODS render_field_text IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_field TYPE zif_abapgit_html_form=>ty_field !is_attr TYPE ty_attr . METHODS render_field_textarea IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_field TYPE zif_abapgit_html_form=>ty_field !is_attr TYPE ty_attr . METHODS render_field_checkbox IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_field TYPE zif_abapgit_html_form=>ty_field !is_attr TYPE ty_attr . METHODS render_field_radio IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_field TYPE zif_abapgit_html_form=>ty_field !is_attr TYPE ty_attr . METHODS render_field_table IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_field TYPE zif_abapgit_html_form=>ty_field !is_attr TYPE ty_attr !io_values TYPE REF TO zcl_abapgit_string_map . METHODS render_command IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_cmd TYPE zif_abapgit_html_form=>ty_command . METHODS render_command_link IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_cmd TYPE zif_abapgit_html_form=>ty_command . METHODS render_field_hidden IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_field TYPE zif_abapgit_html_form=>ty_field !is_attr TYPE ty_attr . ENDCLASS. CLASS zcl_abapgit_html_form_utils DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS create IMPORTING !io_form TYPE REF TO zcl_abapgit_html_form RETURNING VALUE(ro_form_util) TYPE REF TO zcl_abapgit_html_form_utils . CLASS-METHODS is_dirty IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map !io_compare_with TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(rv_dirty) TYPE abap_bool . METHODS constructor IMPORTING !io_form TYPE REF TO zcl_abapgit_html_form . METHODS normalize IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS validate IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS is_empty IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(rv_empty) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS set_data IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map . METHODS exit IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map !io_compare_with TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(rv_state) TYPE i RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. DATA mo_form TYPE REF TO zcl_abapgit_html_form . DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . ENDCLASS. CLASS zcl_abapgit_html_table DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS create IMPORTING !ii_renderer TYPE REF TO zif_abapgit_html_table OPTIONAL " Can be passed to renderer !is_initial_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state OPTIONAL PREFERRED PARAMETER ii_renderer RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_html_table . " maybe also th css_class METHODS define_column IMPORTING !iv_column_id TYPE string !iv_column_title TYPE string OPTIONAL !iv_from_field TYPE abap_compname OPTIONAL !iv_sortable TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_table . METHODS define_column_group IMPORTING !iv_group_id TYPE string OPTIONAL " not mandatory, but can be used for CSS (TODO data-gid) !iv_group_title TYPE string OPTIONAL " can be empty ! PREFERRED PARAMETER iv_group_title RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_table RAISING zcx_abapgit_exception . " Maybe also data_provider " TODO record Limiter METHODS render IMPORTING !ii_renderer TYPE REF TO zif_abapgit_html_table OPTIONAL !it_data TYPE ANY TABLE !iv_id TYPE csequence OPTIONAL !iv_css_class TYPE csequence OPTIONAL !iv_with_cids TYPE abap_bool DEFAULT abap_false !is_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state OPTIONAL !iv_wrap_in_div TYPE string OPTIONAL " div class name RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . " Sorting utils CLASS-METHODS detect_sorting_request IMPORTING iv_event TYPE string RETURNING VALUE(rs_sorting_request) TYPE zif_abapgit_html_table=>ty_sorting_state. METHODS process_sorting_request IMPORTING iv_event TYPE string RETURNING VALUE(rv_processed) TYPE abap_bool. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_sort_by_event_prefix TYPE string VALUE `sort_by:`. CONSTANTS c_sort_by_event_regex TYPE string VALUE `^sort_by:\w+:(asc|dsc)$`. TYPES: BEGIN OF ty_column, column_id TYPE string, column_title TYPE string, from_field TYPE abap_compname, sortable TYPE abap_bool, is_group TYPE abap_bool, group_span TYPE i, END OF ty_column, ty_columns TYPE STANDARD TABLE OF ty_column WITH KEY column_id. DATA mi_renderer TYPE REF TO zif_abapgit_html_table. DATA mt_columns TYPE ty_columns. DATA mi_html TYPE REF TO zif_abapgit_html. DATA mv_with_cids TYPE abap_bool. DATA mv_table_id TYPE string. DATA ms_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state. DATA mr_last_grp TYPE REF TO ty_column. " potentially receive from outside DATA mv_sort_span_class TYPE string VALUE `sort-arrow`. DATA mv_sort_active_class TYPE string VALUE `sort-active`. METHODS render_thead RAISING zcx_abapgit_exception . METHODS render_tbody IMPORTING it_data TYPE ANY TABLE RAISING zcx_abapgit_exception . METHODS render_row IMPORTING iv_row_index TYPE i is_row TYPE any RAISING zcx_abapgit_exception . METHODS render_column_title IMPORTING is_col TYPE ty_column RETURNING VALUE(rv_text) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS cid_attr IMPORTING iv_column_id TYPE string RETURNING VALUE(rs_data_attr) TYPE zif_abapgit_html=>ty_data_attr. CLASS-METHODS gid_attr IMPORTING iv_column_id TYPE string RETURNING VALUE(rs_data_attr) TYPE zif_abapgit_html=>ty_data_attr. METHODS apply_sorting CHANGING ct_data TYPE STANDARD TABLE. ENDCLASS. CLASS zcl_abapgit_html_toolbar DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS create IMPORTING !iv_id TYPE string OPTIONAL RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_html_toolbar. METHODS constructor IMPORTING !iv_id TYPE string OPTIONAL . METHODS add IMPORTING !iv_txt TYPE string !io_sub TYPE REF TO zcl_abapgit_html_toolbar OPTIONAL !iv_typ TYPE c DEFAULT zif_abapgit_html=>c_action_type-sapevent !iv_act TYPE string OPTIONAL !iv_ico TYPE string OPTIONAL !iv_cur TYPE abap_bool OPTIONAL !iv_opt TYPE c OPTIONAL !iv_chk TYPE abap_bool DEFAULT abap_undefined !iv_aux TYPE string OPTIONAL !iv_id TYPE string OPTIONAL !iv_title TYPE string OPTIONAL !iv_class TYPE string OPTIONAL !iv_hotkey TYPE string OPTIONAL !iv_li_class TYPE string OPTIONAL RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_toolbar . METHODS count_items RETURNING VALUE(rv_count) TYPE i . METHODS render IMPORTING !iv_right TYPE abap_bool OPTIONAL !iv_sort TYPE abap_bool OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_as_droplist IMPORTING !iv_label TYPE string !iv_right TYPE abap_bool OPTIONAL !iv_sort TYPE abap_bool OPTIONAL !iv_corner TYPE abap_bool OPTIONAL !iv_action TYPE string OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS get_hotkeys IMPORTING iv_component_name TYPE string OPTIONAL RETURNING VALUE(rt_hotkeys) TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_item, txt TYPE string, act TYPE string, ico TYPE string, sub TYPE REF TO zcl_abapgit_html_toolbar, opt TYPE c LENGTH 1, typ TYPE c LENGTH 1, cur TYPE abap_bool, chk TYPE abap_bool, aux TYPE string, id TYPE string, title TYPE string, class TYPE string, li_class TYPE string, hotkey TYPE string, END OF ty_item . TYPES: ty_items TYPE STANDARD TABLE OF ty_item . DATA mt_items TYPE ty_items . DATA mv_id TYPE string . METHODS render_items IMPORTING !iv_sort TYPE abap_bool OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . ENDCLASS. CLASS zcl_abapgit_log_viewer DEFINITION FINAL CREATE PRIVATE . PUBLIC SECTION. CLASS-METHODS show_log IMPORTING !ii_log TYPE REF TO zif_abapgit_log . CLASS-METHODS to_html IMPORTING !ii_log TYPE REF TO zif_abapgit_log RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . CLASS-METHODS write_log IMPORTING !ii_log TYPE REF TO zif_abapgit_log . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_log_out, type TYPE icon_d, msg TYPE string, obj_type TYPE trobjtype, obj_name TYPE sobj_name, exception TYPE REF TO cx_root, longtext TYPE icon_d, t100 TYPE icon_d, source TYPE icon_d, callstack TYPE icon_d, cell_type TYPE salv_t_int4_column, END OF ty_log_out. TYPES: ty_log_outs TYPE STANDARD TABLE OF ty_log_out WITH NON-UNIQUE DEFAULT KEY. CLASS-METHODS: prepare_log_for_display IMPORTING ii_log TYPE REF TO zif_abapgit_log RETURNING VALUE(rt_log_out) TYPE ty_log_outs, show_longtext IMPORTING is_log TYPE ty_log_out RAISING zcx_abapgit_exception, goto_source IMPORTING is_log TYPE ty_log_out RAISING zcx_abapgit_exception, goto_callstack IMPORTING is_log TYPE ty_log_out RAISING zcx_abapgit_exception, goto_t100_message IMPORTING is_log TYPE ty_log_out RAISING zcx_abapgit_exception, on_link_click FOR EVENT link_click OF cl_salv_events_table IMPORTING row column, dispatch IMPORTING is_log TYPE ty_log_out iv_column TYPE salv_de_column RAISING zcx_abapgit_exception, calculate_cell_type, get_exception_viewer IMPORTING is_log TYPE ty_log_out RETURNING VALUE(ro_exception_viewer) TYPE REF TO zcl_abapgit_exception_viewer. CLASS-DATA: gt_log TYPE ty_log_outs. ENDCLASS. CLASS zcl_abapgit_gui_page_codi_base DEFINITION INHERITING FROM zcl_abapgit_gui_component. PUBLIC SECTION. INTERFACES zif_abapgit_html_table. PROTECTED SECTION. CONSTANTS: BEGIN OF c_actions, rerun TYPE string VALUE 'rerun', stage TYPE string VALUE 'stage', commit TYPE string VALUE 'commit', filter_kind TYPE string VALUE 'filter_kind', apply_filter TYPE string VALUE 'apply_filter', END OF c_actions . DATA mo_repo TYPE REF TO zcl_abapgit_repo. DATA mt_result TYPE zif_abapgit_code_inspector=>ty_results. DATA mv_summary TYPE string. METHODS on_event IMPORTING ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception. METHODS render_ci_report IMPORTING !ii_html TYPE REF TO zif_abapgit_html !iv_variant TYPE sci_chkv !iv_success_msg TYPE string RAISING zcx_abapgit_exception. METHODS render_head IMPORTING !ii_html TYPE REF TO zif_abapgit_html !iv_variant TYPE sci_chkv !iv_summary TYPE string. METHODS render_detail IMPORTING !ii_html TYPE REF TO zif_abapgit_html !it_result TYPE zif_abapgit_code_inspector=>ty_results RAISING zcx_abapgit_exception. METHODS render_stats IMPORTING !ii_html TYPE REF TO zif_abapgit_html !it_result TYPE zif_abapgit_code_inspector=>ty_results RAISING zcx_abapgit_exception. METHODS render_success IMPORTING ii_html TYPE REF TO zif_abapgit_html iv_message TYPE string. METHODS build_base_menu RETURNING VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. PRIVATE SECTION. CONSTANTS c_object_separator TYPE c LENGTH 1 VALUE '|'. CONSTANTS c_ci_sig TYPE string VALUE 'cinav:'. CONSTANTS c_limit TYPE i VALUE 500. DATA mv_filter_kind TYPE string. DATA ms_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state. TYPES: BEGIN OF ty_result_view, kind TYPE zif_abapgit_code_inspector=>ty_result-kind, obj_type TYPE zif_abapgit_code_inspector=>ty_result-objtype, location TYPE string, text TYPE string, nav TYPE string, END OF ty_result_view, ty_view_tab TYPE STANDARD TABLE OF ty_result_view WITH DEFAULT KEY. METHODS convert_result_to_view IMPORTING it_result TYPE zif_abapgit_code_inspector=>ty_results RETURNING VALUE(rt_view) TYPE ty_view_tab. METHODS explain_include IMPORTING !is_result TYPE zif_abapgit_code_inspector=>ty_result RETURNING VALUE(rv_txt) TYPE string. METHODS render_limit_warning IMPORTING !ii_html TYPE REF TO zif_abapgit_html. METHODS build_nav_link IMPORTING !is_result TYPE zif_abapgit_code_inspector=>ty_result RETURNING VALUE(rv_link) TYPE string. METHODS jump IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_item !is_sub_item TYPE zif_abapgit_definitions=>ty_item !iv_line_number TYPE i RAISING zcx_abapgit_exception. METHODS apply_sorting CHANGING ct_view TYPE ty_view_tab. METHODS apply_filter_kind CHANGING ct_view TYPE ty_view_tab. METHODS handle_navigation IMPORTING iv_link TYPE string RAISING zcx_abapgit_exception. METHODS render_stat IMPORTING !ii_html TYPE REF TO zif_abapgit_html !iv_count TYPE i !iv_type TYPE string !iv_title TYPE string RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_code_insp DEFINITION INHERITING FROM zcl_abapgit_gui_page_codi_base FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES: zif_abapgit_gui_page_title, zif_abapgit_gui_event_handler, zif_abapgit_gui_hotkeys, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING io_repo TYPE REF TO zcl_abapgit_repo io_stage TYPE REF TO zcl_abapgit_stage OPTIONAL iv_check_variant TYPE sci_chkv OPTIONAL iv_raise_when_no_results TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING io_repo TYPE REF TO zcl_abapgit_repo io_stage TYPE REF TO zcl_abapgit_stage OPTIONAL iv_check_variant TYPE sci_chkv OPTIONAL iv_raise_when_no_results TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mo_stage TYPE REF TO zcl_abapgit_stage. DATA mv_check_variant TYPE sci_chkv. METHODS: run_code_inspector RAISING zcx_abapgit_exception, has_inspection_errors RETURNING VALUE(rv_has_inspection_errors) TYPE abap_bool, is_stage_allowed RETURNING VALUE(rv_is_stage_allowed) TYPE abap_bool, ask_user_for_check_variant RETURNING VALUE(rv_check_variant) TYPE sci_chkv RAISING zcx_abapgit_exception, determine_check_variant RAISING zcx_abapgit_exception. METHODS status RETURNING VALUE(rv_status) TYPE zif_abapgit_definitions=>ty_sci_result. ENDCLASS. CLASS zcl_abapgit_gui_page_runit DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. INTERFACES zif_abapgit_gui_menu_provider. CLASS-METHODS create IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_actions, rerun TYPE string VALUE 'rerun' ##NO_TEXT, END OF c_actions . TYPES: BEGIN OF ty_key, obj_name TYPE tadir-obj_name, obj_type TYPE tadir-object, END OF ty_key, ty_keys_tt TYPE STANDARD TABLE OF ty_key WITH DEFAULT KEY. DATA mo_repo TYPE REF TO zcl_abapgit_repo. DATA mv_summary TYPE string. METHODS build_tadir RETURNING VALUE(rt_tadir) TYPE ty_keys_tt RAISING zcx_abapgit_exception. METHODS run RETURNING VALUE(ro_result) TYPE REF TO object RAISING zcx_abapgit_exception. METHODS get_text_for_method IMPORTING !is_method TYPE any !it_indices TYPE ANY TABLE !iv_program_ndx TYPE sy-tabix !iv_class_ndx TYPE sy-tabix !iv_method_ndx TYPE sy-tabix RETURNING VALUE(rv_text) TYPE string. ENDCLASS. CLASS zcl_abapgit_gui_page_syntax DEFINITION INHERITING FROM zcl_abapgit_gui_page_codi_base FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES: zif_abapgit_gui_page_title, zif_abapgit_gui_event_handler, zif_abapgit_gui_hotkeys, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING io_repo TYPE REF TO zcl_abapgit_repo RAISING zcx_abapgit_exception. PROTECTED SECTION. CONSTANTS c_variant TYPE c LENGTH 30 VALUE 'SYNTAX_CHECK'. PRIVATE SECTION. METHODS run_syntax_check RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_whereused DEFINITION FINAL INHERITING FROM zcl_abapgit_gui_component CREATE PUBLIC . PUBLIC SECTION. INTERFACES: zif_abapgit_gui_page_title, zif_abapgit_gui_event_handler, zif_abapgit_gui_hotkeys, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable, zif_abapgit_html_table. CLASS-METHODS create IMPORTING iv_package TYPE devclass OPTIONAL ii_repo TYPE REF TO zif_abapgit_repo OPTIONAL PREFERRED PARAMETER iv_package RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING iv_package TYPE devclass OPTIONAL ii_repo TYPE REF TO zif_abapgit_repo OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_action, refresh TYPE string VALUE 'refresh', show_used_obj TYPE string VALUE 'show_used_obj', END OF c_action. CONSTANTS c_title TYPE string VALUE 'Where Used'. DATA mv_package TYPE devclass. DATA mv_ignore_subpackages TYPE abap_bool. DATA mi_table TYPE REF TO zcl_abapgit_html_table. DATA mv_show_used_obj TYPE abap_bool. DATA mt_where_used TYPE zcl_abapgit_where_used_tools=>ty_dependency_tt. METHODS init_table_component RAISING zcx_abapgit_exception. METHODS render_filter_help_hint RETURNING VALUE(rv_html) TYPE string. METHODS render_header IMPORTING ii_html TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS run_where_used RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_db DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. INTERFACES zif_abapgit_gui_menu_provider. INTERFACES zif_abapgit_html_table. CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_action, delete TYPE string VALUE 'delete', backup TYPE string VALUE 'backup', restore TYPE string VALUE 'restore', END OF c_action. CONSTANTS c_css_url TYPE string VALUE 'css/page_db.css'. CONSTANTS c_toc_filename TYPE string VALUE '#_Table_of_Content_#.txt'. TYPES: BEGIN OF ty_explanation, value TYPE string, extra TYPE string, END OF ty_explanation. DATA mt_methods TYPE zcl_abapgit_background=>ty_methods. METHODS register_stylesheet RAISING zcx_abapgit_exception. METHODS render_stats IMPORTING it_db_entries TYPE zif_abapgit_persistence=>ty_contents RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS render_table IMPORTING it_db_entries TYPE zif_abapgit_persistence=>ty_contents RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS do_backup_db RAISING zcx_abapgit_exception. CLASS-METHODS do_delete_entry IMPORTING !is_key TYPE zif_abapgit_persistence=>ty_content RAISING zcx_abapgit_exception. CLASS-METHODS do_restore_db RAISING zcx_abapgit_exception. METHODS explain_content IMPORTING !is_data TYPE zif_abapgit_persistence=>ty_content RETURNING VALUE(rv_text) TYPE string RAISING zcx_abapgit_exception. METHODS explain_content_repo IMPORTING !is_data TYPE zif_abapgit_persistence=>ty_content RETURNING VALUE(rs_expl) TYPE ty_explanation RAISING zcx_abapgit_exception. METHODS explain_content_repo_cs IMPORTING !is_data TYPE zif_abapgit_persistence=>ty_content RETURNING VALUE(rs_expl) TYPE ty_explanation RAISING zcx_abapgit_exception. METHODS explain_content_background IMPORTING !is_data TYPE zif_abapgit_persistence=>ty_content RETURNING VALUE(rs_expl) TYPE ty_explanation RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_db_entry DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler . INTERFACES zif_abapgit_gui_renderable . INTERFACES zif_abapgit_gui_page_title . CLASS-METHODS create IMPORTING !is_key TYPE zif_abapgit_persistence=>ty_content !iv_edit_mode TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !is_key TYPE zif_abapgit_persistence=>ty_content !iv_edit_mode TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_action, update TYPE string VALUE 'update', switch_mode TYPE string VALUE 'switch_mode', END OF c_action . CONSTANTS c_edit_form_id TYPE string VALUE `db_form`. CONSTANTS c_css_url TYPE string VALUE 'css/page_db_entry.css'. DATA ms_key TYPE zif_abapgit_persistence=>ty_content. DATA mv_edit_mode TYPE abap_bool. METHODS register_stylesheet RAISING zcx_abapgit_exception. METHODS render_view IMPORTING iv_raw_db_value TYPE zif_abapgit_persistence=>ty_content-data_str ii_html TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS render_edit IMPORTING iv_raw_db_value TYPE zif_abapgit_persistence=>ty_content-data_str ii_html TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS render_header IMPORTING ii_html TYPE REF TO zif_abapgit_html io_toolbar TYPE REF TO zcl_abapgit_html_toolbar. METHODS build_toolbar RETURNING VALUE(ro_toolbar) TYPE REF TO zcl_abapgit_html_toolbar. CLASS-METHODS render_entry_tag IMPORTING is_key TYPE zif_abapgit_persistence=>ty_content RETURNING VALUE(rv_html) TYPE string. CLASS-METHODS dbcontent_decode IMPORTING io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(rs_content) TYPE zif_abapgit_persistence=>ty_content RAISING zcx_abapgit_exception . CLASS-METHODS do_update IMPORTING is_content TYPE zif_abapgit_persistence=>ty_content RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_gui_page_addofflin DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, name TYPE string VALUE 'name', package TYPE string VALUE 'package', folder_logic TYPE string VALUE 'folder_logic', labels TYPE string VALUE 'labels', ignore_subpackages TYPE string VALUE 'ignore_subpackages', main_lang_only TYPE string VALUE 'main_lang_only', abap_lang_vers TYPE string VALUE 'abap_lang_vers', END OF c_id . CONSTANTS: BEGIN OF c_event, choose_package TYPE string VALUE 'choose-package', choose_labels TYPE string VALUE 'choose-labels', create_package TYPE string VALUE 'create-package', add_offline_repo TYPE string VALUE 'add-repo-offline', END OF c_event . DATA mo_form TYPE REF TO zcl_abapgit_html_form . DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . METHODS validate_form IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form . METHODS choose_labels RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_addonline DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, url TYPE string VALUE 'url', package TYPE string VALUE 'package', branch_name TYPE string VALUE 'branch_name', display_name TYPE string VALUE 'display_name', labels TYPE string VALUE 'labels', folder_logic TYPE string VALUE 'folder_logic', ignore_subpackages TYPE string VALUE 'ignore_subpackages', main_lang_only TYPE string VALUE 'main_lang_only', abap_lang_vers TYPE string VALUE 'abap_lang_vers', END OF c_id. CONSTANTS: BEGIN OF c_event, choose_package TYPE string VALUE 'choose-package', create_package TYPE string VALUE 'create-package', choose_branch TYPE string VALUE 'choose-branch', choose_labels TYPE string VALUE 'choose-labels', add_online_repo TYPE string VALUE 'add-repo-online', END OF c_event. DATA mo_form TYPE REF TO zcl_abapgit_html_form . DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . METHODS validate_form IMPORTING io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. METHODS choose_labels RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_bckg DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler . INTERFACES zif_abapgit_gui_renderable . CLASS-METHODS create IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, mode_selection TYPE string VALUE 'mode_selection', method TYPE string VALUE 'method', authentication TYPE string VALUE 'authentication', username TYPE string VALUE 'username', password TYPE string VALUE 'password', mode_settings TYPE string VALUE 'mode_settings', settings TYPE string VALUE 'settings', END OF c_id . CONSTANTS: BEGIN OF c_event, run_now TYPE string VALUE 'run_now', save TYPE string VALUE 'save', END OF c_event . DATA mo_form TYPE REF TO zcl_abapgit_html_form . DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . DATA mo_repo TYPE REF TO zcl_abapgit_repo . DATA mv_settings_count TYPE i . METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form RAISING zcx_abapgit_exception . METHODS read_settings RETURNING VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS read_persist RETURNING VALUE(rs_persist) TYPE zcl_abapgit_persist_background=>ty_background RAISING zcx_abapgit_exception . METHODS save_settings RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_gui_page_sett_glob DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, proxy_settings TYPE string VALUE 'proxy_settings', proxy_url TYPE string VALUE 'proxy_url', proxy_port TYPE string VALUE 'proxy_port', proxy_auth TYPE string VALUE 'proxy_auth', proxy_bypass TYPE string VALUE 'proxy_bypass', commit_settings TYPE string VALUE 'commit_settings', commitmsg_comment_length TYPE string VALUE 'commitmsg_comment_length', commitmsg_comment_deflt TYPE string VALUE 'commitmsg_comment_deflt', commitmsg_body_size TYPE string VALUE 'commitmsg_body_size', commitmsg_hide_author TYPE string VALUE 'commitmsg_hide_author', devint_settings TYPE string VALUE 'devint_settings', run_critical_tests TYPE string VALUE 'run_critical_tests', experimental_features TYPE string VALUE 'experimental_features', activate_wo_popup TYPE string VALUE 'activate_wo_popup', END OF c_id. CONSTANTS: BEGIN OF c_event, proxy_bypass TYPE string VALUE 'proxy_bypass', save TYPE string VALUE 'save', END OF c_event. DATA mo_form TYPE REF TO zcl_abapgit_html_form. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. DATA mo_settings TYPE REF TO zcl_abapgit_settings. METHODS validate_form IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. METHODS read_settings RETURNING VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS save_settings RAISING zcx_abapgit_exception. CLASS-METHODS read_proxy_bypass IMPORTING io_form_data TYPE REF TO zcl_abapgit_string_map io_settings TYPE REF TO zcl_abapgit_settings RAISING zcx_abapgit_exception. METHODS save_proxy_bypass RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_info DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler . INTERFACES zif_abapgit_gui_renderable . CLASS-METHODS create IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_stats, measure TYPE string, local TYPE i, remote TYPE i, END OF ty_stats . TYPES: BEGIN OF ty_infos, size TYPE p LENGTH 16 DECIMALS 0, line TYPE p LENGTH 16 DECIMALS 0, sloc TYPE p LENGTH 16 DECIMALS 0, END OF ty_infos . CONSTANTS: BEGIN OF c_id, info TYPE string VALUE 'info', created_by TYPE string VALUE 'created_by', created_at TYPE string VALUE 'created_at', deserialized_by TYPE string VALUE 'deserialized_by', deserialized_at TYPE string VALUE 'deserialized_at', stats TYPE string VALUE 'stats', stats_table TYPE string VALUE 'stats_table', END OF c_id . DATA mo_form TYPE REF TO zcl_abapgit_html_form . DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . DATA mo_repo TYPE REF TO zcl_abapgit_repo . DATA: mt_stats TYPE STANDARD TABLE OF ty_stats WITH KEY measure . METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form RAISING zcx_abapgit_exception . METHODS read_settings RAISING zcx_abapgit_exception . METHODS read_stats RAISING zcx_abapgit_exception . METHODS read_stats_files EXPORTING !et_local TYPE zif_abapgit_definitions=>ty_files_item_tt !et_remote TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception . METHODS read_stats_state RAISING zcx_abapgit_exception . METHODS read_stats_size_lines_sloc IMPORTING !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt !it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt EXPORTING !et_local_items TYPE zif_abapgit_definitions=>ty_items_tt !et_remote_items TYPE zif_abapgit_definitions=>ty_items_tt RAISING zcx_abapgit_exception . METHODS read_stats_file IMPORTING !is_file TYPE zif_abapgit_git_definitions=>ty_file RETURNING VALUE(rs_info) TYPE ty_infos . METHODS read_stats_objects CHANGING !ct_local_items TYPE zif_abapgit_definitions=>ty_items_tt !ct_remote_items TYPE zif_abapgit_definitions=>ty_items_tt RAISING zcx_abapgit_exception . METHODS format_user IMPORTING !iv_username TYPE syuname RETURNING VALUE(rv_user) TYPE string . METHODS format_timestamp IMPORTING !iv_timestamp TYPE timestampl RETURNING VALUE(rv_timestamp) TYPE string . METHODS format_size IMPORTING !iv_size TYPE i RETURNING VALUE(rv_size) TYPE string . ENDCLASS. CLASS zcl_abapgit_gui_page_sett_locl DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler . INTERFACES zif_abapgit_gui_renderable . CLASS-METHODS create IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. DATA mo_popup_picklist TYPE REF TO zcl_abapgit_gui_picklist. CONSTANTS: BEGIN OF c_id, local TYPE string VALUE 'local', display_name TYPE string VALUE 'display_name', transport_request TYPE string VALUE 'transport_request', customizing_request TYPE string VALUE 'customizing_request', labels TYPE string VALUE 'labels', ignore_subpackages TYPE string VALUE 'ignore_subpackages', write_protected TYPE string VALUE 'write_protected', only_local_objects TYPE string VALUE 'only_local_objects', main_language_only TYPE string VALUE 'main_language_only', checks TYPE string VALUE 'checks', code_inspector_check_variant TYPE string VALUE 'code_inspector_check_variant', block_commit TYPE string VALUE 'block_commit', flow TYPE string VALUE 'flow', END OF c_id . CONSTANTS: BEGIN OF c_event, save TYPE string VALUE 'save', choose_transport_request TYPE string VALUE 'choose_transport_request', choose_customizing_request TYPE string VALUE 'choose_customizing_request', choose_labels TYPE string VALUE 'choose-labels', choose_check_variant TYPE string VALUE 'choose_check_variant', END OF c_event . DATA mo_form TYPE REF TO zcl_abapgit_html_form . DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . DATA mo_repo TYPE REF TO zcl_abapgit_repo . DATA ms_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings . METHODS validate_form IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form RAISING zcx_abapgit_exception . METHODS read_settings RETURNING VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS save_settings RAISING zcx_abapgit_exception . METHODS choose_labels RAISING zcx_abapgit_exception . METHODS choose_check_variant IMPORTING iv_is_return TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . METHODS choose_transport_request RAISING zcx_abapgit_exception . METHODS choose_customizing_request RAISING zcx_abapgit_exception . METHODS is_customizing_included RETURNING VALUE(rv_result) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS handle_picklist_state RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_gui_page_sett_pers DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, startup TYPE string VALUE 'startup', show_default_repo TYPE string VALUE 'show_default_repo', ui TYPE string VALUE 'ui', ui_theme TYPE string VALUE 'ui_theme', icon_scaling TYPE string VALUE 'icon_scaling', max_lines TYPE string VALUE 'max_lines', interaction TYPE string VALUE 'interaction', adt_jump_enabled TYPE string VALUE 'adt_jump_enabled', link_hints_enabled TYPE string VALUE 'link_hints_enabled', link_hint_key TYPE string VALUE 'link_hint_key', hotkeys TYPE string VALUE 'hotkeys', resources TYPE string VALUE 'resources', parallel_proc_disabled TYPE string VALUE 'parallel_proc_disabled', hide_sapgui_hint TYPE string VALUE 'hide_sapgui_hint', activate_wo_popup TYPE string VALUE 'activate_wo_popup', label_colors TYPE string VALUE 'label_colors', END OF c_id. CONSTANTS: BEGIN OF c_event, save TYPE string VALUE 'save', END OF c_event. DATA mo_form TYPE REF TO zcl_abapgit_html_form. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. DATA mo_settings TYPE REF TO zcl_abapgit_settings. DATA ms_settings TYPE zif_abapgit_definitions=>ty_s_user_settings. METHODS validate_form IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. METHODS read_settings RETURNING VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS save_settings RAISING zcx_abapgit_exception. METHODS render_repo_labels_help_hint RETURNING VALUE(rv_html) TYPE string. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_remo DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler . INTERFACES zif_abapgit_gui_renderable . INTERFACES zif_abapgit_gui_hotkeys. CLASS-METHODS create IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_head_type TYPE c LENGTH 1, BEGIN OF ty_remote_settings, offline TYPE zif_abapgit_persistence=>ty_repo-offline, url TYPE zif_abapgit_persistence=>ty_repo-url, branch TYPE zif_abapgit_git_definitions=>ty_git_branch-name, tag TYPE zif_abapgit_git_definitions=>ty_git_tag-name, commit TYPE zif_abapgit_git_definitions=>ty_commit-sha1, pull_request TYPE string, head_type TYPE ty_head_type, switched_origin TYPE zif_abapgit_persistence=>ty_repo-switched_origin, END OF ty_remote_settings. CONSTANTS: BEGIN OF c_repo_type, online TYPE string VALUE 'Online Repository', offline TYPE string VALUE 'Offline Repository', END OF c_repo_type. CONSTANTS: BEGIN OF c_head_types, branch TYPE ty_head_type VALUE 'B', tag TYPE ty_head_type VALUE 'T', commit TYPE ty_head_type VALUE 'C', pull_request TYPE ty_head_type VALUE 'P', END OF c_head_types. CONSTANTS: BEGIN OF c_id, general TYPE string VALUE 'general', repo_type TYPE string VALUE 'repo_type', offline TYPE string VALUE 'offline', url TYPE string VALUE 'url', head_group TYPE string VALUE 'head_group', branch TYPE string VALUE 'branch', tag TYPE string VALUE 'tag', commit TYPE string VALUE 'commit', pull_request TYPE string VALUE 'pull_request', head_type TYPE string VALUE 'head_type', END OF c_id. CONSTANTS: BEGIN OF c_event, save TYPE string VALUE 'save', switch TYPE string VALUE 'switch', choose_url TYPE string VALUE 'choose_url', choose_branch TYPE string VALUE 'choose_branch', choose_tag TYPE string VALUE 'choose_tag', choose_commit TYPE string VALUE 'choose_commit', choose_pull_request TYPE string VALUE 'choose_pull_request', change_head_type TYPE string VALUE 'change_head_type', END OF c_event . DATA mo_repo TYPE REF TO zcl_abapgit_repo . DATA ms_settings_snapshot TYPE ty_remote_settings. DATA mo_form TYPE REF TO zcl_abapgit_html_form . DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . DATA mv_refresh_on_back TYPE abap_bool. DATA mv_offline_switch_saved_url TYPE string. DATA mo_popup_picklist TYPE REF TO zcl_abapgit_gui_picklist. METHODS get_remote_settings_from_repo IMPORTING io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(rs_settings) TYPE ty_remote_settings RAISING zcx_abapgit_exception. METHODS get_remote_settings_from_form IMPORTING io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(rs_settings) TYPE ty_remote_settings RAISING zcx_abapgit_exception. METHODS get_form_schema IMPORTING io_existing_form_data TYPE REF TO zcl_abapgit_string_map OPTIONAL RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form RAISING zcx_abapgit_exception. METHODS initialize_form_data RETURNING VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS prepare_for_compare IMPORTING io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS check_protection RAISING zcx_abapgit_exception. METHODS validate_form IMPORTING io_form_data TYPE REF TO zcl_abapgit_string_map iv_connection_check TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS save_settings RAISING zcx_abapgit_exception. METHODS choose_url RETURNING VALUE(rv_url) TYPE string RAISING zcx_abapgit_exception. METHODS choose_branch IMPORTING iv_is_return TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception. METHODS choose_tag IMPORTING iv_is_return TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception. METHODS choose_pr IMPORTING iv_is_return TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception. METHODS choose_commit RETURNING VALUE(rv_commit) TYPE ty_remote_settings-commit RAISING zcx_abapgit_exception. METHODS switch_online_offline RAISING zcx_abapgit_exception. METHODS switch_to_branch_tag IMPORTING !iv_name TYPE string OPTIONAL RAISING zcx_abapgit_exception. METHODS switch_to_commit IMPORTING !iv_revert TYPE abap_bool DEFAULT abap_false !iv_commit TYPE ty_remote_settings-commit OPTIONAL RAISING zcx_abapgit_exception. METHODS switch_to_pull_req IMPORTING !iv_revert TYPE abap_bool DEFAULT abap_false !iv_pull TYPE string OPTIONAL RAISING zcx_abapgit_exception. METHODS handle_picklist_state RAISING zcx_abapgit_exception. METHODS render_content RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_repo DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler . INTERFACES zif_abapgit_gui_renderable . CLASS-METHODS create IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS constructor IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, dot TYPE string VALUE 'dot', file_system TYPE string VALUE 'file_system', abap_system TYPE string VALUE 'abap_system', name TYPE string VALUE 'name', i18n TYPE string VALUE 'i18n', main_language TYPE string VALUE 'main_language', i18n_langs TYPE string VALUE 'i18n_langs', use_lxe TYPE string VALUE 'use_lxe', starting_folder TYPE string VALUE 'starting_folder', folder_logic TYPE string VALUE 'folder_logic', ignore TYPE string VALUE 'ignore', requirements TYPE string VALUE 'requirements', version_constant TYPE string VALUE 'version_constant', version_value TYPE string VALUE 'version_value', abap_langu_vers TYPE string VALUE 'abap_langu_vers', original_system TYPE string VALUE 'original_system', END OF c_id. CONSTANTS: BEGIN OF c_event, save TYPE string VALUE 'save', END OF c_event . CONSTANTS c_empty_rows TYPE i VALUE 2 ##NO_TEXT. DATA mo_form TYPE REF TO zcl_abapgit_html_form . DATA mo_form_data TYPE REF TO zcl_abapgit_string_map . DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map . DATA mo_repo TYPE REF TO zcl_abapgit_repo . DATA mv_requirements_count TYPE i . METHODS validate_form IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS validate_version_constant IMPORTING !iv_version_constant TYPE string RAISING zcx_abapgit_exception . METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form RAISING zcx_abapgit_exception . METHODS read_settings RETURNING VALUE(ro_form_data) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS save_settings RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_gui_page_commit DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online !io_stage TYPE REF TO zcl_abapgit_stage !iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result DEFAULT zif_abapgit_definitions=>c_sci_result-no_run RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online !io_stage TYPE REF TO zcl_abapgit_stage !iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, committer TYPE string VALUE 'committer', committer_name TYPE string VALUE 'committer_name', committer_email TYPE string VALUE 'committer_email', message TYPE string VALUE 'message', comment TYPE string VALUE 'comment', body TYPE string VALUE 'body', author TYPE string VALUE 'author', author_name TYPE string VALUE 'author_name', author_email TYPE string VALUE 'author_email', new_branch_name TYPE string VALUE 'new_branch_name', END OF c_id. CONSTANTS: BEGIN OF c_event, commit TYPE string VALUE 'commit', END OF c_event. DATA mo_form TYPE REF TO zcl_abapgit_html_form. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. DATA mo_settings TYPE REF TO zcl_abapgit_settings. DATA mo_repo TYPE REF TO zcl_abapgit_repo_online. DATA mo_stage TYPE REF TO zcl_abapgit_stage. DATA mt_stage TYPE zif_abapgit_definitions=>ty_stage_tt. DATA ms_commit TYPE zif_abapgit_services_git=>ty_commit_fields. DATA mv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result. METHODS render_stage_summary RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS render_stage_details RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS validate_form IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. METHODS get_defaults RAISING zcx_abapgit_exception. METHODS get_committer_name RETURNING VALUE(rv_user) TYPE string RAISING zcx_abapgit_exception. METHODS get_committer_email RETURNING VALUE(rv_email) TYPE string RAISING zcx_abapgit_exception. METHODS get_comment_default RETURNING VALUE(rv_text) TYPE string. METHODS get_comment_object IMPORTING !it_stage TYPE zif_abapgit_definitions=>ty_stage_tt RETURNING VALUE(rv_text) TYPE string. METHODS get_comment_file IMPORTING !it_stage TYPE zif_abapgit_definitions=>ty_stage_tt RETURNING VALUE(rv_text) TYPE string. METHODS branch_name_to_internal IMPORTING iv_branch_name TYPE string RETURNING VALUE(rv_new_branch_name) TYPE string. ENDCLASS. CLASS zcl_abapgit_gui_page_data DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES: zif_abapgit_gui_event_handler, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception. PROTECTED SECTION. CONSTANTS: BEGIN OF c_event, add TYPE string VALUE 'add', update TYPE string VALUE 'update', remove TYPE string VALUE 'remove', add_via_transport TYPE string VALUE 'add_via_transport', END OF c_event. CONSTANTS: BEGIN OF c_id, table TYPE string VALUE 'table', where TYPE string VALUE 'where', skip_initial TYPE string VALUE 'skip_initial', END OF c_id. DATA mi_config TYPE REF TO zif_abapgit_data_config. PRIVATE SECTION. DATA mo_repo TYPE REF TO zcl_abapgit_repo . CLASS-METHODS concatenated_key_to_where IMPORTING !iv_table TYPE tabname !iv_tabkey TYPE clike RETURNING VALUE(rv_where) TYPE string RAISING zcx_abapgit_exception. METHODS add_via_transport RAISING zcx_abapgit_exception . METHODS build_where IMPORTING !io_map TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(rt_where) TYPE string_table . METHODS render_add RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_existing RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS event_add IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RAISING zcx_abapgit_exception . METHODS event_remove IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RAISING zcx_abapgit_exception . METHODS event_update IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_gui_page_debuginfo DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler . INTERFACES zif_abapgit_gui_renderable . CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. CONSTANTS c_exit_standalone TYPE syrepid VALUE 'ZABAPGIT_USER_EXIT' ##NO_TEXT. CONSTANTS c_exit_class TYPE c LENGTH 30 VALUE 'ZCL_ABAPGIT_USER_EXIT' ##NO_TEXT. CONSTANTS c_exit_interface TYPE c LENGTH 30 VALUE 'ZIF_ABAPGIT_EXIT' ##NO_TEXT. CONSTANTS: BEGIN OF c_action, save TYPE string VALUE 'save', END OF c_action. DATA mv_html TYPE string . CLASS-METHODS build_toolbar RETURNING VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. METHODS render_debug_info RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_exit_info RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_exit_info_methods IMPORTING !it_source TYPE string_table !iv_clsname TYPE seoclsname OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_supported_object_types RETURNING VALUE(rv_html) TYPE string . METHODS render_scripts RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS get_jump_object IMPORTING !iv_obj_type TYPE csequence DEFAULT 'CLAS' !iv_obj_name TYPE csequence RETURNING VALUE(rv_html) TYPE string . ENDCLASS. CLASS zcl_abapgit_gui_page_diff_base DEFINITION INHERITING FROM zcl_abapgit_gui_component CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_hotkeys. INTERFACES zif_abapgit_gui_menu_provider. INTERFACES zif_abapgit_gui_renderable. TYPES: BEGIN OF ty_file_diff, path TYPE string, filename TYPE string, obj_type TYPE string, obj_name TYPE string, lstate TYPE c LENGTH 1, rstate TYPE c LENGTH 1, fstate TYPE c LENGTH 1, " FILE state - Abstraction for shorter ifs o_diff TYPE REF TO zcl_abapgit_diff, changed_by TYPE syuname, type TYPE string, END OF ty_file_diff. TYPES: ty_file_diffs TYPE STANDARD TABLE OF ty_file_diff WITH NON-UNIQUE DEFAULT KEY WITH NON-UNIQUE SORTED KEY secondary COMPONENTS path filename. CONSTANTS: BEGIN OF c_fstate, local TYPE c LENGTH 1 VALUE 'L', remote TYPE c LENGTH 1 VALUE 'R', both TYPE c LENGTH 1 VALUE 'B', END OF c_fstate. METHODS constructor IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. CONSTANTS: BEGIN OF c_actions, toggle_unified TYPE string VALUE 'toggle_unified', toggle_hide_diffs TYPE string VALUE 'toggle_hide_diffs', toggle_hidden_chars TYPE string VALUE 'toggle_hidden_chars', toggle_ignore_indent TYPE string VALUE 'toggle_ignore_indent', toggle_ignore_comments TYPE string VALUE 'toggle_ignore_comments', toggle_ignore_case TYPE string VALUE 'toggle_ignore_case', refresh_prefix TYPE string VALUE 'refresh', refresh_all TYPE string VALUE 'refresh_all', refresh_local TYPE string VALUE 'refresh_local', refresh_local_object TYPE string VALUE 'refresh_local_object', END OF c_actions , BEGIN OF c_action_texts, refresh_all TYPE string VALUE `Refresh All`, refresh_local TYPE string VALUE `Refresh Local`, END OF c_action_texts, BEGIN OF c_action_titles, refresh_local TYPE string VALUE `Refresh all local objects, without refreshing the remote`, refresh_all TYPE string VALUE `Complete refresh of all objects, local and remote`, END OF c_action_titles. DATA mv_unified TYPE abap_bool VALUE abap_true ##NO_TEXT. DATA mo_repo TYPE REF TO zcl_abapgit_repo . DATA mt_diff_files TYPE ty_file_diffs . CLASS-METHODS get_page_layout RETURNING VALUE(rv_page_layout) TYPE string. METHODS get_normalized_fname_with_path IMPORTING !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 add_menu_end IMPORTING !io_menu TYPE REF TO zcl_abapgit_html_toolbar . METHODS calculate_diff IMPORTING !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL RAISING zcx_abapgit_exception . METHODS add_menu_begin IMPORTING !io_menu TYPE REF TO zcl_abapgit_html_toolbar . METHODS render_table_head_non_unified IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_diff TYPE ty_file_diff . METHODS render_beacon_begin_of_row IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_diff TYPE ty_file_diff . METHODS render_diff_head_after_state IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_diff TYPE ty_file_diff . METHODS insert_nav RETURNING VALUE(rv_insert_nav) TYPE abap_bool . METHODS render_line_split_row IMPORTING !ii_html TYPE REF TO zif_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 . 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 . METHODS is_refresh IMPORTING iv_action TYPE string RETURNING VALUE(rv_is_refrseh) TYPE abap_bool. METHODS modify_files_before_diff_calc IMPORTING it_diff_files_old TYPE ty_file_diffs RETURNING VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_stage_tt. METHODS add_view_sub_menu IMPORTING io_menu TYPE REF TO zcl_abapgit_html_toolbar . PRIVATE SECTION. TYPES: BEGIN OF ty_view, hide_diffs TYPE abap_bool, hidden_chars TYPE abap_bool, ignore_indent TYPE abap_bool, ignore_comments TYPE abap_bool, ignore_case TYPE abap_bool, END OF ty_view. DATA mt_delayed_lines TYPE zif_abapgit_definitions=>ty_diffs_tt . DATA mv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key . DATA mv_seed TYPE string . " Unique page id to bind JS sessionStorage DATA ms_view TYPE ty_view. METHODS render_diff IMPORTING !is_diff TYPE ty_file_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_diff_head IMPORTING !is_diff TYPE ty_file_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_table_head IMPORTING !is_diff TYPE ty_file_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_beacon IMPORTING !is_diff_line TYPE zif_abapgit_definitions=>ty_diff !is_diff TYPE ty_file_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_line_no_diffs RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_line_split IMPORTING !is_diff_line TYPE zif_abapgit_definitions=>ty_diff !iv_filename TYPE string !iv_fstate TYPE char1 !iv_index TYPE sy-tabix RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_line_unified IMPORTING !is_diff_line TYPE zif_abapgit_definitions=>ty_diff OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS append_diff IMPORTING !it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt !it_local TYPE zif_abapgit_definitions=>ty_files_item_tt !is_status TYPE zif_abapgit_definitions=>ty_result RAISING zcx_abapgit_exception . METHODS is_binary IMPORTING !iv_d1 TYPE xstring !iv_d2 TYPE xstring RETURNING VALUE(rv_yes) 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 render_lines IMPORTING !is_diff TYPE ty_file_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_table_head_unified IMPORTING !ii_html TYPE REF TO zif_abapgit_html . METHODS render_scripts RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS is_file_requested IMPORTING it_files TYPE zif_abapgit_definitions=>ty_stage_tt is_status TYPE zif_abapgit_definitions=>ty_result RETURNING VALUE(rv_is_file_requested) TYPE abap_bool. METHODS has_diffs IMPORTING !it_diffs TYPE zif_abapgit_definitions=>ty_diffs_tt RETURNING VALUE(rv_has_diffs) TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_gui_page_diff DEFINITION INHERITING FROM zcl_abapgit_gui_page_diff_base CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS create IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_gui_page_ex_object DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, object_type TYPE string VALUE 'object_type', object_name TYPE string VALUE 'object_name', only_main TYPE string VALUE 'only_main', END OF c_id. CONSTANTS: BEGIN OF c_event, export TYPE string VALUE 'export', choose_object_type TYPE string VALUE 'choose-object-type', END OF c_event. DATA mo_form TYPE REF TO zcl_abapgit_html_form. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. METHODS export_object RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_ex_pckage DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, package TYPE string VALUE 'package', folder_logic TYPE string VALUE 'folder_logic', ignore_subpackages TYPE string VALUE 'ignore_subpackages', main_lang_only TYPE string VALUE 'main_lang_only', END OF c_id. CONSTANTS: BEGIN OF c_event, export_package TYPE string VALUE 'export-package', choose_package TYPE string VALUE 'choose-object-type', END OF c_event. DATA mo_form TYPE REF TO zcl_abapgit_html_form. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. METHODS export_package RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_merge DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES: zif_abapgit_gui_event_handler, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online iv_source TYPE string iv_target TYPE string RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online iv_source TYPE string iv_target TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mo_repo TYPE REF TO zcl_abapgit_repo_online. DATA mi_merge TYPE REF TO zif_abapgit_merge. CONSTANTS: BEGIN OF c_actions, merge TYPE string VALUE 'merge', res_conflicts TYPE string VALUE 'res_conflicts', END OF c_actions. METHODS show_file IMPORTING !it_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt !ii_html TYPE REF TO zif_abapgit_html !is_file TYPE zif_abapgit_git_definitions=>ty_expanded !is_result TYPE zif_abapgit_git_definitions=>ty_expanded. ENDCLASS. CLASS zcl_abapgit_gui_page_merge_res DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES: zif_abapgit_gui_event_handler, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online io_merge_page TYPE REF TO zcl_abapgit_gui_page_merge io_merge TYPE REF TO zif_abapgit_merge RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online io_merge_page TYPE REF TO zcl_abapgit_gui_page_merge io_merge TYPE REF TO zif_abapgit_merge RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_file_diff, path TYPE string, filename TYPE string, lstate TYPE char1, rstate TYPE char1, fstate TYPE char1, " FILE state - Abstraction for shorter ifs o_diff TYPE REF TO zcl_abapgit_diff, changed_by TYPE syuname, type TYPE string, END OF ty_file_diff . CONSTANTS: BEGIN OF c_actions, toggle_mode TYPE string VALUE 'toggle_mode' ##NO_TEXT, apply_merge TYPE string VALUE 'apply_merge' ##NO_TEXT, apply_source TYPE string VALUE 'apply_source' ##NO_TEXT, apply_target TYPE string VALUE 'apply_target' ##NO_TEXT, cancel TYPE string VALUE 'cancel' ##NO_TEXT, END OF c_actions . CONSTANTS: BEGIN OF c_merge_mode, selection TYPE string VALUE 'selection' ##NO_TEXT, merge TYPE string VALUE 'merge' ##NO_TEXT, END OF c_merge_mode . DATA mo_merge TYPE REF TO zif_abapgit_merge . DATA mo_merge_page TYPE REF TO zcl_abapgit_gui_page_merge . DATA mo_repo TYPE REF TO zcl_abapgit_repo_online . DATA ms_diff_file TYPE ty_file_diff . DATA mv_current_conflict_index TYPE sy-tabix . DATA mv_merge_mode TYPE string . DATA mt_conflicts TYPE zif_abapgit_merge=>ty_merge_conflict_tt . METHODS apply_merged_content IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RAISING zcx_abapgit_exception . METHODS is_binary IMPORTING !iv_d1 TYPE xstring !iv_d2 TYPE xstring RETURNING VALUE(rv_yes) TYPE abap_bool . METHODS render_beacon IMPORTING !is_diff_line TYPE zif_abapgit_definitions=>ty_diff !is_diff TYPE ty_file_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_diff IMPORTING !is_diff TYPE ty_file_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_diff_head IMPORTING !is_diff TYPE ty_file_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_lines IMPORTING !is_diff TYPE ty_file_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_line_split IMPORTING !is_diff_line TYPE zif_abapgit_definitions=>ty_diff RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_table_head RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS resolve_diff RAISING zcx_abapgit_exception . METHODS toggle_merge_mode . ENDCLASS. CLASS zcl_abapgit_gui_page_merge_sel DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING !ii_repo TYPE REF TO zif_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !ii_repo TYPE REF TO zif_abapgit_repo RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, branches TYPE string VALUE 'branches', source TYPE string VALUE 'source', target TYPE string VALUE 'target', END OF c_id. CONSTANTS: BEGIN OF c_event, merge TYPE string VALUE 'merge', END OF c_event. DATA mo_form TYPE REF TO zcl_abapgit_html_form. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. DATA mo_repo TYPE REF TO zcl_abapgit_repo_online. DATA mt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. METHODS read_branches RAISING zcx_abapgit_exception. METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_patch DEFINITION INHERITING FROM zcl_abapgit_gui_page_diff_base CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS create IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !is_file TYPE zif_abapgit_git_definitions=>ty_file OPTIONAL !is_object TYPE zif_abapgit_definitions=>ty_item OPTIONAL !it_files TYPE zif_abapgit_definitions=>ty_stage_tt OPTIONAL 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. METHODS: zif_abapgit_gui_event_handler~on_event REDEFINITION, zif_abapgit_gui_hotkeys~get_hotkey_actions REDEFINITION, zif_abapgit_gui_renderable~render REDEFINITION. PROTECTED SECTION. METHODS: add_menu_begin REDEFINITION, add_menu_end REDEFINITION, insert_nav REDEFINITION, refresh REDEFINITION, render_beacon_begin_of_row REDEFINITION, render_diff_head_after_state REDEFINITION, render_line_split_row REDEFINITION, render_table_head_non_unified REDEFINITION. PRIVATE SECTION. TYPES ty_patch_action TYPE string . CONSTANTS: BEGIN OF c_patch_actions, stage TYPE string VALUE 'patch_stage', END OF c_patch_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 mo_stage TYPE REF TO zcl_abapgit_stage . DATA mv_section_count TYPE i . DATA mv_pushed TYPE abap_bool . DATA mo_repo_online TYPE REF TO zcl_abapgit_repo_online . METHODS render_patch IMPORTING !ii_html TYPE REF TO zif_abapgit_html !iv_filename TYPE string !is_diff_line TYPE zif_abapgit_definitions=>ty_diff !iv_index TYPE sy-tabix RAISING zcx_abapgit_exception . METHODS render_patch_head IMPORTING !ii_html TYPE REF TO zif_abapgit_html !is_diff TYPE ty_file_diff . METHODS start_staging IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RAISING zcx_abapgit_exception . METHODS apply_patch_from_form_fields IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RAISING zcx_abapgit_exception . METHODS restore_patch_flags IMPORTING !it_diff_files_old TYPE ty_file_diffs RAISING zcx_abapgit_exception . METHODS add_to_stage RAISING zcx_abapgit_exception . METHODS apply_patch_all IMPORTING !iv_patch TYPE string !iv_patch_flag TYPE abap_bool 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 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 . CLASS-METHODS is_patch_line_possible IMPORTING !is_diff_line TYPE zif_abapgit_definitions=>ty_diff RETURNING VALUE(rv_is_patch_line_possible) TYPE abap_bool . METHODS render_scripts RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_gui_page_pull DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_menu_provider. INTERFACES zif_abapgit_gui_renderable. CONSTANTS: BEGIN OF c_id, transport_request TYPE string VALUE 'transport_request', END OF c_id . CONSTANTS: BEGIN OF c_action, pull TYPE string VALUE 'pull', refresh TYPE string VALUE 'refresh', choose_tr TYPE string VALUE 'choose_tr', END OF c_action. CLASS-METHODS create IMPORTING io_repo TYPE REF TO zcl_abapgit_repo iv_trkorr TYPE trkorr OPTIONAL ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING io_repo TYPE REF TO zcl_abapgit_repo iv_trkorr TYPE trkorr ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. DATA mo_repo TYPE REF TO zcl_abapgit_repo. DATA mi_obj_filter TYPE REF TO zif_abapgit_object_filter. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA ms_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks. METHODS form RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form RAISING zcx_abapgit_exception. METHODS choose_transport_request RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_gui_page_repo_over DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES: zif_abapgit_gui_event_handler, zif_abapgit_gui_hotkeys, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING !iv_only_favorites TYPE abap_bool OPTIONAL RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !iv_only_favorites TYPE abap_bool OPTIONAL RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_overview, favorite TYPE string, "! True for offline, false for online repo type TYPE string, key TYPE zif_abapgit_persistence=>ty_value, name TYPE string, labels TYPE string_table, url TYPE string, package TYPE devclass, branch TYPE string, created_by TYPE syuname, created_at TYPE string, created_at_raw TYPE timestampl, deserialized_by TYPE syuname, deserialized_at TYPE string, deserialized_at_raw TYPE timestampl, write_protected TYPE abap_bool, flow TYPE abap_bool, END OF ty_overview, ty_overviews TYPE STANDARD TABLE OF ty_overview WITH NON-UNIQUE DEFAULT KEY. CONSTANTS: BEGIN OF c_action, select TYPE string VALUE 'select', apply_filter TYPE string VALUE 'apply_filter', label_filter TYPE string VALUE 'label_filter', END OF c_action, c_label_filter_prefix TYPE string VALUE `label:`, c_raw_field_suffix TYPE string VALUE `_RAW` ##NO_TEXT. DATA: mt_all_labels TYPE string_table, mo_label_colors TYPE REF TO zcl_abapgit_string_map. DATA ms_list_settings TYPE zif_abapgit_definitions=>ty_list_settings. METHODS set_order_by IMPORTING !iv_order_by TYPE string RAISING zcx_abapgit_exception. METHODS set_order_direction IMPORTING !iv_order_descending TYPE abap_bool RAISING zcx_abapgit_exception. METHODS set_filter IMPORTING it_postdata TYPE zif_abapgit_html_viewer=>ty_post_data RAISING zcx_abapgit_exception. METHODS: apply_filter CHANGING ct_overview TYPE ty_overviews, map_repo_list_to_overview IMPORTING it_repo_obj_list TYPE zif_abapgit_repo_srv=>ty_repo_list RETURNING VALUE(rt_overview) TYPE ty_overviews RAISING zcx_abapgit_exception, render_repo_list IMPORTING ii_html TYPE REF TO zif_abapgit_html it_overview TYPE ty_overviews RAISING zcx_abapgit_exception, render_table_header IMPORTING ii_html TYPE REF TO zif_abapgit_html, render_table_footer IMPORTING ii_html TYPE REF TO zif_abapgit_html, render_table_body IMPORTING ii_html TYPE REF TO zif_abapgit_html it_repo_list TYPE ty_overviews RAISING zcx_abapgit_exception, render_table_item IMPORTING ii_html TYPE REF TO zif_abapgit_html is_repo TYPE ty_overview RAISING zcx_abapgit_exception, render_header_bar IMPORTING ii_html TYPE REF TO zif_abapgit_html, render_header_label_list IMPORTING ii_html TYPE REF TO zif_abapgit_html, apply_order_by CHANGING ct_overview TYPE ty_overviews. METHODS prepare_overviews RETURNING VALUE(rt_overviews) TYPE ty_overviews RAISING zcx_abapgit_exception. METHODS render_scripts RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS render_action_toolbar RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html. METHODS render_filter_bar RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html. METHODS build_table_scheme RETURNING VALUE(rt_tab_scheme) TYPE zif_abapgit_definitions=>ty_col_spec_tt. METHODS collect_all_labels IMPORTING it_overview TYPE ty_overviews RETURNING VALUE(rt_list) TYPE string_table. METHODS render_filter_help_hint RETURNING VALUE(rv_html) TYPE string. METHODS save_settings RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_repo_view DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES: zif_abapgit_gui_event_handler, zif_abapgit_gui_hotkeys, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable. CONSTANTS: BEGIN OF c_actions, change_dir TYPE string VALUE 'change_dir' ##NO_TEXT, toggle_hide_files TYPE string VALUE 'toggle_hide_files' ##NO_TEXT, toggle_folders TYPE string VALUE 'toggle_folders' ##NO_TEXT, toggle_changes TYPE string VALUE 'toggle_changes' ##NO_TEXT, toggle_diff_first TYPE string VALUE 'toggle_diff_first ' ##NO_TEXT, display_more TYPE string VALUE 'display_more' ##NO_TEXT, go_data TYPE string VALUE 'go_data', go_unit TYPE string VALUE 'go_unit', END OF c_actions . CLASS-METHODS create IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. DATA mo_repo TYPE REF TO zcl_abapgit_repo . DATA mo_repo_aggregated_state TYPE REF TO zcl_abapgit_repo_item_state. DATA mv_connection_error TYPE abap_bool. DATA mv_cur_dir TYPE string . DATA mv_hide_files TYPE abap_bool . DATA mv_max_lines TYPE i . DATA mv_max_setting TYPE i . DATA mv_show_folders TYPE abap_bool . DATA mv_changes_only TYPE abap_bool . DATA mv_order_by TYPE string . DATA mv_order_descending TYPE abap_bool . DATA mv_diff_first TYPE abap_bool . DATA mv_key TYPE zif_abapgit_persistence=>ty_value . DATA mv_are_changes_recorded_in_tr TYPE abap_bool . METHODS render_head_line RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS build_view_dropdown RETURNING VALUE(ro_toolbar) TYPE REF TO zcl_abapgit_html_toolbar RAISING zcx_abapgit_exception . METHODS render_item IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item !iv_render_transports TYPE abap_bool RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_item_files IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_item_command IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_file_command IMPORTING !is_file TYPE zif_abapgit_definitions=>ty_repo_file RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS get_item_class IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item iv_is_object_row TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_html) TYPE string . METHODS render_item_transport IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_parent_dir RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS build_dir_jump_link IMPORTING !iv_path TYPE string RETURNING VALUE(rv_html) TYPE string . METHODS build_inactive_object_code IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item RETURNING VALUE(rv_inactive_html_code) TYPE string . METHODS build_srcsystem_code IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item RETURNING VALUE(rv_srcsystem_html_code) TYPE string . METHODS build_origlang_code IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item RETURNING VALUE(rv_html_code) TYPE string . METHODS open_in_main_language RAISING zcx_abapgit_exception . METHODS render_table_header RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_table_footer RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS apply_order_by CHANGING !ct_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt . METHODS build_branch_dropdown RETURNING VALUE(ro_branch_dropdown) TYPE REF TO zcl_abapgit_html_toolbar RAISING zcx_abapgit_exception . METHODS build_tag_dropdown RETURNING VALUE(ro_tag_dropdown) TYPE REF TO zcl_abapgit_html_toolbar RAISING zcx_abapgit_exception . METHODS build_advanced_dropdown RETURNING VALUE(ro_advanced_dropdown) TYPE REF TO zcl_abapgit_html_toolbar RAISING zcx_abapgit_exception . METHODS build_main_toolbar RETURNING VALUE(ro_toolbar) TYPE REF TO zcl_abapgit_html_toolbar RAISING zcx_abapgit_exception . METHODS render_scripts RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS is_repo_lang_logon_lang RETURNING VALUE(rv_repo_lang_is_logon_lang) TYPE abap_bool . METHODS render_item_changed_by IMPORTING !is_item TYPE zif_abapgit_definitions=>ty_repo_item RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS order_files CHANGING ct_files TYPE zif_abapgit_definitions=>ty_repo_file_tt. METHODS get_crossout IMPORTING !iv_authorization TYPE zif_abapgit_auth=>ty_authorization OPTIONAL !iv_protected TYPE abap_bool DEFAULT abap_false !iv_strong TYPE abap_bool DEFAULT abap_false PREFERRED PARAMETER iv_authorization RETURNING VALUE(rv_crossout) LIKE zif_abapgit_html=>c_html_opt-crossout. METHODS check_branch RAISING zcx_abapgit_exception. METHODS check_connection RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_run_bckg DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler . INTERFACES zif_abapgit_gui_renderable . CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS constructor RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. DATA: mt_text TYPE TABLE OF string. METHODS run. ENDCLASS. CLASS zcl_abapgit_gui_page_stage DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES: zif_abapgit_gui_event_handler, zif_abapgit_gui_hotkeys, zif_abapgit_gui_menu_provider, zif_abapgit_gui_renderable. CONSTANTS: BEGIN OF c_action, stage_refresh TYPE string VALUE 'stage_refresh', stage_all TYPE string VALUE 'stage_all', stage_commit TYPE string VALUE 'stage_commit', stage_filter TYPE string VALUE 'stage_filter', END OF c_action. CLASS-METHODS create IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online iv_seed TYPE string OPTIONAL iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result DEFAULT zif_abapgit_definitions=>c_sci_result-no_run ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL ii_force_refresh TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING io_repo TYPE REF TO zcl_abapgit_repo_online iv_seed TYPE string OPTIONAL iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result DEFAULT zif_abapgit_definitions=>c_sci_result-no_run ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL ii_force_refresh TYPE abap_bool DEFAULT abap_true RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_changed_by, item TYPE zif_abapgit_definitions=>ty_item, filename TYPE string, name TYPE syuname, END OF ty_changed_by . TYPES: ty_changed_by_tt TYPE SORTED TABLE OF ty_changed_by WITH UNIQUE KEY item filename. DATA mo_repo TYPE REF TO zcl_abapgit_repo_online . DATA ms_files TYPE zif_abapgit_definitions=>ty_stage_files . DATA mv_seed TYPE string . " Unique page id to bind JS sessionStorage DATA mv_filter_value TYPE string . DATA mv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result. DATA mi_obj_filter TYPE REF TO zif_abapgit_object_filter. METHODS check_selected IMPORTING !io_files TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS find_changed_by IMPORTING !it_files TYPE zif_abapgit_definitions=>ty_stage_files !it_transports TYPE zif_abapgit_cts_api=>ty_transport_list RETURNING VALUE(rt_changed_by) TYPE ty_changed_by_tt . METHODS find_transports IMPORTING !it_files TYPE zif_abapgit_definitions=>ty_stage_files RETURNING VALUE(rt_transports) TYPE zif_abapgit_cts_api=>ty_transport_list . METHODS render_list RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_file IMPORTING !iv_context TYPE string !is_file TYPE zif_abapgit_git_definitions=>ty_file !is_item TYPE zif_abapgit_definitions=>ty_item OPTIONAL !is_status TYPE zif_abapgit_definitions=>ty_result !iv_changed_by TYPE syuname OPTIONAL !iv_transport TYPE trkorr OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS render_actions RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS stage_selected IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING 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 RAISING zcx_abapgit_exception . METHODS get_page_patch IMPORTING !io_stage TYPE REF TO zcl_abapgit_stage RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS render_main_language_warning RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS count_default_files_to_commit RETURNING VALUE(rv_count) TYPE i . METHODS render_deferred_hidden_events RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . METHODS render_scripts RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception . METHODS init_files RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_gui_page_tags DEFINITION INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING !ii_repo TYPE REF TO zif_abapgit_repo RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !ii_repo TYPE REF TO zif_abapgit_repo RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, tag_group TYPE string VALUE 'tag_group', tag_type TYPE string VALUE 'tag_type', tags TYPE string VALUE 'tags', type TYPE string VALUE 'type', name TYPE string VALUE 'name', sha1 TYPE string VALUE 'sha1', anno_group TYPE string VALUE 'anno_group', tagger TYPE string VALUE 'tagger', tagger_name TYPE string VALUE 'tagger_name', tagger_email TYPE string VALUE 'tagger_email', message TYPE string VALUE 'message', body TYPE string VALUE 'body', END OF c_id. CONSTANTS: BEGIN OF c_event, create TYPE string VALUE 'create', choose_commit TYPE string VALUE 'choose_commit', change_type TYPE string VALUE 'change_type', END OF c_event. DATA mo_form TYPE REF TO zcl_abapgit_html_form. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. DATA mo_repo TYPE REF TO zcl_abapgit_repo_online. DATA mo_settings TYPE REF TO zcl_abapgit_settings. DATA ms_tag TYPE zif_abapgit_git_definitions=>ty_git_tag. METHODS get_form_schema IMPORTING io_form_data TYPE REF TO zcl_abapgit_string_map OPTIONAL RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form RAISING zcx_abapgit_exception. METHODS initialize_form_data RAISING zcx_abapgit_exception. METHODS get_tagger_name RETURNING VALUE(rv_user) TYPE string RAISING zcx_abapgit_exception. METHODS get_tagger_email RETURNING VALUE(rv_email) TYPE string RAISING zcx_abapgit_exception. METHODS validate_form IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS choose_commit RETURNING VALUE(rv_commit) TYPE zif_abapgit_git_definitions=>ty_commit-sha1 RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_gui_page_tutorial DEFINITION FINAL INHERITING FROM zcl_abapgit_gui_component CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS build_main_menu RETURNING VALUE(ro_menu) TYPE REF TO zcl_abapgit_html_toolbar. ENDCLASS. CLASS zcl_abapgit_popup_branch_list DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_render_item. INTERFACES zif_abapgit_html_popup. CLASS-METHODS create IMPORTING !iv_url TYPE string !iv_default_branch TYPE string OPTIONAL !iv_show_new_option TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_popup) TYPE REF TO zif_abapgit_html_popup. METHODS constructor IMPORTING !iv_url TYPE string !iv_default_branch TYPE string OPTIONAL !iv_show_new_option TYPE abap_bool DEFAULT abap_false. PRIVATE SECTION. DATA mv_repo_url TYPE string. DATA mv_default_branch TYPE string. DATA mv_show_new_option TYPE abap_bool. METHODS fetch_branch_list RETURNING VALUE(rt_branches) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_popup_code_insp DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_render_item . INTERFACES zif_abapgit_html_popup . CLASS-METHODS create RETURNING VALUE(ri_popup) TYPE REF TO zif_abapgit_html_popup . PROTECTED SECTION. PRIVATE SECTION. METHODS fetch_list RETURNING VALUE(rt_list) TYPE zif_abapgit_code_inspector=>ty_variants RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_popup_pull_request DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_render_item. INTERFACES zif_abapgit_html_popup. CLASS-METHODS create IMPORTING iv_url TYPE string RETURNING VALUE(ri_popup) TYPE REF TO zif_abapgit_html_popup. METHODS constructor IMPORTING iv_url TYPE string. PROTECTED SECTION. PRIVATE SECTION. DATA mv_repo_url TYPE string. METHODS fetch_pull_request_list RETURNING VALUE(rt_pulls) TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_popup_tag_list DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_gui_render_item. INTERFACES zif_abapgit_html_popup. CLASS-METHODS create IMPORTING iv_url TYPE string RETURNING VALUE(ri_popup) TYPE REF TO zif_abapgit_html_popup. METHODS constructor IMPORTING iv_url TYPE string. PRIVATE SECTION. DATA mv_repo_url TYPE string. METHODS fetch_tag_list RETURNING VALUE(rt_tags) TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_progress DEFINITION FINAL CREATE PROTECTED . PUBLIC SECTION. INTERFACES zif_abapgit_progress . CLASS-METHODS set_instance IMPORTING !ii_progress TYPE REF TO zif_abapgit_progress . CLASS-METHODS get_instance IMPORTING !iv_total TYPE i RETURNING VALUE(ri_progress) TYPE REF TO zif_abapgit_progress . PROTECTED SECTION. DATA mv_total TYPE i . CLASS-DATA gi_progress TYPE REF TO zif_abapgit_progress . METHODS calc_pct IMPORTING !iv_current TYPE i RETURNING VALUE(rv_pct) TYPE i . PRIVATE SECTION. DATA mv_cv_time_next TYPE sy-uzeit . DATA mv_cv_datum_next TYPE sy-datum . ENDCLASS. CLASS zcl_abapgit_gui_router DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. PROTECTED SECTION. PRIVATE SECTION. METHODS general_page_routing IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception . METHODS abapgit_services_actions IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception . METHODS db_actions IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception . CLASS-METHODS file_download IMPORTING !iv_package TYPE devclass !iv_xstr TYPE xstring RAISING zcx_abapgit_exception . METHODS git_services IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception . METHODS sap_gui_actions IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception . METHODS other_utilities IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception . METHODS zip_services IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception . METHODS repository_services IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rs_handled) TYPE zif_abapgit_gui_event_handler=>ty_handling_result RAISING zcx_abapgit_exception . METHODS get_page_diff IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS get_page_patch IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . METHODS get_page_stage IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event ii_obj_filter TYPE REF TO zif_abapgit_object_filter OPTIONAL RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception . CLASS-METHODS jump_object IMPORTING !iv_obj_type TYPE string !iv_obj_name TYPE string !iv_filename TYPE string !iv_sub_type TYPE string OPTIONAL !iv_sub_name TYPE string OPTIONAL !iv_line TYPE string OPTIONAL !iv_new_window TYPE string DEFAULT 'X' RAISING zcx_abapgit_exception . CLASS-METHODS jump_display_transport IMPORTING !iv_transport TYPE trkorr RAISING zcx_abapgit_exception . CLASS-METHODS jump_display_user IMPORTING !iv_username TYPE syuname RAISING zcx_abapgit_exception . METHODS call_browser IMPORTING !iv_url TYPE csequence RAISING zcx_abapgit_exception . METHODS call_transaction IMPORTING !iv_tcode TYPE csequence RAISING zcx_abapgit_exception . METHODS get_state_settings IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rv_state) TYPE i . METHODS get_state_diff IMPORTING !ii_event TYPE REF TO zif_abapgit_gui_event RETURNING VALUE(rv_state) TYPE i . METHODS main_page RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_services_abapgit DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CONSTANTS c_abapgit_repo TYPE string VALUE 'https://github.com/abapGit/abapGit' ##NO_TEXT. CONSTANTS c_abapgit_homepage TYPE string VALUE 'https://www.abapgit.org' ##NO_TEXT. CONSTANTS c_abapgit_wikipage TYPE string VALUE 'https://docs.abapgit.org' ##NO_TEXT. CONSTANTS c_dotabap_homepage TYPE string VALUE 'https://dotabap.org' ##NO_TEXT. CONSTANTS c_changelog_path TYPE string VALUE '/blob/main/changelog.txt' ##NO_TEXT. CLASS-METHODS open_abapgit_homepage IMPORTING iv_page TYPE string OPTIONAL RAISING zcx_abapgit_exception . CLASS-METHODS open_abapgit_wikipage IMPORTING iv_page TYPE string OPTIONAL RAISING zcx_abapgit_exception . CLASS-METHODS open_dotabap_homepage RAISING zcx_abapgit_exception . CLASS-METHODS open_abapgit_changelog RAISING zcx_abapgit_exception . CLASS-METHODS get_abapgit_tcode RETURNING VALUE(rv_tcode) TYPE tcode . PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS open_url_in_browser IMPORTING !iv_url TYPE string RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_services_git DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS pull IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception. CLASS-METHODS create_branch IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception. CLASS-METHODS switch_branch IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception. CLASS-METHODS delete_branch IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception. CLASS-METHODS delete_tag IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception. CLASS-METHODS switch_tag IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception. CLASS-METHODS commit IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo_online !is_commit TYPE zif_abapgit_services_git=>ty_commit_fields !io_stage TYPE REF TO zcl_abapgit_stage RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_services_repo DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS new_online IMPORTING !is_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params RETURNING VALUE(ro_repo) TYPE REF TO zcl_abapgit_repo_online RAISING zcx_abapgit_exception . CLASS-METHODS refresh IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . CLASS-METHODS remove IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . CLASS-METHODS purge IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key !iv_keep_repo TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . CLASS-METHODS new_offline IMPORTING !is_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params RETURNING VALUE(ro_repo) TYPE REF TO zcl_abapgit_repo_offline RAISING zcx_abapgit_exception . CLASS-METHODS refresh_local_checksums IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . CLASS-METHODS toggle_favorite IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RAISING zcx_abapgit_exception . CLASS-METHODS transport_to_branch IMPORTING !iv_repository_key TYPE zif_abapgit_persistence=>ty_value RAISING zcx_abapgit_exception . CLASS-METHODS gui_deserialize IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo RAISING zcx_abapgit_exception . CLASS-METHODS real_deserialize IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks RAISING zcx_abapgit_exception . CLASS-METHODS activate_objects IMPORTING !iv_key TYPE zif_abapgit_persistence=>ty_repo-key RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception. CLASS-METHODS create_package IMPORTING !iv_prefill_package TYPE devclass OPTIONAL RETURNING VALUE(rv_package) TYPE devclass RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS check_package_exists IMPORTING !iv_package TYPE devclass !it_remote TYPE zif_abapgit_git_definitions=>ty_files_tt RAISING zcx_abapgit_exception. CLASS-METHODS delete_unnecessary_objects IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo !ii_log TYPE REF TO zif_abapgit_log !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks RAISING zcx_abapgit_exception . CLASS-METHODS popup_decisions IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo CHANGING !cs_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks RAISING zcx_abapgit_cancel zcx_abapgit_exception . CLASS-METHODS popup_objects_overwrite CHANGING !ct_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt RAISING zcx_abapgit_exception . CLASS-METHODS popup_package_overwrite CHANGING !ct_overwrite TYPE zif_abapgit_definitions=>ty_overwrite_tt RAISING zcx_abapgit_exception . CLASS-METHODS check_package IMPORTING !is_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params RAISING zcx_abapgit_exception . CLASS-METHODS raise_error_if_package_exists IMPORTING iv_devclass TYPE devclass RAISING zcx_abapgit_exception. CLASS-METHODS check_for_restart IMPORTING !io_repo TYPE REF TO zif_abapgit_repo. ENDCLASS. CLASS zcl_abapgit_frontend_no_gui DEFINITION CREATE PRIVATE FRIENDS ZCL_ABAPGIT_ui_factory. PUBLIC SECTION. INTERFACES zif_abapgit_frontend_services. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_frontend_services DEFINITION CREATE PRIVATE FRIENDS ZCL_ABAPGIT_ui_factory. PUBLIC SECTION. INTERFACES zif_abapgit_frontend_services. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gv_initial_folder TYPE string. METHODS get_path_from_fullname IMPORTING iv_fullname TYPE string RETURNING VALUE(rv_path) TYPE string. ENDCLASS. CLASS zcl_abapgit_password_dialog DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS popup IMPORTING !iv_repo_url TYPE string CHANGING !cv_user TYPE string !cv_pass TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_popups DEFINITION FINAL CREATE PRIVATE FRIENDS ZCL_ABAPGIT_ui_factory . PUBLIC SECTION. INTERFACES zif_abapgit_popups . CLASS-METHODS center IMPORTING !iv_width TYPE i !iv_height TYPE i RETURNING VALUE(rs_position) TYPE zif_abapgit_popups=>ty_popup_position. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_lt_fields TYPE STANDARD TABLE OF sval WITH DEFAULT KEY . TYPES: BEGIN OF ty_commit_value_tab, commit TYPE zif_abapgit_git_definitions=>ty_sha1, message TYPE c LENGTH 100, datetime TYPE c LENGTH 20, END OF ty_commit_value_tab. TYPES: ty_commit_value_tab_tt TYPE STANDARD TABLE OF ty_commit_value_tab WITH DEFAULT KEY. CONSTANTS c_answer_cancel TYPE c LENGTH 1 VALUE 'A' ##NO_TEXT. DATA ms_position TYPE zif_abapgit_popups=>ty_popup_position. TYPES ty_sval_tt TYPE STANDARD TABLE OF sval WITH DEFAULT KEY. METHODS add_field IMPORTING !iv_tabname TYPE sval-tabname !iv_fieldname TYPE sval-fieldname !iv_fieldtext TYPE sval-fieldtext !iv_value TYPE clike DEFAULT '' !iv_field_attr TYPE sval-field_attr DEFAULT '' !iv_obligatory TYPE spo_obl OPTIONAL CHANGING !ct_fields TYPE ty_sval_tt . METHODS _popup_3_get_values IMPORTING !iv_popup_title TYPE string !iv_no_value_check TYPE abap_bool DEFAULT abap_false EXPORTING !ev_value_1 TYPE spo_value !ev_value_2 TYPE spo_value !ev_value_3 TYPE spo_value CHANGING !ct_fields TYPE ty_lt_fields RAISING zcx_abapgit_exception . METHODS commit_list_build IMPORTING !iv_repo_url TYPE string !iv_branch_name TYPE string EXPORTING !et_value_tab TYPE ty_commit_value_tab_tt !et_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_ui_factory DEFINITION CREATE PRIVATE . PUBLIC SECTION. CLASS-METHODS get_asset_manager RETURNING VALUE(ri_asset_man) TYPE REF TO zif_abapgit_gui_asset_manager RAISING zcx_abapgit_exception . CLASS-METHODS get_popups RETURNING VALUE(ri_popups) TYPE REF TO zif_abapgit_popups . CLASS-METHODS get_gui RETURNING VALUE(ro_gui) TYPE REF TO zcl_abapgit_gui RAISING zcx_abapgit_exception . CLASS-METHODS get_gui_services RETURNING VALUE(ri_gui_services) TYPE REF TO zif_abapgit_gui_services RAISING zcx_abapgit_exception . CLASS-METHODS get_frontend_services IMPORTING !iv_disable_gui TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ri_fe_serv) TYPE REF TO zif_abapgit_frontend_services . CLASS-METHODS get_html_viewer IMPORTING !io_container TYPE REF TO cl_gui_container DEFAULT cl_gui_container=>screen0 !iv_disable_query_table TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ri_viewer) TYPE REF TO zif_abapgit_html_viewer . PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA gi_popups TYPE REF TO zif_abapgit_popups . CLASS-DATA gi_html_viewer TYPE REF TO zif_abapgit_html_viewer . CLASS-DATA go_gui TYPE REF TO zcl_abapgit_gui . CLASS-DATA gi_fe_services TYPE REF TO zif_abapgit_frontend_services . CLASS-DATA gi_gui_services TYPE REF TO zif_abapgit_gui_services . ENDCLASS. CLASS zcl_abapgit_convert DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS bitbyte_to_int IMPORTING !iv_bits TYPE clike RETURNING VALUE(rv_int) TYPE i . CLASS-METHODS x_to_bitbyte IMPORTING !iv_x TYPE x RETURNING VALUE(rv_bitbyte) TYPE zif_abapgit_git_definitions=>ty_bitbyte . CLASS-METHODS string_to_xstring_utf8 IMPORTING !iv_string TYPE string RETURNING VALUE(rv_xstring) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS xstring_to_string_utf8 IMPORTING !iv_data TYPE xsequence !iv_length TYPE i OPTIONAL RETURNING VALUE(rv_string) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS string_to_xstring_utf8_bom IMPORTING !iv_string TYPE string RETURNING VALUE(rv_xstring) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS xstring_to_string_utf8_bom IMPORTING !iv_xstring TYPE xstring RETURNING VALUE(rv_string) TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS xstring_to_int IMPORTING !iv_xstring TYPE xstring RETURNING VALUE(rv_i) TYPE i RAISING zcx_abapgit_exception . CLASS-METHODS int_to_xstring4 IMPORTING !iv_i TYPE i RETURNING VALUE(rv_xstring) TYPE xstring . CLASS-METHODS split_string IMPORTING !iv_string TYPE string RETURNING VALUE(rt_lines) TYPE string_table . CLASS-METHODS conversion_exit_isola_output IMPORTING !iv_spras TYPE spras RETURNING VALUE(rv_spras) TYPE laiso . CLASS-METHODS string_to_xstring IMPORTING !iv_str TYPE string RETURNING VALUE(rv_xstr) TYPE xstring RAISING zcx_abapgit_exception . CLASS-METHODS string_to_tab IMPORTING !iv_str TYPE string EXPORTING !ev_size TYPE i !et_tab TYPE STANDARD TABLE . CLASS-METHODS base64_to_xstring IMPORTING !iv_base64 TYPE string RETURNING VALUE(rv_xstr) TYPE xstring . CLASS-METHODS xstring_to_bintab IMPORTING !iv_xstr TYPE xstring EXPORTING !ev_size TYPE i !et_bintab TYPE STANDARD TABLE . CLASS-METHODS language_sap1_to_sap2 IMPORTING im_lang_sap1 TYPE sy-langu RETURNING VALUE(re_lang_sap2) TYPE string EXCEPTIONS no_assignment. CLASS-METHODS language_sap2_to_sap1 IMPORTING im_lang_sap2 TYPE laiso RETURNING VALUE(re_lang_sap1) TYPE sy-langu EXCEPTIONS no_assignment. CLASS-METHODS language_sap1_to_bcp47 IMPORTING im_lang_sap1 TYPE sy-langu RETURNING VALUE(re_lang_bcp47) TYPE string EXCEPTIONS no_assignment. CLASS-METHODS language_bcp47_to_sap1 IMPORTING im_lang_bcp47 TYPE string RETURNING VALUE(re_lang_sap1) TYPE sy-langu EXCEPTIONS no_assignment. PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS xstring_remove_bom IMPORTING iv_xstr TYPE xsequence RETURNING VALUE(rv_xstr) TYPE xstring. ENDCLASS. CLASS zcl_abapgit_diff DEFINITION CREATE PUBLIC. PUBLIC SECTION. CONSTANTS c_starting_beacon TYPE i VALUE 1. * assumes data is UTF8 based with newlines METHODS constructor IMPORTING !iv_new TYPE xstring !iv_old TYPE xstring !iv_ignore_indentation TYPE abap_bool DEFAULT abap_false !iv_ignore_comments TYPE abap_bool DEFAULT abap_false !iv_ignore_case TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception. METHODS get RETURNING VALUE(rt_diff) TYPE zif_abapgit_definitions=>ty_diffs_tt. METHODS stats RETURNING VALUE(rs_count) TYPE zif_abapgit_definitions=>ty_count. METHODS set_patch_new IMPORTING !iv_line_new TYPE i !iv_patch_flag TYPE abap_bool RAISING zcx_abapgit_exception. METHODS set_patch_old IMPORTING !iv_line_old TYPE i !iv_patch_flag TYPE abap_bool RAISING zcx_abapgit_exception. METHODS get_beacons RETURNING VALUE(rt_beacons) TYPE zif_abapgit_definitions=>ty_string_tt. METHODS is_line_patched IMPORTING iv_index TYPE i RETURNING VALUE(rv_patched) TYPE abap_bool RAISING zcx_abapgit_exception. METHODS set_patch_by_old_diff IMPORTING is_diff_old TYPE zif_abapgit_definitions=>ty_diff iv_patch_flag TYPE abap_bool. PROTECTED SECTION. PRIVATE SECTION. TYPES: ty_regexset_tt TYPE STANDARD TABLE OF REF TO cl_abap_regex WITH KEY table_line. DATA mt_beacons TYPE zif_abapgit_definitions=>ty_string_tt. DATA mt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt. DATA ms_stats TYPE zif_abapgit_definitions=>ty_count. DATA mv_compare_mode TYPE c LENGTH 1. DATA mv_ignore_case TYPE abap_bool. METHODS unpack IMPORTING !iv_new TYPE xstring !iv_old TYPE xstring EXPORTING !et_new TYPE rswsourcet !et_old TYPE rswsourcet RAISING zcx_abapgit_exception. METHODS map_beacons. METHODS shortlist. METHODS create_regex_set RETURNING VALUE(rt_regex_set) TYPE ty_regexset_tt. METHODS compute_and_render IMPORTING !it_new TYPE rswsourcet !it_old TYPE rswsourcet RETURNING VALUE(rt_diff) TYPE zif_abapgit_definitions=>ty_diffs_tt. METHODS calculate_stats. METHODS adjust_diff. ENDCLASS. CLASS zcl_abapgit_log DEFINITION CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_log . METHODS constructor IMPORTING iv_title TYPE string OPTIONAL. CLASS-METHODS from_exception IMPORTING io_x TYPE REF TO cx_root RETURNING VALUE(ro_log) TYPE REF TO zcl_abapgit_log. PROTECTED SECTION. TYPES: BEGIN OF ty_log, "in order of occurrence msg TYPE zif_abapgit_log=>ty_msg, item TYPE zif_abapgit_definitions=>ty_item, exception TYPE REF TO cx_root, END OF ty_log . DATA: mt_log TYPE STANDARD TABLE OF ty_log WITH DEFAULT KEY . DATA mv_title TYPE string . METHODS get_messages_status IMPORTING !it_msg TYPE zif_abapgit_log=>ty_msgs RETURNING VALUE(rv_status) TYPE sy-msgty . PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_path DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS split_file_location IMPORTING iv_fullpath TYPE string EXPORTING ev_path TYPE string ev_filename TYPE string. CLASS-METHODS is_root IMPORTING iv_path TYPE string RETURNING VALUE(rv_yes) TYPE abap_bool. CLASS-METHODS is_subdir IMPORTING iv_path TYPE string iv_parent TYPE string RETURNING VALUE(rv_yes) TYPE abap_bool. CLASS-METHODS change_dir IMPORTING iv_cur_dir TYPE string iv_cd TYPE string RETURNING VALUE(rv_path) TYPE string. CLASS-METHODS get_filename_from_syspath IMPORTING iv_path TYPE string RETURNING VALUE(rv_filename) TYPE string. ENDCLASS. CLASS zcl_abapgit_string_buffer DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS new RETURNING VALUE(ro_me) TYPE REF TO zcl_abapgit_string_buffer. METHODS add IMPORTING !iv_str TYPE string RETURNING VALUE(ro_me) TYPE REF TO zcl_abapgit_string_buffer. METHODS join_and_flush RETURNING VALUE(rv_str) TYPE string. METHODS join_w_newline_and_flush RETURNING VALUE(rv_str) TYPE string. METHODS join_w_space_and_flush RETURNING VALUE(rv_str) TYPE string. PROTECTED SECTION. PRIVATE SECTION. DATA mt_buffer TYPE string_table. ENDCLASS. CLASS zcl_abapgit_string_map DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_entry, k TYPE string, v TYPE string, END OF ty_entry . TYPES: ty_entries TYPE SORTED TABLE OF ty_entry WITH UNIQUE KEY k . DATA mt_entries TYPE ty_entries READ-ONLY . CLASS-METHODS create IMPORTING !iv_case_insensitive TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_string_map . METHODS constructor IMPORTING !iv_case_insensitive TYPE abap_bool DEFAULT abap_false . METHODS get IMPORTING !iv_key TYPE string RETURNING VALUE(rv_val) TYPE string . METHODS has IMPORTING !iv_key TYPE string RETURNING VALUE(rv_has) TYPE abap_bool . METHODS set IMPORTING !iv_key TYPE string !iv_val TYPE csequence OPTIONAL RETURNING VALUE(ro_map) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . METHODS size RETURNING VALUE(rv_size) TYPE i . METHODS is_empty RETURNING VALUE(rv_yes) TYPE abap_bool . METHODS delete IMPORTING !iv_key TYPE string RAISING zcx_abapgit_exception . METHODS clear RAISING zcx_abapgit_exception . METHODS to_abap CHANGING !cs_container TYPE any RAISING zcx_abapgit_exception . METHODS strict IMPORTING !iv_strict TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_string_map . METHODS freeze . METHODS merge IMPORTING !io_string_map TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. DATA mv_read_only TYPE abap_bool. DATA mv_is_strict TYPE abap_bool. DATA mv_case_insensitive TYPE abap_bool. ENDCLASS. CLASS zcl_abapgit_timer DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS create IMPORTING !iv_text TYPE string OPTIONAL !iv_count TYPE i OPTIONAL PREFERRED PARAMETER iv_text RETURNING VALUE(ro_timer) TYPE REF TO zcl_abapgit_timer. METHODS constructor IMPORTING !iv_text TYPE string OPTIONAL !iv_count TYPE i OPTIONAL. METHODS start RETURNING VALUE(ro_timer) TYPE REF TO zcl_abapgit_timer. METHODS end IMPORTING !iv_output_as_status_message TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_result) TYPE string. PROTECTED SECTION. PRIVATE SECTION. DATA mv_text TYPE string. DATA mv_count TYPE i. DATA mv_timer TYPE timestampl. ENDCLASS. CLASS zcl_abapgit_utils DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS is_binary IMPORTING !iv_data TYPE xstring RETURNING VALUE(rv_is_binary) TYPE abap_bool. CLASS-METHODS is_valid_email IMPORTING iv_email TYPE string RETURNING VALUE(rv_valid) TYPE abap_bool. CLASS-METHODS check_eol IMPORTING !iv_data TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_xml DEFINITION ABSTRACT CREATE PUBLIC . PUBLIC SECTION. METHODS: constructor IMPORTING iv_filename TYPE string OPTIONAL. PROTECTED SECTION. DATA: mi_ixml TYPE REF TO if_ixml, mi_xml_doc TYPE REF TO if_ixml_document, ms_metadata TYPE zif_abapgit_definitions=>ty_metadata, mv_filename TYPE string. CONSTANTS: c_abapgit_tag TYPE string VALUE 'abapGit' ##NO_TEXT, c_attr_version TYPE string VALUE 'version' ##NO_TEXT, c_attr_serializer TYPE string VALUE 'serializer' ##NO_TEXT, c_attr_serializer_version TYPE string VALUE 'serializer_version' ##NO_TEXT. METHODS to_xml IMPORTING iv_normalize TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rv_xml) TYPE string. METHODS parse IMPORTING iv_xml TYPE string RAISING zcx_abapgit_exception. PRIVATE SECTION. METHODS error IMPORTING !ii_parser TYPE REF TO if_ixml_parser RAISING zcx_abapgit_exception . METHODS raise_version_mismatch IMPORTING !iv_vers TYPE string RAISING zcx_abapgit_exception . METHODS raise_exception_for IMPORTING !ii_error TYPE REF TO if_ixml_parse_error RAISING zcx_abapgit_exception . ENDCLASS. CLASS zcl_abapgit_xml_input DEFINITION INHERITING FROM zcl_abapgit_xml CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_xml_input. METHODS constructor IMPORTING !iv_xml TYPE clike !iv_filename TYPE string OPTIONAL RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. METHODS fix_xml. ENDCLASS. CLASS zcl_abapgit_xml_output DEFINITION INHERITING FROM zcl_abapgit_xml CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_abapgit_xml_output. PROTECTED SECTION. PRIVATE SECTION. DATA mi_raw TYPE REF TO if_ixml_element . METHODS build_asx_node RETURNING VALUE(ri_element) TYPE REF TO if_ixml_element . ENDCLASS. CLASS zcl_abapgit_xml_pretty DEFINITION CREATE PUBLIC . PUBLIC SECTION. CLASS-METHODS print IMPORTING !iv_xml TYPE string !iv_ignore_errors TYPE abap_bool DEFAULT abap_true !iv_unpretty TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_xml) TYPE string RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_abapgit_factory DEFINITION CREATE PRIVATE . PUBLIC SECTION. CLASS-METHODS get_tadir RETURNING VALUE(ri_tadir) TYPE REF TO zif_abapgit_tadir . CLASS-METHODS get_sap_package IMPORTING !iv_package TYPE devclass RETURNING VALUE(ri_sap_package) TYPE REF TO zif_abapgit_sap_package . CLASS-METHODS get_code_inspector IMPORTING !iv_package TYPE devclass RETURNING VALUE(ri_code_inspector) TYPE REF TO zif_abapgit_code_inspector RAISING zcx_abapgit_exception . CLASS-METHODS get_stage_logic RETURNING VALUE(ri_logic) TYPE REF TO zif_abapgit_stage_logic . CLASS-METHODS get_cts_api RETURNING VALUE(ri_cts_api) TYPE REF TO zif_abapgit_cts_api . CLASS-METHODS get_default_transport RETURNING VALUE(ri_default_transport) TYPE REF TO zif_abapgit_default_transport RAISING zcx_abapgit_exception. CLASS-METHODS get_environment RETURNING VALUE(ri_environment) TYPE REF TO zif_abapgit_environment . CLASS-METHODS get_longtexts RETURNING VALUE(ri_longtexts) TYPE REF TO zif_abapgit_longtexts . CLASS-METHODS get_http_agent RETURNING VALUE(ri_http_agent) TYPE REF TO zif_abapgit_http_agent . CLASS-METHODS get_lxe_texts RETURNING VALUE(ri_lxe_texts) TYPE REF TO zif_abapgit_lxe_texts . CLASS-METHODS get_sap_namespace RETURNING VALUE(ri_namespace) TYPE REF TO zif_abapgit_sap_namespace . CLASS-METHODS get_sap_report RETURNING VALUE(ri_report) TYPE REF TO zif_abapgit_sap_report. CLASS-METHODS get_function_module RETURNING VALUE(ri_function_module) TYPE REF TO zif_abapgit_function_module. PROTECTED SECTION. PRIVATE SECTION. TYPES: BEGIN OF ty_sap_package, package TYPE devclass, instance TYPE REF TO zif_abapgit_sap_package, END OF ty_sap_package . TYPES: ty_sap_packages TYPE HASHED TABLE OF ty_sap_package WITH UNIQUE KEY package . TYPES: BEGIN OF ty_code_inspector_pack, package TYPE devclass, instance TYPE REF TO zif_abapgit_code_inspector, END OF ty_code_inspector_pack . TYPES: ty_code_inspector_packs TYPE HASHED TABLE OF ty_code_inspector_pack WITH UNIQUE KEY package . CLASS-DATA gi_tadir TYPE REF TO zif_abapgit_tadir . CLASS-DATA gt_sap_package TYPE ty_sap_packages . CLASS-DATA gt_code_inspector TYPE ty_code_inspector_packs . CLASS-DATA gi_stage_logic TYPE REF TO zif_abapgit_stage_logic . CLASS-DATA gi_cts_api TYPE REF TO zif_abapgit_cts_api . CLASS-DATA gi_environment TYPE REF TO zif_abapgit_environment . CLASS-DATA gi_longtext TYPE REF TO zif_abapgit_longtexts . CLASS-DATA gi_http_agent TYPE REF TO zif_abapgit_http_agent . CLASS-DATA gi_lxe_texts TYPE REF TO zif_abapgit_lxe_texts . CLASS-DATA gi_sap_namespace TYPE REF TO zif_abapgit_sap_namespace . CLASS-DATA gi_sap_report TYPE REF TO zif_abapgit_sap_report. CLASS-DATA gi_function_module TYPE REF TO zif_abapgit_function_module. CLASS-DATA gi_default_transport TYPE REF TO zif_abapgit_default_transport . ENDCLASS. CLASS ZCL_ABAPGIT_FACTORY IMPLEMENTATION. METHOD get_code_inspector. DATA: ls_code_inspector LIKE LINE OF gt_code_inspector. FIELD-SYMBOLS: TYPE ty_code_inspector_pack. READ TABLE gt_code_inspector ASSIGNING WITH TABLE KEY package = iv_package. IF sy-subrc <> 0. ls_code_inspector-package = iv_package. CREATE OBJECT ls_code_inspector-instance TYPE zcl_abapgit_code_inspector EXPORTING iv_package = iv_package. INSERT ls_code_inspector INTO TABLE gt_code_inspector ASSIGNING . ENDIF. ri_code_inspector = -instance. ENDMETHOD. METHOD get_cts_api. IF gi_cts_api IS NOT BOUND. CREATE OBJECT gi_cts_api TYPE zcl_abapgit_cts_api. ENDIF. ri_cts_api = gi_cts_api. ENDMETHOD. METHOD get_default_transport. IF gi_default_transport IS NOT BOUND. CREATE OBJECT gi_default_transport TYPE zcl_abapgit_default_transport. ENDIF. ri_default_transport = gi_default_transport. ENDMETHOD. METHOD get_environment. IF gi_environment IS NOT BOUND. CREATE OBJECT gi_environment TYPE zcl_abapgit_environment. ENDIF. ri_environment = gi_environment. ENDMETHOD. METHOD get_function_module. IF gi_function_module IS INITIAL. CREATE OBJECT gi_function_module TYPE zcl_abapgit_function_module. ENDIF. ri_function_module = gi_function_module. ENDMETHOD. METHOD get_http_agent. IF gi_http_agent IS INITIAL. gi_http_agent = zcl_abapgit_http_agent=>create( ). ENDIF. ri_http_agent = gi_http_agent. ENDMETHOD. METHOD get_longtexts. IF gi_longtext IS NOT BOUND. CREATE OBJECT gi_longtext TYPE zcl_abapgit_longtexts. ENDIF. ri_longtexts = gi_longtext. ENDMETHOD. METHOD get_lxe_texts. IF gi_lxe_texts IS NOT BOUND. CREATE OBJECT gi_lxe_texts TYPE zcl_abapgit_lxe_texts. ENDIF. ri_lxe_texts = gi_lxe_texts. ENDMETHOD. METHOD get_sap_namespace. IF gi_sap_namespace IS NOT BOUND. CREATE OBJECT gi_sap_namespace TYPE zcl_abapgit_sap_namespace. ENDIF. ri_namespace = gi_sap_namespace. ENDMETHOD. METHOD get_sap_package. DATA: ls_sap_package TYPE ty_sap_package. FIELD-SYMBOLS: TYPE ty_sap_package. READ TABLE gt_sap_package ASSIGNING WITH TABLE KEY package = iv_package. IF sy-subrc <> 0. ls_sap_package-package = iv_package. CREATE OBJECT ls_sap_package-instance TYPE zcl_abapgit_sap_package EXPORTING iv_package = iv_package. INSERT ls_sap_package INTO TABLE gt_sap_package ASSIGNING . ENDIF. ri_sap_package = -instance. ENDMETHOD. METHOD get_sap_report. IF gi_sap_report IS NOT BOUND. CREATE OBJECT gi_sap_report TYPE zcl_abapgit_sap_report. ENDIF. ri_report = gi_sap_report. ENDMETHOD. METHOD get_stage_logic. IF gi_stage_logic IS INITIAL. CREATE OBJECT gi_stage_logic TYPE zcl_abapgit_stage_logic. ENDIF. ri_logic = gi_stage_logic. ENDMETHOD. METHOD get_tadir. IF gi_tadir IS INITIAL. CREATE OBJECT gi_tadir TYPE zcl_abapgit_tadir. ENDIF. ri_tadir = gi_tadir. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_XML_PRETTY IMPLEMENTATION. METHOD print. DATA: li_ixml TYPE REF TO if_ixml, li_xml_doc TYPE REF TO if_ixml_document, li_stream_factory TYPE REF TO if_ixml_stream_factory, li_istream TYPE REF TO if_ixml_istream, li_parser TYPE REF TO if_ixml_parser, lv_xstring TYPE xstring, li_encoding TYPE REF TO if_ixml_encoding, li_ostream TYPE REF TO if_ixml_ostream, li_renderer TYPE REF TO if_ixml_renderer. ASSERT NOT iv_xml IS INITIAL. li_ixml = cl_ixml=>create( ). li_xml_doc = li_ixml->create_document( ). li_stream_factory = li_ixml->create_stream_factory( ). li_istream = li_stream_factory->create_istream_xstring( zcl_abapgit_convert=>string_to_xstring_utf8( iv_xml ) ). li_parser = li_ixml->create_parser( stream_factory = li_stream_factory istream = li_istream document = li_xml_doc ). li_parser->set_normalizing( abap_true ). IF li_parser->parse( ) <> 0. IF iv_ignore_errors = abap_true. rv_xml = iv_xml. RETURN. ELSE. zcx_abapgit_exception=>raise( 'error parsing xml' ). ENDIF. ENDIF. li_ostream = li_stream_factory->create_ostream_xstring( lv_xstring ). li_encoding = li_ixml->create_encoding( character_set = 'utf-8' byte_order = if_ixml_encoding=>co_big_endian ). li_xml_doc->set_encoding( li_encoding ). li_renderer = li_ixml->create_renderer( ostream = li_ostream document = li_xml_doc ). li_renderer->set_normalizing( boolc( iv_unpretty = abap_false ) ). li_renderer->render( ). rv_xml = zcl_abapgit_convert=>xstring_to_string_utf8_bom( lv_xstring ). REPLACE FIRST OCCURRENCE OF 'utf-8' IN rv_xml WITH 'utf-16'. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_XML_OUTPUT IMPLEMENTATION. METHOD build_asx_node. DATA: li_attr TYPE REF TO if_ixml_attribute. ri_element = mi_xml_doc->create_element_ns( name = 'abap' prefix = 'asx' ). li_attr = mi_xml_doc->create_attribute_ns( 'version' ). li_attr->if_ixml_node~set_value( '1.0' ). ri_element->set_attribute_node_ns( li_attr ). li_attr = mi_xml_doc->create_attribute_ns( name = 'asx' prefix = 'xmlns' ). li_attr->if_ixml_node~set_value( 'http://www.sap.com/abapxml' ). ri_element->set_attribute_node_ns( li_attr ). ENDMETHOD. METHOD zif_abapgit_xml_output~add. DATA: li_node TYPE REF TO if_ixml_node, li_doc TYPE REF TO if_ixml_document, lt_stab TYPE abap_trans_srcbind_tab. FIELD-SYMBOLS: LIKE LINE OF lt_stab. ASSERT NOT iv_name IS INITIAL. IF ig_data IS INITIAL. RETURN. ENDIF. APPEND INITIAL LINE TO lt_stab ASSIGNING . -name = iv_name. GET REFERENCE OF ig_data INTO -value. li_doc = cl_ixml=>create( )->create_document( ). CALL TRANSFORMATION id OPTIONS initial_components = 'suppress' SOURCE (lt_stab) RESULT XML li_doc. li_node = mi_xml_doc->get_root( )->get_first_child( ). IF li_node IS BOUND. mi_xml_doc->get_root( )->get_first_child( )->get_first_child( )->append_child( li_doc->get_root( )->get_first_child( )->get_first_child( )->get_first_child( ) ). ELSE. mi_xml_doc->get_root( )->append_child( li_doc->get_root( )->get_first_child( ) ). ENDIF. ENDMETHOD. METHOD zif_abapgit_xml_output~add_xml. DATA: li_element TYPE REF TO if_ixml_element. li_element = mi_xml_doc->create_element( iv_name ). li_element->append_child( ii_xml ). mi_xml_doc->get_root( )->get_first_child( )->get_first_child( )->append_child( li_element ). ENDMETHOD. METHOD zif_abapgit_xml_output~render. DATA: li_git TYPE REF TO if_ixml_element, li_abap TYPE REF TO if_ixml_element. IF mi_raw IS INITIAL. li_abap ?= mi_xml_doc->get_root( )->get_first_child( ). mi_xml_doc->get_root( )->remove_child( li_abap ). IF li_abap IS INITIAL. li_abap = build_asx_node( ). ENDIF. ELSE. li_abap = mi_raw. ENDIF. li_git = mi_xml_doc->create_element( c_abapgit_tag ). li_git->set_attribute( name = c_attr_version value = zif_abapgit_version=>c_xml_version ). IF NOT is_metadata IS INITIAL. li_git->set_attribute( name = c_attr_serializer value = is_metadata-class ). li_git->set_attribute( name = c_attr_serializer_version value = is_metadata-version ). ENDIF. li_git->append_child( li_abap ). mi_xml_doc->get_root( )->append_child( li_git ). rv_xml = to_xml( iv_normalize ). ENDMETHOD. METHOD zif_abapgit_xml_output~set_raw. mi_raw = ii_raw. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_XML_INPUT IMPLEMENTATION. METHOD constructor. super->constructor( iv_filename ). parse( iv_xml ). fix_xml( ). ENDMETHOD. METHOD fix_xml. DATA: li_git TYPE REF TO if_ixml_element, li_abap TYPE REF TO if_ixml_node. li_git ?= mi_xml_doc->find_from_name_ns( depth = 0 name = c_abapgit_tag ). li_abap = li_git->get_first_child( ). mi_xml_doc->get_root( )->remove_child( li_git ). mi_xml_doc->get_root( )->append_child( li_abap ). ENDMETHOD. METHOD zif_abapgit_xml_input~get_metadata. rs_metadata = ms_metadata. ENDMETHOD. METHOD zif_abapgit_xml_input~get_raw. ri_raw = mi_xml_doc. ENDMETHOD. METHOD zif_abapgit_xml_input~read. DATA: lx_error TYPE REF TO cx_transformation_error, lt_rtab TYPE abap_trans_resbind_tab. FIELD-SYMBOLS: LIKE LINE OF lt_rtab. ASSERT NOT iv_name IS INITIAL. CLEAR cg_data. "Initialize result to avoid problems with empty values APPEND INITIAL LINE TO lt_rtab ASSIGNING . -name = iv_name. GET REFERENCE OF cg_data INTO -value. TRY. CALL TRANSFORMATION id OPTIONS value_handling = 'accept_data_loss' SOURCE XML mi_xml_doc RESULT (lt_rtab). CATCH cx_transformation_error INTO lx_error. IF mv_filename IS INITIAL. zcx_abapgit_exception=>raise( lx_error->if_message~get_text( ) ). ELSE. zcx_abapgit_exception=>raise( |File { mv_filename }: { lx_error->if_message~get_text( ) }| ). ENDIF. ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_xml IMPLEMENTATION. METHOD constructor. mi_ixml = cl_ixml=>create( ). mi_xml_doc = mi_ixml->create_document( ). mv_filename = iv_filename. ENDMETHOD. METHOD error. IF ii_parser->num_errors( ) <> 0. raise_exception_for( ii_parser->get_error( 0 ) ). ENDIF. IF mv_filename IS INITIAL. zcx_abapgit_exception=>raise( |Error while parsing XML| ). ELSE. zcx_abapgit_exception=>raise( |Error while parsing XML file { mv_filename }| ). ENDIF. ENDMETHOD. METHOD parse. DATA: li_stream_factory TYPE REF TO if_ixml_stream_factory, li_istream TYPE REF TO if_ixml_istream, li_element TYPE REF TO if_ixml_element, li_version TYPE REF TO if_ixml_node, li_parser TYPE REF TO if_ixml_parser. ASSERT NOT iv_xml IS INITIAL. li_stream_factory = mi_ixml->create_stream_factory( ). li_istream = li_stream_factory->create_istream_string( iv_xml ). li_parser = mi_ixml->create_parser( stream_factory = li_stream_factory istream = li_istream document = mi_xml_doc ). li_parser->add_strip_space_element( ). IF li_parser->parse( ) <> 0. error( li_parser ). ENDIF. li_istream->close( ). li_element = mi_xml_doc->find_from_name_ns( depth = 0 name = c_abapgit_tag ). li_version = li_element->if_ixml_node~get_attributes( )->get_named_item_ns( c_attr_version ). IF li_version->get_value( ) <> zif_abapgit_version=>c_xml_version. raise_version_mismatch( li_version->get_value( ) ). ENDIF. * buffer serializer metadata. Git node will be removed lateron ms_metadata-class = li_element->get_attribute_ns( c_attr_serializer ). ms_metadata-version = li_element->get_attribute_ns( c_attr_serializer_version ). ENDMETHOD. METHOD raise_exception_for. DATA lv_message TYPE string. lv_message = |XML parser error: { ii_error->get_reason( ) }, | && |Line { ii_error->get_line( ) } | && |Col. { ii_error->get_column( ) }|. IF mv_filename IS NOT INITIAL. lv_message = lv_message && | File { mv_filename }|. ENDIF. zcx_abapgit_exception=>raise( lv_message ). ENDMETHOD. METHOD raise_version_mismatch. DATA lv_text TYPE string. lv_text = |The XML versions do not match, expected: { zif_abapgit_version=>c_xml_version }, actual: { iv_vers }|. IF mv_filename IS NOT INITIAL. lv_text = lv_text && |, file: { mv_filename }|. ENDIF. lv_text = lv_text && | (see https://docs.abapgit.org/other-xml-mismatch.html)|. zcx_abapgit_exception=>raise( lv_text ). ENDMETHOD. METHOD to_xml. * will render to codepage UTF-16 DATA: li_ostream TYPE REF TO if_ixml_ostream, li_renderer TYPE REF TO if_ixml_renderer, li_streamfactory TYPE REF TO if_ixml_stream_factory. li_streamfactory = mi_ixml->create_stream_factory( ). li_ostream = li_streamfactory->create_ostream_cstring( rv_xml ). li_renderer = mi_ixml->create_renderer( ostream = li_ostream document = mi_xml_doc ). li_renderer->set_normalizing( iv_normalize ). li_renderer->render( ). " handling of BOM moved to zcl_abapgit_convert=>string_to_xstring_utf8_bom ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_utils IMPLEMENTATION. METHOD check_eol. " Check if data is using CRLF as EOL separator. If only LF is used, data was likely " edited by external tools IF iv_data IS NOT INITIAL AND iv_data CS cl_abap_char_utilities=>newline AND iv_data NS cl_abap_char_utilities=>cr_lf. zcx_abapgit_exception=>raise( 'Incorrect source format: Requires CRLF instead of LF' ). ENDIF. ENDMETHOD. METHOD is_binary. " Previously we did a simple char range test described here " stackoverflow.com/questions/277521/how-to-identify-the-file-content-as-ascii-or-binary " but this is insufficient if the data contains German umlauts and other special characters. " Therefore we adopted another algorithm, which is similarly used by AL11 " RSWATCH0 / GUESS_FILE_TYPE " We count non-printable characters if there are more than XX% it's binary. CONSTANTS: lc_binary_threshold TYPE i VALUE 10, lc_bytes_to_check TYPE i VALUE 1000. DATA: lv_string_data TYPE string, lv_printable_chars_count TYPE i, lv_percentage TYPE i, lv_data TYPE xstring, lv_xlen TYPE i. lv_xlen = xstrlen( iv_data ). IF lv_xlen = 0. RETURN. ENDIF. lv_xlen = nmin( val1 = lv_xlen val2 = lc_bytes_to_check ). lv_data = iv_data(lv_xlen). TRY. lv_string_data = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). CATCH zcx_abapgit_exception. " Contains data that does not convert to UTF-8 so consider it binary rv_is_binary = abap_true. RETURN. ENDTRY. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN lv_string_data WITH space. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_string_data WITH space. FIND ALL OCCURRENCES OF REGEX '[^[:print:]]' IN lv_string_data MATCH COUNT lv_printable_chars_count. lv_percentage = lv_printable_chars_count * 100 / strlen( lv_string_data ). rv_is_binary = boolc( lv_percentage > lc_binary_threshold ). ENDMETHOD. METHOD is_valid_email. " Email address validation (RFC 5322) " https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s01.html CONSTANTS lc_email_regex TYPE string VALUE '[\w!#$%&*+/=?`{|}~^-]+(?:\.[\w!#$%&*+/=?`{|}~^-]+)*@(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,6}'. IF iv_email IS INITIAL. rv_valid = abap_true. ELSE. FIND REGEX lc_email_regex IN iv_email. rv_valid = boolc( sy-subrc = 0 ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_timer IMPLEMENTATION. METHOD constructor. mv_text = iv_text. mv_count = iv_count. ENDMETHOD. METHOD create. CREATE OBJECT ro_timer EXPORTING iv_text = iv_text iv_count = iv_count. ENDMETHOD. METHOD end. DATA: lv_timestamp TYPE timestampl, lv_runtime TYPE timestampl, lv_sec TYPE p LENGTH 11 DECIMALS 2. IF mv_timer IS INITIAL. rv_result = 'Runtime measurement has not been started'. ELSE. GET TIME STAMP FIELD lv_timestamp. TRY. lv_runtime = cl_abap_tstmp=>subtract( tstmp1 = lv_timestamp tstmp2 = mv_timer ). lv_sec = lv_runtime. " round to 2 decimal places IF mv_count = 1. rv_result = |1 object, |. ELSEIF mv_count > 1. rv_result = |{ mv_count } objects, |. ENDIF. rv_result = rv_result && |{ lv_sec } seconds|. CATCH cx_parameter_invalid. rv_result = 'Error getting runtime measurement'. ENDTRY. ENDIF. IF iv_output_as_status_message = abap_true. MESSAGE s000(oo) WITH mv_text rv_result. ENDIF. IF mv_text IS NOT INITIAL. rv_result = |{ mv_text } { rv_result }|. ENDIF. ENDMETHOD. METHOD start. GET TIME STAMP FIELD mv_timer. ro_timer = me. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_STRING_MAP IMPLEMENTATION. METHOD clear. IF mv_read_only = abap_true. zcx_abapgit_exception=>raise( 'Cannot clear. This string map is immutable' ). ENDIF. CLEAR mt_entries. ENDMETHOD. METHOD constructor. mv_is_strict = abap_true. mv_case_insensitive = iv_case_insensitive. ENDMETHOD. METHOD create. CREATE OBJECT ro_instance EXPORTING iv_case_insensitive = iv_case_insensitive. ENDMETHOD. METHOD delete. IF mv_read_only = abap_true. zcx_abapgit_exception=>raise( 'Cannot delete. This string map is immutable' ). ENDIF. DELETE mt_entries WHERE k = iv_key. ENDMETHOD. METHOD freeze. mv_read_only = abap_true. ENDMETHOD. METHOD get. DATA lv_key LIKE iv_key. FIELD-SYMBOLS LIKE LINE OF mt_entries. IF mv_case_insensitive = abap_true. lv_key = to_upper( iv_key ). ELSE. lv_key = iv_key. ENDIF. READ TABLE mt_entries ASSIGNING WITH KEY k = lv_key. IF sy-subrc IS INITIAL. rv_val = -v. ENDIF. ENDMETHOD. METHOD has. READ TABLE mt_entries TRANSPORTING NO FIELDS WITH KEY k = iv_key. rv_has = boolc( sy-subrc IS INITIAL ). ENDMETHOD. METHOD is_empty. rv_yes = boolc( lines( mt_entries ) = 0 ). ENDMETHOD. METHOD merge. FIELD-SYMBOLS LIKE LINE OF mt_entries. LOOP AT io_string_map->mt_entries ASSIGNING . set( iv_key = -k iv_val = -v ). ENDLOOP. ro_instance = me. ENDMETHOD. METHOD set. DATA lv_key LIKE iv_key. DATA ls_entry LIKE LINE OF mt_entries. FIELD-SYMBOLS LIKE LINE OF mt_entries. IF mv_read_only = abap_true. zcx_abapgit_exception=>raise( 'Cannot set. This string map is immutable' ). ENDIF. IF mv_case_insensitive = abap_true. lv_key = to_upper( iv_key ). ELSE. lv_key = iv_key. ENDIF. READ TABLE mt_entries ASSIGNING WITH KEY k = lv_key. IF sy-subrc IS INITIAL. -v = iv_val. ELSE. ls_entry-k = lv_key. ls_entry-v = iv_val. INSERT ls_entry INTO TABLE mt_entries. ENDIF. ro_map = me. ENDMETHOD. METHOD size. rv_size = lines( mt_entries ). ENDMETHOD. METHOD strict. mv_is_strict = iv_strict. ro_instance = me. ENDMETHOD. METHOD to_abap. DATA lo_type TYPE REF TO cl_abap_typedescr. DATA lv_field TYPE string. FIELD-SYMBOLS LIKE LINE OF mt_entries. FIELD-SYMBOLS TYPE any. lo_type = cl_abap_typedescr=>describe_by_data( cs_container ). IF lo_type->type_kind <> cl_abap_typedescr=>typekind_struct1 AND lo_type->type_kind <> cl_abap_typedescr=>typekind_struct2. zcx_abapgit_exception=>raise( 'Only structures supported' ). ENDIF. LOOP AT mt_entries ASSIGNING . lv_field = to_upper( -k ). ASSIGN COMPONENT lv_field OF STRUCTURE cs_container TO . IF sy-subrc = 0. " TODO check target type ? = -v. ELSEIF mv_is_strict = abap_false. CONTINUE. ELSE. zcx_abapgit_exception=>raise( |Component { lv_field } not found in target| ). ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_STRING_BUFFER IMPLEMENTATION. METHOD add. APPEND iv_str TO mt_buffer. ro_me = me. ENDMETHOD. METHOD join_and_flush. rv_str = concat_lines_of( mt_buffer ). CLEAR mt_buffer. ENDMETHOD. METHOD join_w_newline_and_flush. rv_str = concat_lines_of( table = mt_buffer sep = cl_abap_char_utilities=>newline ). CLEAR mt_buffer. ENDMETHOD. METHOD join_w_space_and_flush. rv_str = concat_lines_of( table = mt_buffer sep = ` ` ). CLEAR mt_buffer. ENDMETHOD. METHOD new. CREATE OBJECT ro_me. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_PATH IMPLEMENTATION. METHOD change_dir. DATA: lv_last TYPE i, lv_temp TYPE string. lv_last = strlen( iv_cur_dir ) - 1. IF iv_cd = '' OR iv_cd = '.'. " No change rv_path = iv_cur_dir. ELSEIF iv_cd+0(1) = '/'. " Absolute path rv_path = iv_cd. ELSEIF iv_cd = '..'. " CD back IF iv_cur_dir = '/' OR iv_cur_dir = ''. " Back from root = root rv_path = iv_cur_dir. ELSE. lv_temp = reverse( iv_cur_dir ). IF lv_temp+0(1) = '/'. SHIFT lv_temp BY 1 PLACES LEFT. ENDIF. SHIFT lv_temp UP TO '/' LEFT. rv_path = reverse( lv_temp ). ENDIF. ELSEIF iv_cur_dir+lv_last(1) = '/'. " Append cd to cur_dir separated by / rv_path = iv_cur_dir && iv_cd. ELSE. rv_path = iv_cur_dir && '/' && iv_cd. ENDIF. " TODO: improve logic and cases ENDMETHOD. METHOD get_filename_from_syspath. DATA: lv_split TYPE c LENGTH 1, lv_index TYPE i, lt_split TYPE TABLE OF string. " filename | c:\filename | /dir/filename | \\server\filename IF iv_path CA '/'. lv_split = '/'. ELSE. lv_split = '\'. ENDIF. SPLIT iv_path AT lv_split INTO TABLE lt_split. lv_index = lines( lt_split ). READ TABLE lt_split INDEX lv_index INTO rv_filename. ENDMETHOD. METHOD is_root. rv_yes = boolc( iv_path = '/' ). ENDMETHOD. METHOD is_subdir. DATA lv_len TYPE i. DATA lv_last TYPE i. lv_len = strlen( iv_parent ). lv_last = lv_len - 1. rv_yes = boolc( strlen( iv_path ) > lv_len AND iv_path+0(lv_len) = iv_parent AND ( iv_parent+lv_last(1) = '/' OR iv_path+lv_len(1) = '/' ) ). ENDMETHOD. METHOD split_file_location. DATA: lv_cnt TYPE i, lv_len TYPE i. FIND FIRST OCCURRENCE OF REGEX '^/(.*/)?' IN iv_fullpath MATCH COUNT lv_cnt MATCH LENGTH lv_len. IF lv_cnt > 0. ev_path = iv_fullpath+0(lv_len). ev_filename = iv_fullpath+lv_len. ELSE. CLEAR ev_path. ev_filename = iv_fullpath. ENDIF. ev_filename = cl_http_utility=>unescape_url( escaped = ev_filename ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_log IMPLEMENTATION. METHOD constructor. zif_abapgit_log~set_title( iv_title ). ENDMETHOD. METHOD from_exception. CREATE OBJECT ro_log. IF io_x IS BOUND. ro_log->zif_abapgit_log~add_exception( io_x ). ENDIF. ENDMETHOD. METHOD get_messages_status. DATA lr_msg TYPE REF TO zif_abapgit_log=>ty_msg. rv_status = 'S'. LOOP AT it_msg REFERENCE INTO lr_msg. CASE lr_msg->type. WHEN 'E' OR 'A' OR 'X'. rv_status = 'E'. "not okay EXIT. WHEN 'W'. rv_status = 'W'. "maybe CONTINUE. WHEN 'S' OR 'I'. IF rv_status <> 'W'. rv_status = 'S'. "okay ENDIF. CONTINUE. WHEN OTHERS. "unknown CONTINUE. ENDCASE. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_log~add. FIELD-SYMBOLS: LIKE LINE OF mt_log. APPEND INITIAL LINE TO mt_log ASSIGNING . -msg-text = iv_msg. -msg-type = iv_type. -item = is_item. -exception = ix_exc. CASE iv_type. WHEN 'E' OR 'A' OR 'X'. -msg-level = zif_abapgit_log=>c_log_level-error. WHEN 'W'. -msg-level = zif_abapgit_log=>c_log_level-warning. WHEN 'S' OR 'I'. -msg-level = zif_abapgit_log=>c_log_level-info. WHEN OTHERS. "unknown ASSERT 0 = 1. ENDCASE. ENDMETHOD. METHOD zif_abapgit_log~add_error. zif_abapgit_log~add( iv_msg = iv_msg iv_type = 'E' is_item = is_item ). ENDMETHOD. METHOD zif_abapgit_log~add_exception. DATA lx_exc TYPE REF TO cx_root. DATA lv_msg TYPE string. lx_exc = ix_exc. DO. lv_msg = lx_exc->get_text( ). zif_abapgit_log~add( iv_msg = lv_msg iv_type = 'E' is_item = is_item ix_exc = lx_exc ). IF lx_exc->previous IS BOUND. lx_exc = lx_exc->previous. ELSE. EXIT. ENDIF. ENDDO. ENDMETHOD. METHOD zif_abapgit_log~add_info. zif_abapgit_log~add( iv_msg = iv_msg iv_type = 'I' is_item = is_item ). ENDMETHOD. METHOD zif_abapgit_log~add_success. zif_abapgit_log~add( iv_msg = iv_msg iv_type = 'S' is_item = is_item ). ENDMETHOD. METHOD zif_abapgit_log~add_warning. zif_abapgit_log~add( iv_msg = iv_msg iv_type = 'W' is_item = is_item ). ENDMETHOD. METHOD zif_abapgit_log~clear. CLEAR mt_log. ENDMETHOD. METHOD zif_abapgit_log~clone. DATA lo_log TYPE REF TO zcl_abapgit_log. CREATE OBJECT lo_log EXPORTING iv_title = mv_title. lo_log->mt_log = mt_log. ri_log = lo_log. ENDMETHOD. METHOD zif_abapgit_log~count. rv_count = lines( mt_log ). ENDMETHOD. METHOD zif_abapgit_log~get_item_status. DATA lr_log TYPE REF TO ty_log. DATA ls_msg TYPE zif_abapgit_log=>ty_msg. DATA ls_item_status TYPE zif_abapgit_log=>ty_item_status_out. DATA lr_item_status TYPE REF TO zif_abapgit_log=>ty_item_status_out. "collect all message for all objects LOOP AT mt_log REFERENCE INTO lr_log. CLEAR ls_item_status. ls_item_status-item = lr_log->item. READ TABLE rt_item_status REFERENCE INTO lr_item_status WITH KEY item-obj_type = ls_item_status-item-obj_type item-obj_name = ls_item_status-item-obj_name. IF sy-subrc <> 0. INSERT ls_item_status INTO TABLE rt_item_status. GET REFERENCE OF ls_item_status INTO lr_item_status. ENDIF. CLEAR ls_msg. ls_msg-type = lr_log->msg-type. ls_msg-text = lr_log->msg-text. INSERT ls_msg INTO TABLE lr_item_status->messages. ENDLOOP. "determine object status from object messages LOOP AT rt_item_status REFERENCE INTO lr_item_status. lr_item_status->status = get_messages_status( lr_item_status->messages ). IF lr_item_status->messages IS INITIAL. CLEAR ls_msg. ls_msg-type = 'I'. ls_msg-text = 'No message'. INSERT ls_msg INTO TABLE lr_item_status->messages. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_log~get_log_level. FIELD-SYMBOLS LIKE LINE OF mt_log. rv_level = zif_abapgit_log=>c_log_level-empty. LOOP AT mt_log ASSIGNING . IF -msg-level = zif_abapgit_log=>c_log_level-error. rv_level = zif_abapgit_log=>c_log_level-error. EXIT. ELSEIF -msg-level > rv_level. rv_level = -msg-level. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_log~get_messages. DATA ls_msg TYPE zif_abapgit_log~ty_log_out. FIELD-SYMBOLS TYPE ty_log. LOOP AT mt_log ASSIGNING . ls_msg-type = -msg-type. ls_msg-text = -msg-text. ls_msg-obj_type = -item-obj_type. ls_msg-obj_name = -item-obj_name. ls_msg-exception = -exception. APPEND ls_msg TO rt_msg. ENDLOOP. DELETE ADJACENT DUPLICATES FROM rt_msg. ENDMETHOD. METHOD zif_abapgit_log~get_status. DATA lr_log TYPE REF TO ty_log. rv_status = zif_abapgit_log=>c_status-ok. LOOP AT mt_log REFERENCE INTO lr_log. CASE lr_log->msg-type. WHEN 'E' OR 'A' OR 'X'. rv_status = zif_abapgit_log=>c_status-error. EXIT. WHEN 'W'. rv_status = zif_abapgit_log=>c_status-warning. CONTINUE. WHEN 'S' OR 'I'. IF rv_status <> zif_abapgit_log=>c_status-warning. rv_status = zif_abapgit_log=>c_status-ok. ENDIF. CONTINUE. WHEN OTHERS. "unknown ASSERT 0 = 1. ENDCASE. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_log~get_title. rv_title = mv_title. IF rv_title IS INITIAL. rv_title = 'Log'. ENDIF. ENDMETHOD. METHOD zif_abapgit_log~merge_with. DATA lo_log TYPE REF TO zcl_abapgit_log. DATA lt_log_temp LIKE lo_log->mt_log. IF ii_log IS BOUND. lo_log ?= ii_log. IF iv_min_level > 0. lt_log_temp = lo_log->mt_log. DELETE lt_log_temp WHERE msg-level < iv_min_level. APPEND LINES OF lt_log_temp TO mt_log. ELSE. APPEND LINES OF lo_log->mt_log TO mt_log. ENDIF. ENDIF. ri_log = me. ENDMETHOD. METHOD zif_abapgit_log~set_title. mv_title = iv_title. ri_log = me. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_diff IMPLEMENTATION. METHOD adjust_diff. " ABAP kernel diff traverses files from bottom up which leads to odd display of diffs " SAP won't adjust this kernel service so we will do it here " https://github.com/abapGit/abapGit/issues/4395 TYPES: BEGIN OF ty_diff_block, start TYPE i, len TYPE i, END OF ty_diff_block. DATA: lv_block_begin TYPE i, lv_block_end TYPE i, ls_diff_block TYPE ty_diff_block, lt_diff_block TYPE STANDARD TABLE OF ty_diff_block WITH DEFAULT KEY. FIELD-SYMBOLS: LIKE LINE OF mt_diff, LIKE LINE OF mt_diff, LIKE LINE OF mt_diff. " Determine start and length of diff blocks LOOP AT mt_diff ASSIGNING . IF -result = zif_abapgit_definitions=>c_diff-insert OR -result = zif_abapgit_definitions=>c_diff-delete. IF ls_diff_block IS INITIAL. ls_diff_block-start = sy-tabix. ENDIF. ls_diff_block-len = ls_diff_block-len + 1. ELSEIF ls_diff_block-start IS NOT INITIAL. APPEND ls_diff_block TO lt_diff_block. CLEAR ls_diff_block. ENDIF. ENDLOOP. " For each diff block, check if beginning is same as end of block " If yes, move diff block down LOOP AT lt_diff_block INTO ls_diff_block. DO ls_diff_block-len TIMES. lv_block_begin = ls_diff_block-start + sy-index - 1. READ TABLE mt_diff ASSIGNING INDEX lv_block_begin. IF sy-subrc <> 0. EXIT. ENDIF. lv_block_end = ls_diff_block-start + ls_diff_block-len + sy-index - 1. READ TABLE mt_diff ASSIGNING INDEX lv_block_end. IF sy-subrc <> 0. EXIT. ENDIF. CASE -result. WHEN zif_abapgit_definitions=>c_diff-insert. IF -new = -new. -old_num = -old_num. -old = -old. -result = -result. CLEAR: -result, -old_num, -old. ELSE. EXIT. ENDIF. WHEN zif_abapgit_definitions=>c_diff-delete. IF -old = -old. -new_num = -new_num. -new = -new. -result = -result. CLEAR: -result, -new_num, -new. ELSE. EXIT. ENDIF. WHEN OTHERS. EXIT. ENDCASE. ENDDO. ENDLOOP. ENDMETHOD. METHOD calculate_stats. FIELD-SYMBOLS: LIKE LINE OF mt_diff. LOOP AT mt_diff ASSIGNING . CASE -result. WHEN zif_abapgit_definitions=>c_diff-insert. ms_stats-insert = ms_stats-insert + 1. WHEN zif_abapgit_definitions=>c_diff-delete. ms_stats-delete = ms_stats-delete + 1. WHEN zif_abapgit_definitions=>c_diff-update. ms_stats-update = ms_stats-update + 1. ENDCASE. ENDLOOP. ENDMETHOD. METHOD compute_and_render. DATA: lv_i TYPE i, ls_diff LIKE LINE OF rt_diff, lt_delta TYPE STANDARD TABLE OF rsedcresul WITH DEFAULT KEY. FIELD-SYMBOLS: LIKE LINE OF it_old, LIKE LINE OF it_new, LIKE LINE OF lt_delta. " Note: Ignore case is for keywords, variables, types etc, but not for literals CALL FUNCTION 'RS_CMP_COMPUTE_DELTA' EXPORTING compare_mode = mv_compare_mode ignore_case_differences = mv_ignore_case TABLES text_tab1 = it_new text_tab2 = it_old text_tab_res = lt_delta EXCEPTIONS parameter_invalid = 1 difference_not_found = 2 OTHERS = 3. IF sy-subrc = 0. " Process delta LOOP AT lt_delta ASSIGNING . CLEAR ls_diff. IF -line1 > 0. lv_i = -line1. ls_diff-old_num = lv_i. ls_diff-old = -text1. ENDIF. IF -line2 > 0. lv_i = -line2. ls_diff-new_num = lv_i. ls_diff-new = -text2. ENDIF. IF -flag1 = 'D'. ls_diff-result = zif_abapgit_definitions=>c_diff-delete. ELSEIF -flag2 = 'I'. ls_diff-result = zif_abapgit_definitions=>c_diff-insert. ELSEIF -flag1 = 'M' AND -flag2 = 'M'. ls_diff-result = zif_abapgit_definitions=>c_diff-update. ELSEIF -flag1 = '' AND -flag2 = ''. ls_diff-result = zif_abapgit_definitions=>c_diff-unchanged. ELSEIF -flag1 = '' AND -flag2 = 'E'. " ignore comment ls_diff-result = zif_abapgit_definitions=>c_diff-unchanged. ELSEIF -flag1 = 'E' AND -flag2 = ''. " ignore comment ls_diff-result = zif_abapgit_definitions=>c_diff-unchanged. ELSE. ASSERT 0 = 1. " unknown comparison result ENDIF. APPEND ls_diff TO rt_diff. ENDLOOP. ELSEIF sy-subrc = 2. " Copy input... but it might not be identical LOOP AT it_old ASSIGNING . CLEAR ls_diff. ls_diff-old_num = sy-tabix. ls_diff-old = . READ TABLE it_new ASSIGNING INDEX sy-tabix. ASSERT sy-subrc = 0. ls_diff-new_num = sy-tabix. ls_diff-new = . " SAP function ignores lines that contain only whitespace so we compare directly IF ( mv_compare_mode = 1 OR mv_compare_mode = 3 ) AND <> AND ( strlen( condense( ) ) = 0 OR strlen( condense( ) ) = 0 ). ls_diff-result = zif_abapgit_definitions=>c_diff-update. ENDIF. APPEND ls_diff TO rt_diff. ENDLOOP. ELSE. ASSERT 0 = 1. " incorrect function call ENDIF. ENDMETHOD. METHOD constructor. DATA: lt_new TYPE rswsourcet, lt_old TYPE rswsourcet. mv_compare_mode = 1. IF iv_ignore_indentation = abap_true. mv_compare_mode = mv_compare_mode + 1. ENDIF. IF iv_ignore_comments = abap_true. mv_compare_mode = mv_compare_mode + 2. ENDIF. mv_ignore_case = iv_ignore_case. unpack( EXPORTING iv_new = iv_new iv_old = iv_old IMPORTING et_new = lt_new et_old = lt_old ). mt_diff = compute_and_render( it_new = lt_new it_old = lt_old ). adjust_diff( ). calculate_stats( ). map_beacons( ). shortlist( ). ENDMETHOD. METHOD create_regex_set. DATA: lo_regex TYPE REF TO cl_abap_regex, lt_regex TYPE zif_abapgit_definitions=>ty_string_tt, lv_regex LIKE LINE OF lt_regex. APPEND '^\s*(CLASS|FORM|MODULE|REPORT|METHOD|INTERFACE|FUNCTION)\s[^=]' TO lt_regex. APPEND '^\s*(PUBLIC|PROTECTED|PRIVATE)\sSECTION(\s|\.)' TO lt_regex. APPEND '^\s*(CLASS|INTERFACE|FUNCTION|TYPE)-POOL\s' TO lt_regex. APPEND '^\s*(START|END)-OF-SELECTION(\s|\.)' TO lt_regex. APPEND '^\s*INITIALIZATION(\s|\.)' TO lt_regex. APPEND '^\s*(TOP-OF-PAGE|END-OF-PAGE)(\s|\.)' TO lt_regex. APPEND '^\s*AT\s*(SELECTION-SCREEN|LINE-SELECTION|USER-COMMAND|PF\d+)(\s|\.)' TO lt_regex. APPEND '^\s*(DEFINE|ENHANCEMENT)\s' TO lt_regex. LOOP AT lt_regex INTO lv_regex. CREATE OBJECT lo_regex EXPORTING pattern = lv_regex ignore_case = abap_true. APPEND lo_regex TO rt_regex_set. ENDLOOP. ENDMETHOD. METHOD get. rt_diff = mt_diff. ENDMETHOD. METHOD get_beacons. rt_beacons = mt_beacons. ENDMETHOD. METHOD is_line_patched. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. READ TABLE mt_diff INDEX iv_index ASSIGNING . IF sy-subrc = 0. rv_patched = -patch_flag. ELSE. zcx_abapgit_exception=>raise( |Diff line not found { iv_index }| ). ENDIF. ENDMETHOD. METHOD map_beacons. DATA: lv_beacon_idx TYPE i VALUE c_starting_beacon, lv_offs TYPE i, lv_beacon_str TYPE string, lv_beacon_2lev TYPE string, lv_submatch TYPE string, lo_regex TYPE REF TO cl_abap_regex, lt_regex TYPE ty_regexset_tt. FIELD-SYMBOLS: LIKE LINE OF mt_diff. lt_regex = create_regex_set( ). LOOP AT mt_diff ASSIGNING . CLEAR lv_offs. -beacon = lv_beacon_idx. LOOP AT lt_regex INTO lo_regex. FIND FIRST OCCURRENCE OF REGEX lo_regex IN -new SUBMATCHES lv_submatch. IF sy-subrc = 0. " Match lv_beacon_str = -new. lv_submatch = to_upper( lv_submatch ). " Get rid of comments and end of line FIND FIRST OCCURRENCE OF '.' IN lv_beacon_str MATCH OFFSET lv_offs. IF sy-subrc <> 0. FIND FIRST OCCURRENCE OF '"' IN lv_beacon_str MATCH OFFSET lv_offs. ENDIF. IF lv_offs > 0. lv_beacon_str = lv_beacon_str(lv_offs). ENDIF. lv_beacon_str = condense( val = lv_beacon_str del = ` ` ). IF lv_submatch = 'CLASS'. lv_beacon_2lev = replace( val = lv_beacon_str regex = '\s+(DEFINITION|IMPLEMENTATION)' with = '' occ = 0 ). ELSEIF lv_submatch = 'METHOD'. lv_beacon_str = lv_beacon_2lev && ` => ` && lv_beacon_str. ELSEIF lv_submatch = 'PUBLIC' OR lv_submatch = 'PROTECTED' OR lv_submatch = 'PRIVATE'. lv_beacon_str = lv_beacon_2lev && ` ` && lv_beacon_str. ENDIF. APPEND lv_beacon_str TO mt_beacons. lv_beacon_idx = sy-tabix. -beacon = lv_beacon_idx. EXIT. "Loop ENDIF. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD set_patch_by_old_diff. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. LOOP AT mt_diff ASSIGNING USING KEY new_num WHERE old = is_diff_old-old AND new = is_diff_old-new AND new_num = is_diff_old-new_num AND old_num = is_diff_old-old_num. -patch_flag = iv_patch_flag. EXIT. ENDLOOP. ENDMETHOD. METHOD set_patch_new. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. READ TABLE mt_diff WITH TABLE KEY new_num COMPONENTS new_num = iv_line_new ASSIGNING . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Invalid new line number { iv_line_new }| ). ENDIF. -patch_flag = iv_patch_flag. ENDMETHOD. METHOD set_patch_old. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_diff. READ TABLE mt_diff WITH TABLE KEY old_num COMPONENTS old_num = iv_line_old ASSIGNING . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Invalid old line number { iv_line_old }| ). ENDIF. -patch_flag = iv_patch_flag. ENDMETHOD. METHOD shortlist. DATA: lv_index TYPE i. FIELD-SYMBOLS: LIKE LINE OF mt_diff. IF lines( mt_diff ) < 20. LOOP AT mt_diff ASSIGNING . -short = abap_true. ENDLOOP. ELSE. LOOP AT mt_diff TRANSPORTING NO FIELDS WHERE NOT result IS INITIAL AND short = abap_false. lv_index = sy-tabix. DO 8 TIMES. " Backward READ TABLE mt_diff INDEX ( lv_index - sy-index ) ASSIGNING . IF sy-subrc <> 0 OR -short = abap_true. " tab bound or prev marker EXIT. ENDIF. -short = abap_true. ENDDO. DO 8 TIMES. " Forward READ TABLE mt_diff INDEX ( lv_index + sy-index - 1 ) ASSIGNING . IF sy-subrc <> 0. " tab bound reached EXIT. ENDIF. CHECK -short = abap_false. " skip marked -short = abap_true. ENDDO. ENDLOOP. ENDIF. ENDMETHOD. METHOD stats. rs_count = ms_stats. ENDMETHOD. METHOD unpack. DATA: lv_new TYPE string, lv_old TYPE string, lv_new_last TYPE c LENGTH 1, lv_old_last TYPE c LENGTH 1. lv_new = zcl_abapgit_convert=>xstring_to_string_utf8( iv_new ). lv_old = zcl_abapgit_convert=>xstring_to_string_utf8( iv_old ). " Check if one value contains a final newline but the other not " If yes, add a special character that's visible in diff render IF lv_new IS NOT INITIAL. lv_new_last = substring( val = lv_new off = strlen( lv_new ) - 1 ). ENDIF. IF lv_old IS NOT INITIAL. lv_old_last = substring( val = lv_old off = strlen( lv_old ) - 1 ). ENDIF. IF lv_new_last = cl_abap_char_utilities=>newline AND lv_old_last <> cl_abap_char_utilities=>newline AND lv_old IS NOT INITIAL. lv_old = lv_old && cl_abap_char_utilities=>form_feed. ELSEIF lv_new_last <> cl_abap_char_utilities=>newline AND lv_old_last = cl_abap_char_utilities=>newline AND lv_new IS NOT INITIAL. lv_new = lv_new && cl_abap_char_utilities=>form_feed. ENDIF. SPLIT lv_new AT cl_abap_char_utilities=>newline INTO TABLE et_new. SPLIT lv_old AT cl_abap_char_utilities=>newline INTO TABLE et_old. ENDMETHOD. ENDCLASS. CLASS kHGwldKtJfHZXmphMQgfeIQhGnfrcH DEFINITION DEFERRED. CLASS kHGwldKtJfHZXmphMQgfcZaQwkuAox DEFINITION DEFERRED. CLASS kHGwldKtJfHZXmphMQgfQYNhjRNkGw DEFINITION DEFERRED. * renamed: zcl_abapgit_convert :: lcl_in CLASS kHGwldKtJfHZXmphMQgfQYNhjRNkGw DEFINITION. PUBLIC SECTION. CLASS-METHODS convert IMPORTING !iv_data TYPE xsequence !iv_length TYPE i OPTIONAL RETURNING VALUE(rv_string) TYPE string RAISING zcx_abapgit_exception. PRIVATE SECTION. CLASS-DATA go_conv_new TYPE REF TO object. CLASS-DATA go_conv_old TYPE REF TO object. ENDCLASS. CLASS kHGwldKtJfHZXmphMQgfQYNhjRNkGw IMPLEMENTATION. METHOD convert. DATA lv_class TYPE string. DATA lx_error TYPE REF TO cx_root. IF go_conv_new IS INITIAL AND go_conv_old IS INITIAL. TRY. CALL METHOD ('CL_ABAP_CONV_CODEPAGE')=>create_in RECEIVING instance = go_conv_new. CATCH cx_sy_dyn_call_illegal_class. lv_class = 'CL_ABAP_CONV_IN_CE'. CALL METHOD (lv_class)=>create EXPORTING encoding = 'UTF-8' RECEIVING conv = go_conv_old. ENDTRY. ENDIF. TRY. IF go_conv_new IS NOT INITIAL. CALL METHOD go_conv_new->('IF_ABAP_CONV_IN~CONVERT') EXPORTING source = iv_data RECEIVING result = rv_string. ELSE. CALL METHOD go_conv_old->('CONVERT') EXPORTING input = iv_data n = iv_length IMPORTING data = rv_string. ENDIF. CATCH cx_parameter_invalid_range cx_sy_codepage_converter_init cx_sy_conversion_codepage cx_parameter_invalid_type INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. * renamed: zcl_abapgit_convert :: lcl_out CLASS kHGwldKtJfHZXmphMQgfcZaQwkuAox DEFINITION. PUBLIC SECTION. CLASS-METHODS convert IMPORTING !iv_string TYPE string RETURNING VALUE(rv_xstring) TYPE xstring RAISING zcx_abapgit_exception. PRIVATE SECTION. CLASS-DATA go_conv_new TYPE REF TO object. CLASS-DATA go_conv_old TYPE REF TO object. ENDCLASS. CLASS kHGwldKtJfHZXmphMQgfcZaQwkuAox IMPLEMENTATION. METHOD convert. DATA lx_error TYPE REF TO cx_root. DATA lv_class TYPE string. IF go_conv_new IS INITIAL AND go_conv_old IS INITIAL. TRY. CALL METHOD ('CL_ABAP_CONV_CODEPAGE')=>create_out RECEIVING instance = go_conv_new. CATCH cx_sy_dyn_call_illegal_class. lv_class = 'CL_ABAP_CONV_OUT_CE'. CALL METHOD (lv_class)=>create EXPORTING encoding = 'UTF-8' RECEIVING conv = go_conv_old. ENDTRY. ENDIF. TRY. IF go_conv_new IS NOT INITIAL. CALL METHOD go_conv_new->('IF_ABAP_CONV_OUT~CONVERT') EXPORTING source = iv_string RECEIVING result = rv_xstring. ELSE. CALL METHOD go_conv_old->('CONVERT') EXPORTING data = iv_string IMPORTING buffer = rv_xstring. ENDIF. CATCH cx_parameter_invalid_range cx_sy_codepage_converter_init cx_sy_conversion_codepage cx_parameter_invalid_type INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. * renamed: zcl_abapgit_convert :: lcl_bcp47_language_table CLASS kHGwldKtJfHZXmphMQgfeIQhGnfrcH DEFINITION CREATE PRIVATE. PUBLIC SECTION. TYPES: BEGIN OF ty_language_mapping, sap1_code TYPE sy-langu, bcp47_code TYPE string, END OF ty_language_mapping, ty_language_mappings TYPE STANDARD TABLE OF ty_language_mapping WITH DEFAULT KEY. CLASS-DATA gv_language_mappings TYPE ty_language_mappings. CLASS-METHODS: sap1_to_bcp47 IMPORTING im_sap1 TYPE sy-langu RETURNING VALUE(re_bcp47) TYPE string RAISING zcx_abapgit_exception, bcp47_to_sap1 IMPORTING im_bcp47 TYPE string RETURNING VALUE(re_sap1) TYPE sy-langu RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CLASS-METHODS fill_language_mappings. CLASS-METHODS fill_language_mappings_1. CLASS-METHODS fill_language_mappings_2. CLASS-METHODS fill_language_mapping IMPORTING im_sap1 TYPE string im_bcp47 TYPE string. ENDCLASS. CLASS kHGwldKtJfHZXmphMQgfeIQhGnfrcH IMPLEMENTATION. METHOD sap1_to_bcp47. DATA lv_language_mapping TYPE ty_language_mapping. IF gv_language_mappings IS INITIAL OR lines( gv_language_mappings ) = 0. fill_language_mappings( ). ENDIF. LOOP AT gv_language_mappings INTO lv_language_mapping WHERE sap1_code = im_sap1. IF re_bcp47 IS INITIAL OR strlen( re_bcp47 ) > strlen( lv_language_mapping-bcp47_code ). re_bcp47 = lv_language_mapping-bcp47_code. ENDIF. ENDLOOP. IF re_bcp47 IS INITIAL. zcx_abapgit_exception=>raise( |Could not map SAP1 language code { im_sap1 } to BCP47 language code.| ). ENDIF. ENDMETHOD. METHOD bcp47_to_sap1. DATA lv_language_mapping TYPE ty_language_mapping. IF gv_language_mappings IS INITIAL OR lines( gv_language_mappings ) = 0. fill_language_mappings( ). ENDIF. LOOP AT gv_language_mappings INTO lv_language_mapping. IF to_lower( lv_language_mapping-bcp47_code ) = to_lower( im_bcp47 ) AND re_sap1 IS INITIAL. re_sap1 = lv_language_mapping-sap1_code. ENDIF. ENDLOOP. IF re_sap1 IS INITIAL. zcx_abapgit_exception=>raise( |Could not map BCP47 language code { im_bcp47 } to SAP1 language code.| ). ENDIF. ENDMETHOD. METHOD fill_language_mapping. DATA lv_line TYPE ty_language_mapping. DATA lv_sap1 TYPE sy-langu. IF strlen( im_sap1 ) = 4. lv_sap1 = cl_abap_conv_in_ce=>uccp( im_sap1 ). ELSEIF strlen( im_sap1 ) = 1. lv_sap1 = im_sap1. ENDIF. lv_line-bcp47_code = im_bcp47. lv_line-sap1_code = lv_sap1. APPEND lv_line TO gv_language_mappings. CLEAR lv_line. ENDMETHOD. METHOD fill_language_mappings. " table is filled with two separate methods to comply " with https://rules.abaplint.org/method_length/ fill_language_mappings_1( ). fill_language_mappings_2( ). ENDMETHOD. METHOD fill_language_mappings_1. fill_language_mapping( im_sap1 = 'a' im_bcp47 = 'af' ). fill_language_mapping( im_sap1 = 'BF51' im_bcp47 = 'sq' ). fill_language_mapping( im_sap1 = 'BA15' im_bcp47 = 'eu' ). fill_language_mapping( im_sap1 = 'B8F3' im_bcp47 = 'bs' ). fill_language_mapping( im_sap1 = 'W' im_bcp47 = 'bg' ). fill_language_mapping( im_sap1 = 'c' im_bcp47 = 'ca' ). fill_language_mapping( im_sap1 = '1' im_bcp47 = 'zh' ). fill_language_mapping( im_sap1 = '1' im_bcp47 = 'zh-Hans' ). fill_language_mapping( im_sap1 = 'B343' im_bcp47 = 'zh-SG' ). fill_language_mapping( im_sap1 = 'M' im_bcp47 = 'zh-Hant' ). fill_language_mapping( im_sap1 = '6' im_bcp47 = 'hr' ). fill_language_mapping( im_sap1 = 'C' im_bcp47 = 'cs' ). fill_language_mapping( im_sap1 = 'K' im_bcp47 = 'da' ). fill_language_mapping( im_sap1 = 'N' im_bcp47 = 'nl' ). fill_language_mapping( im_sap1 = 'N' im_bcp47 = 'nl-NL' ). fill_language_mapping( im_sap1 = 'B284' im_bcp47 = 'nl-BE' ). fill_language_mapping( im_sap1 = 'E' im_bcp47 = 'en' ). fill_language_mapping( im_sap1 = 'E' im_bcp47 = 'en-US' ). fill_language_mapping( im_sap1 = 'B46E' im_bcp47 = 'en-GB' ). fill_language_mapping( im_sap1 = 'B285' im_bcp47 = 'en-AU' ). fill_language_mapping( im_sap1 = 'B2E5' im_bcp47 = 'en-BZ' ). fill_language_mapping( im_sap1 = 'B345' im_bcp47 = 'en-CA' ). fill_language_mapping( im_sap1 = 'B405' im_bcp47 = 'en-HK' ). fill_language_mapping( im_sap1 = 'B465' im_bcp47 = 'en-IN' ). fill_language_mapping( im_sap1 = 'B4C5' im_bcp47 = 'en-ID' ). fill_language_mapping( im_sap1 = 'B525' im_bcp47 = 'en-IE' ). fill_language_mapping( im_sap1 = 'B585' im_bcp47 = 'en-JM' ). fill_language_mapping( im_sap1 = 'B225' im_bcp47 = 'en-MY' ). fill_language_mapping( im_sap1 = 'B28E' im_bcp47 = 'en-NZ' ). fill_language_mapping( im_sap1 = 'B2EE' im_bcp47 = 'en-PH' ). fill_language_mapping( im_sap1 = 'B34E' im_bcp47 = 'en-SG' ). fill_language_mapping( im_sap1 = 'B3AE' im_bcp47 = 'en-ZA' ). fill_language_mapping( im_sap1 = 'B40E' im_bcp47 = 'en-TT' ). fill_language_mapping( im_sap1 = 'B4CE' im_bcp47 = 'en-ZW' ). fill_language_mapping( im_sap1 = '9' im_bcp47 = 'et' ). fill_language_mapping( im_sap1 = 'U' im_bcp47 = 'fi' ). fill_language_mapping( im_sap1 = 'F' im_bcp47 = 'fr' ). fill_language_mapping( im_sap1 = 'F' im_bcp47 = 'fr-FR' ). fill_language_mapping( im_sap1 = 'B286' im_bcp47 = 'fr-BE' ). fill_language_mapping( im_sap1 = 'B2E6' im_bcp47 = 'fr-CM' ). ENDMETHOD. METHOD fill_language_mappings_2. fill_language_mapping( im_sap1 = 'B346' im_bcp47 = 'fr-CA' ). fill_language_mapping( im_sap1 = 'B3A6' im_bcp47 = 'fr-CG' ). fill_language_mapping( im_sap1 = 'B406' im_bcp47 = 'fr-CI' ). fill_language_mapping( im_sap1 = 'B466' im_bcp47 = 'fr-HT' ). fill_language_mapping( im_sap1 = 'B4C6' im_bcp47 = 'fr-LU' ). fill_language_mapping( im_sap1 = 'B526' im_bcp47 = 'fr-ML' ). fill_language_mapping( im_sap1 = 'B586' im_bcp47 = 'fr-MC' ). fill_language_mapping( im_sap1 = 'B288' im_bcp47 = 'fr-MA' ). fill_language_mapping( im_sap1 = 'B2E8' im_bcp47 = 'fr-RE' ). fill_language_mapping( im_sap1 = 'B348' im_bcp47 = 'fr-SN' ). fill_language_mapping( im_sap1 = 'B3A8' im_bcp47 = 'fr-CH' ). fill_language_mapping( im_sap1 = 'BAC4' im_bcp47 = 'gd' ). fill_language_mapping( im_sap1 = 'BACC' im_bcp47 = 'gl' ). fill_language_mapping( im_sap1 = 'D' im_bcp47 = 'de' ). fill_language_mapping( im_sap1 = 'D' im_bcp47 = 'de-DE' ). fill_language_mapping( im_sap1 = 'B287' im_bcp47 = 'de-AT' ). fill_language_mapping( im_sap1 = 'B2E7' im_bcp47 = 'de-LI' ). fill_language_mapping( im_sap1 = 'B347' im_bcp47 = 'de-LU' ). fill_language_mapping( im_sap1 = 'B3A7' im_bcp47 = 'de-CH' ). fill_language_mapping( im_sap1 = 'G' im_bcp47 = 'el' ). fill_language_mapping( im_sap1 = 'B' im_bcp47 = 'he' ). fill_language_mapping( im_sap1 = 'H' im_bcp47 = 'hu' ). fill_language_mapping( im_sap1 = 'b' im_bcp47 = 'is' ). fill_language_mapping( im_sap1 = 'i' im_bcp47 = 'id' ). fill_language_mapping( im_sap1 = 'BAC1' im_bcp47 = 'ga' ). fill_language_mapping( im_sap1 = 'I' im_bcp47 = 'it' ). fill_language_mapping( im_sap1 = 'I' im_bcp47 = 'it-IT' ). fill_language_mapping( im_sap1 = 'B289' im_bcp47 = 'it-CH' ). fill_language_mapping( im_sap1 = 'J' im_bcp47 = 'ja' ). fill_language_mapping( im_sap1 = '3' im_bcp47 = 'ko' ). fill_language_mapping( im_sap1 = '3' im_bcp47 = 'ko-KR' ). fill_language_mapping( im_sap1 = 'Y' im_bcp47 = 'lv' ). fill_language_mapping( im_sap1 = 'X' im_bcp47 = 'lt' ). fill_language_mapping( im_sap1 = '7' im_bcp47 = 'ms' ). fill_language_mapping( im_sap1 = '7' im_bcp47 = 'ms-MY' ). fill_language_mapping( im_sap1 = 'B28D' im_bcp47 = 'ms-BN' ). fill_language_mapping( im_sap1 = 'O' im_bcp47 = 'no' ). fill_language_mapping( im_sap1 = 'L' im_bcp47 = 'pl' ). fill_language_mapping( im_sap1 = 'P' im_bcp47 = 'pt' ). fill_language_mapping( im_sap1 = 'P' im_bcp47 = 'pt-BR' ). fill_language_mapping( im_sap1 = 'BEED' im_bcp47 = 'rm' ). fill_language_mapping( im_sap1 = '4' im_bcp47 = 'ro' ). fill_language_mapping( im_sap1 = '4' im_bcp47 = 'ro-RO' ). fill_language_mapping( im_sap1 = 'R' im_bcp47 = 'ru-RU' ). fill_language_mapping( im_sap1 = '0' im_bcp47 = 'sr' ). fill_language_mapping( im_sap1 = '0' im_bcp47 = 'sr-Cyrl' ). fill_language_mapping( im_sap1 = 'd' im_bcp47 = 'sr-Latn' ). fill_language_mapping( im_sap1 = 'Q' im_bcp47 = 'sk' ). fill_language_mapping( im_sap1 = '5' im_bcp47 = 'sl' ). fill_language_mapping( im_sap1 = 'BF42' im_bcp47 = 'wen' ). fill_language_mapping( im_sap1 = 'B9B3' im_bcp47 = 'dsb' ). fill_language_mapping( im_sap1 = 'BB33' im_bcp47 = 'hsb' ). fill_language_mapping( im_sap1 = 'S' im_bcp47 = 'es' ). fill_language_mapping( im_sap1 = 'S' im_bcp47 = 'es-ES' ). fill_language_mapping( im_sap1 = 'B293' im_bcp47 = 'es-AR' ). fill_language_mapping( im_sap1 = 'B2F3' im_bcp47 = 'es-BO' ). fill_language_mapping( im_sap1 = 'B353' im_bcp47 = 'es-CL' ). fill_language_mapping( im_sap1 = 'B233' im_bcp47 = 'es-CO' ). fill_language_mapping( im_sap1 = 'B3B3' im_bcp47 = 'es-CR' ). fill_language_mapping( im_sap1 = 'B413' im_bcp47 = 'es-DO' ). fill_language_mapping( im_sap1 = 'B473' im_bcp47 = 'es-EC' ). fill_language_mapping( im_sap1 = 'B4D3' im_bcp47 = 'es-SV' ). fill_language_mapping( im_sap1 = 'B533' im_bcp47 = 'es-GT' ). fill_language_mapping( im_sap1 = 'B593' im_bcp47 = 'es-HN' ). fill_language_mapping( im_sap1 = 'B298' im_bcp47 = 'es-MX' ). fill_language_mapping( im_sap1 = 'B2F8' im_bcp47 = 'es-NI' ). fill_language_mapping( im_sap1 = 'B358' im_bcp47 = 'es-PA' ). fill_language_mapping( im_sap1 = 'B3B8' im_bcp47 = 'es-PY' ). fill_language_mapping( im_sap1 = 'B418' im_bcp47 = 'es-PE' ). fill_language_mapping( im_sap1 = 'B478' im_bcp47 = 'es-PR' ). fill_language_mapping( im_sap1 = 'B4D8' im_bcp47 = 'es-UY' ). fill_language_mapping( im_sap1 = 'B538' im_bcp47 = 'es-VE' ). fill_language_mapping( im_sap1 = 'BF57' im_bcp47 = 'sw' ). fill_language_mapping( im_sap1 = 'V' im_bcp47 = 'sv' ). fill_language_mapping( im_sap1 = 'BFAC' im_bcp47 = 'tl' ). fill_language_mapping( im_sap1 = '2' im_bcp47 = 'th' ). fill_language_mapping( im_sap1 = 'T' im_bcp47 = 'tr' ). fill_language_mapping( im_sap1 = '8' im_bcp47 = 'uk' ). fill_language_mapping( im_sap1 = 'C069' im_bcp47 = 'vi' ). fill_language_mapping( im_sap1 = 'C0C1' im_bcp47 = 'wa' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_convert IMPLEMENTATION. METHOD base64_to_xstring. rv_xstr = cl_http_utility=>decode_x_base64( iv_base64 ). ENDMETHOD. METHOD bitbyte_to_int. DATA: lv_bitbyte TYPE string, lv_len TYPE i, lv_offset TYPE i. lv_bitbyte = iv_bits. SHIFT lv_bitbyte LEFT DELETING LEADING '0 '. lv_len = strlen( lv_bitbyte ). lv_offset = lv_len - 1. rv_int = 0. DO lv_len TIMES. IF sy-index = 1. "Initialize IF lv_bitbyte+lv_offset(1) = '1'. rv_int = 1. ENDIF. ELSEIF lv_bitbyte+lv_offset(1) = '1'. rv_int = rv_int + ( 2 ** ( sy-index - 1 ) ). ENDIF. lv_offset = lv_offset - 1. "Move Cursor ENDDO. ENDMETHOD. METHOD conversion_exit_isola_output. language_sap1_to_sap2( EXPORTING im_lang_sap1 = iv_spras RECEIVING re_lang_sap2 = rv_spras EXCEPTIONS no_assignment = 1 OTHERS = 2 ). "#EC CI_SUBRC TRANSLATE rv_spras TO UPPER CASE. ENDMETHOD. METHOD int_to_xstring4. * returns xstring of length 4 containing the integer value iv_i DATA lv_x TYPE x LENGTH 4. lv_x = iv_i. rv_xstring = lv_x. ENDMETHOD. METHOD language_sap1_to_bcp47. DATA lv_converter_instance TYPE REF TO object. DATA lv_converter_class_name TYPE string VALUE `CL_AFF_LANGUAGE_CONVERTER`. DATA lv_converter_method TYPE string VALUE `SAP1_TO_BCP47`. TRY. CALL METHOD (lv_converter_class_name)=>create_instance RECEIVING result = lv_converter_instance. CALL METHOD lv_converter_instance->(lv_converter_method) EXPORTING language = im_lang_sap1 RECEIVING result = re_lang_bcp47 EXCEPTIONS no_assignment = 1 OTHERS = 2. IF sy-subrc <> 0. RAISE no_assignment. ENDIF. CATCH cx_sy_dyn_call_error. TRY. re_lang_bcp47 = kHGwldKtJfHZXmphMQgfeIQhGnfrcH=>sap1_to_bcp47( im_lang_sap1 ). CATCH zcx_abapgit_exception. RAISE no_assignment. ENDTRY. ENDTRY. ENDMETHOD. METHOD language_bcp47_to_sap1. DATA lv_converter_instance TYPE REF TO object. DATA lv_converter_class_name TYPE string VALUE `CL_AFF_LANGUAGE_CONVERTER`. DATA lv_converter_method TYPE string VALUE `SAP1_TO_BCP47`. DATA lv_regex TYPE REF TO cl_abap_regex. DATA lv_abap_matcher TYPE REF TO cl_abap_matcher. DATA lv_sap2_lang_code TYPE laiso. TRY. CALL METHOD (lv_converter_class_name)=>create_instance RECEIVING result = lv_converter_instance. CALL METHOD lv_converter_instance->(lv_converter_method) EXPORTING language = im_lang_bcp47 RECEIVING result = re_lang_sap1 EXCEPTIONS no_assignment = 1 OTHERS = 2. IF sy-subrc <> 0. RAISE no_assignment. ENDIF. CATCH cx_sy_dyn_call_error. TRY. re_lang_sap1 = kHGwldKtJfHZXmphMQgfeIQhGnfrcH=>bcp47_to_sap1( im_lang_bcp47 ). CATCH zcx_abapgit_exception. CREATE OBJECT lv_regex EXPORTING pattern = `[A-Z0-9]{2}`. lv_abap_matcher = lv_regex->create_matcher( text = im_lang_bcp47 ). IF abap_true = lv_abap_matcher->match( ). "Fallback try to convert from SAP language lv_sap2_lang_code = im_lang_bcp47. language_sap2_to_sap1( EXPORTING im_lang_sap2 = lv_sap2_lang_code RECEIVING re_lang_sap1 = re_lang_sap1 EXCEPTIONS no_assignment = 1 OTHERS = 2 ). IF sy-subrc <> 0. RAISE no_assignment. ENDIF. ELSE. RAISE no_assignment. ENDIF. ENDTRY. ENDTRY. ENDMETHOD. METHOD language_sap1_to_sap2. DATA lv_class TYPE string. TRY. SELECT SINGLE languageisocode FROM ('I_LANGUAGE') INTO re_lang_sap2 WHERE language = im_lang_sap1. IF sy-subrc <> 0. RAISE no_assignment. ENDIF. CATCH cx_sy_dynamic_osql_error. lv_class = 'CL_I18N_LANGUAGES'. CALL METHOD (lv_class)=>sap1_to_sap2 EXPORTING im_lang_sap1 = im_lang_sap1 RECEIVING re_lang_sap2 = re_lang_sap2 EXCEPTIONS no_assignment = 1 OTHERS = 2. IF sy-subrc = 1. RAISE no_assignment. ENDIF. ENDTRY. ENDMETHOD. METHOD language_sap2_to_sap1. DATA lv_class TYPE string. TRY. SELECT SINGLE language FROM ('I_LANGUAGE') INTO re_lang_sap1 WHERE languageisocode = im_lang_sap2. IF sy-subrc <> 0. RAISE no_assignment. ENDIF. CATCH cx_sy_dynamic_osql_error. lv_class = 'CL_I18N_LANGUAGES'. CALL METHOD (lv_class)=>sap2_to_sap1 EXPORTING im_lang_sap2 = im_lang_sap2 RECEIVING re_lang_sap1 = re_lang_sap1 EXCEPTIONS no_assignment = 1 OTHERS = 2. IF sy-subrc = 1. RAISE no_assignment. ENDIF. ENDTRY. ENDMETHOD. METHOD split_string. FIND FIRST OCCURRENCE OF cl_abap_char_utilities=>cr_lf IN iv_string. " Convert string into table depending on separator type CR_LF vs. LF IF sy-subrc = 0. SPLIT iv_string AT cl_abap_char_utilities=>cr_lf INTO TABLE rt_lines. ELSE. SPLIT iv_string AT cl_abap_char_utilities=>newline INTO TABLE rt_lines. ENDIF. ENDMETHOD. METHOD string_to_tab. DATA lv_length TYPE i. DATA lv_iterations TYPE i. DATA lv_offset TYPE i. FIELD-SYMBOLS TYPE any. CLEAR et_tab. ev_size = strlen( iv_str ). APPEND INITIAL LINE TO et_tab ASSIGNING . = iv_str. lv_length = cl_abap_typedescr=>describe_by_data( )->length / cl_abap_char_utilities=>charsize. lv_iterations = ev_size DIV lv_length. DO lv_iterations TIMES. lv_offset = sy-index * lv_length. APPEND INITIAL LINE TO et_tab ASSIGNING . = iv_str+lv_offset. ENDDO. ENDMETHOD. METHOD string_to_xstring. rv_xstr = string_to_xstring_utf8( iv_str ). ENDMETHOD. METHOD string_to_xstring_utf8. rv_xstring = kHGwldKtJfHZXmphMQgfcZaQwkuAox=>convert( iv_string ). ENDMETHOD. METHOD string_to_xstring_utf8_bom. IF iv_string IS INITIAL. RETURN. ENDIF. rv_xstring = string_to_xstring_utf8( iv_string ). " Add UTF-8 BOM IF xstrlen( rv_xstring ) < 3 OR rv_xstring(3) <> cl_abap_char_utilities=>byte_order_mark_utf8. rv_xstring = cl_abap_char_utilities=>byte_order_mark_utf8 && rv_xstring. ENDIF. ENDMETHOD. METHOD xstring_remove_bom. rv_xstr = iv_xstr. " cl_abap_conv_in_ce does not handle BOM in non-Unicode systems, so we remove it IF cl_abap_char_utilities=>charsize = 1 AND xstrlen( rv_xstr ) > 3 AND rv_xstr(3) = cl_abap_char_utilities=>byte_order_mark_utf8. rv_xstr = rv_xstr+3. ENDIF. ENDMETHOD. METHOD xstring_to_bintab. DATA lv_length TYPE i. DATA lv_iterations TYPE i. DATA lv_offset TYPE i. DATA lv_struct TYPE abap_bool. FIELD-SYMBOLS TYPE any. CLEAR et_bintab. ev_size = xstrlen( iv_xstr ). APPEND INITIAL LINE TO et_bintab ASSIGNING . lv_struct = boolc( cl_abap_typedescr=>describe_by_data( )->type_kind = cl_abap_typedescr=>typekind_struct1 ). IF lv_struct = abap_true. ASSIGN COMPONENT 1 OF STRUCTURE TO . ENDIF. = iv_xstr. lv_length = cl_abap_typedescr=>describe_by_data( )->length. lv_iterations = ev_size DIV lv_length. DO lv_iterations TIMES. lv_offset = sy-index * lv_length. APPEND INITIAL LINE TO et_bintab ASSIGNING . IF lv_struct = abap_true. ASSIGN COMPONENT 1 OF STRUCTURE TO . ENDIF. = iv_xstr+lv_offset. ENDDO. ENDMETHOD. METHOD xstring_to_int. * use the built-in type conversion rv_i = iv_xstring. ENDMETHOD. METHOD xstring_to_string_utf8. DATA lv_data TYPE xstring. DATA lv_length TYPE i. " Remove BOM for non-Unicode systems lv_data = xstring_remove_bom( iv_data ). lv_length = iv_length. IF lv_length <= 0. lv_length = xstrlen( lv_data ). ENDIF. rv_string = kHGwldKtJfHZXmphMQgfQYNhjRNkGw=>convert( iv_data = lv_data iv_length = lv_length ). ENDMETHOD. METHOD xstring_to_string_utf8_bom. DATA lv_xstring TYPE xstring. IF iv_xstring IS INITIAL. RETURN. ENDIF. lv_xstring = iv_xstring. " Add UTF-8 BOM IF xstrlen( lv_xstring ) < 3 OR lv_xstring(3) <> cl_abap_char_utilities=>byte_order_mark_utf8. lv_xstring = cl_abap_char_utilities=>byte_order_mark_utf8 && lv_xstring. ENDIF. rv_string = xstring_to_string_utf8( lv_xstring ). ENDMETHOD. METHOD x_to_bitbyte. CLEAR rv_bitbyte. GET BIT 1 OF iv_x INTO rv_bitbyte+0(1). GET BIT 2 OF iv_x INTO rv_bitbyte+1(1). GET BIT 3 OF iv_x INTO rv_bitbyte+2(1). GET BIT 4 OF iv_x INTO rv_bitbyte+3(1). GET BIT 5 OF iv_x INTO rv_bitbyte+4(1). GET BIT 6 OF iv_x INTO rv_bitbyte+5(1). GET BIT 7 OF iv_x INTO rv_bitbyte+6(1). GET BIT 8 OF iv_x INTO rv_bitbyte+7(1). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ui_factory IMPLEMENTATION. METHOD get_asset_manager. DATA lo_buf TYPE REF TO zcl_abapgit_string_buffer. DATA li_asset_man TYPE REF TO zif_abapgit_gui_asset_manager. CREATE OBJECT lo_buf. li_asset_man = zcl_abapgit_gui_asset_manager=>create( ). **************************************************** * abapmerge Pragma [include] - ZABAPGIT_CSS_COMMON.W3MI.DATA.CSS **************************************************** lo_buf->add( '/*' ). lo_buf->add( ' * ABAPGIT COMMON CSS' ). lo_buf->add( ' */' ). lo_buf->add( '' ). lo_buf->add( '/* GLOBALS */' ). lo_buf->add( '' ). lo_buf->add( 'body {' ). lo_buf->add( ' overflow-x: hidden;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'body.centered {' ). lo_buf->add( ' max-width: 1280px;' ). lo_buf->add( ' margin: 0 auto;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'body.full_width {' ). lo_buf->add( ' width:100%;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'a, a:visited {' ). lo_buf->add( ' text-decoration: none;' ). lo_buf->add( '}' ). lo_buf->add( 'a:hover, a:active {' ). lo_buf->add( ' cursor: pointer;' ). lo_buf->add( ' text-decoration: underline;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'img {' ). lo_buf->add( ' border-width: 0px;' ). lo_buf->add( ' vertical-align: middle;' ). lo_buf->add( '}' ). lo_buf->add( 'table { border-collapse: collapse; }' ). lo_buf->add( 'pre { display: inline; }' ). lo_buf->add( 'sup {' ). lo_buf->add( ' vertical-align: top;' ). lo_buf->add( ' position: relative;' ). lo_buf->add( ' top: -0.5em;' ). lo_buf->add( ' font-size: 75%;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'input, textarea, select {' ). lo_buf->add( ' padding: 3px 0.5em;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( 'input:focus, textarea:focus {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.cursor-pointer {' ). lo_buf->add( ' cursor: pointer;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'span.separator {' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( ' padding-right: 0.5em;' ). lo_buf->add( ' opacity: 0.25;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* MODIFIERS */' ). lo_buf->add( '' ). lo_buf->add( '.emphasis { font-weight: bold !important; }' ). lo_buf->add( '.crossout { text-decoration: line-through !important; }' ). lo_buf->add( '.right { text-align:right; }' ). lo_buf->add( '.center { text-align:center; }' ). lo_buf->add( '.paddings { padding: 0.5em 0.5em; }' ). lo_buf->add( '.pad-sides { padding-left: 0.3em; padding-right: 0.3em; }' ). lo_buf->add( '.pad-1em { padding: 1em 1em; }' ). lo_buf->add( '.margin-v5 { margin-top: 0.5em; margin-bottom: 0.5em; }' ). lo_buf->add( '.margin-v1 { margin-top: 1em; margin-bottom: 1em; }' ). lo_buf->add( '.indent5em { padding-left: 0.5em; }' ). lo_buf->add( '.pad4px { padding: 4px; }' ). lo_buf->add( '.w100 { width: 100%; }' ). lo_buf->add( '.wmin { width: 1%; }' ). lo_buf->add( '.w40 { width: 40%; }' ). lo_buf->add( '.float-right { float: right; }' ). lo_buf->add( '.pad-right { padding-right: 6px; }' ). lo_buf->add( '.no-pad { padding: 0px !important; }' ). lo_buf->add( '.inline { display: inline; }' ). lo_buf->add( '.hidden { visibility: hidden; }' ). lo_buf->add( '.nodisplay { display: none }' ). lo_buf->add( '.m-em5-sides { margin-left: 0.5em; margin-right: 0.5em }' ). lo_buf->add( '.w600px { width: 600px }' ). lo_buf->add( '.w800px { width: 800px }' ). lo_buf->add( '.w1000px { width: 1000px }' ). lo_buf->add( '.wmax600px { max-width: 600px }' ). lo_buf->add( '.auto-center { /* use with max-width */' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( ' margin-left: auto;' ). lo_buf->add( ' margin-right: auto;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'span.boxed {' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' padding: 4px 7px;' ). lo_buf->add( ' margin-left: 0.2em;' ). lo_buf->add( ' margin-right: 0.2em;' ). lo_buf->add( ' font-size: smaller;' ). lo_buf->add( '}' ). lo_buf->add( 'span.boxed i.icon {' ). lo_buf->add( ' padding-right: 5px;' ). lo_buf->add( '}' ). lo_buf->add( '.red-filled-set {' ). lo_buf->add( ' border-width: 0px;' ). lo_buf->add( ' color: hsl(0, 78%, 93%);' ). lo_buf->add( ' background-color: hsl(0, 78%, 65%);' ). lo_buf->add( '}' ). lo_buf->add( '.green-filled-set {' ). lo_buf->add( ' border-width: 0px;' ). lo_buf->add( ' color: hsl(120, 45%, 90%);' ). lo_buf->add( ' background-color: hsl(120, 27%, 60%);' ). lo_buf->add( '}' ). lo_buf->add( '.yellow-filled-set {' ). lo_buf->add( ' border-width: 0px;' ). lo_buf->add( ' color: hsl(45, 99%, 90%);' ). lo_buf->add( ' background-color: hsl(45, 100%, 46%);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* PANELS */' ). lo_buf->add( '' ). lo_buf->add( 'div.panel {' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' padding: 0.5em 0.5em;' ). lo_buf->add( ' margin: 0.5em 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.dummydiv {' ). lo_buf->add( ' padding: 0.5em 1em;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'a.close-btn {' ). lo_buf->add( ' text-decoration: none;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* STRUCTURE DIVS, HEADER & FOOTER */' ). lo_buf->add( '' ). lo_buf->add( 'div#header {' ). lo_buf->add( ' padding: 0.5em 0.5em;' ). lo_buf->add( ' border-bottom: 3px double;' ). lo_buf->add( '}' ). lo_buf->add( 'div#header > div { display: inline-block }' ). lo_buf->add( '' ). lo_buf->add( '.logo .icon { display: inline-block }' ). lo_buf->add( '.logo .icon:before { width: auto }' ). lo_buf->add( '' ). lo_buf->add( '/* official logo colors, not vars, redefine in themes directly*/' ). lo_buf->add( '.logo .icon.icon-git-alt { color: #f03c2e }' ). lo_buf->add( '.logo .icon.icon-abapgit {' ). lo_buf->add( ' color: #362701;' ). lo_buf->add( ' vertical-align: bottom;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div#header .logo { font-size: x-large }' ). lo_buf->add( 'div#header .page-title { font-size: x-large }' ). lo_buf->add( 'div#header span.spacer {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' padding-right: 0.25em;' ). lo_buf->add( ' padding-left: 0.25em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div#footer .sponsor a { font-size: smaller; }' ). lo_buf->add( 'div#footer .logo { font-size: large }' ). lo_buf->add( 'div#footer {' ). lo_buf->add( ' padding: 0.5em 0.5em;' ). lo_buf->add( ' border-top: 3px double;' ). lo_buf->add( '}' ). lo_buf->add( 'div#footer .version {' ). lo_buf->add( ' margin-top: 0.5em;' ). lo_buf->add( ' font-size: small;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '#debug-output {' ). lo_buf->add( ' text-align: right;' ). lo_buf->add( ' padding-right: 0.5em;' ). lo_buf->add( ' font-size: smaller;' ). lo_buf->add( '}' ). lo_buf->add( '#debug-output p {' ). lo_buf->add( ' margin-top: 0em;' ). lo_buf->add( ' margin-bottom: 0em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* ERROR LOG */' ). lo_buf->add( '' ). lo_buf->add( 'div.log {' ). lo_buf->add( ' padding: 6px;' ). lo_buf->add( ' margin: 4px;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-radius: 4px;' ). lo_buf->add( '}' ). lo_buf->add( 'div.log > span { display:block; }' ). lo_buf->add( 'div.log .icon { padding-right: 6px; }' ). lo_buf->add( '' ). lo_buf->add( '/* REPOSITORY */' ). lo_buf->add( '' ). lo_buf->add( 'div.repo {' ). lo_buf->add( ' padding: 0.5em 1em 0.5em 1em;' ). lo_buf->add( ' position: relative;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_name span.name {' ). lo_buf->add( ' font-weight: bold;' ). lo_buf->add( ' font-size: 14pt;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_name a.url {' ). lo_buf->add( ' font-size: 12pt;' ). lo_buf->add( ' margin-left: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_name span.url {' ). lo_buf->add( ' font-size: 12pt;' ). lo_buf->add( ' margin-left: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_name .icon {' ). lo_buf->add( ' padding-right: 4px;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_attr {' ). lo_buf->add( ' font-size: 12pt;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_attr span {' ). lo_buf->add( ' margin-left: 0.2em;' ). lo_buf->add( ' margin-right: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_attr span.bg_marker {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' font-size: 8pt;' ). lo_buf->add( ' padding: 4px 2px 3px 2px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* ABAPGIT OBJECTS */' ). lo_buf->add( '' ). lo_buf->add( 'span.branch,' ). lo_buf->add( 'span.user-box,' ). lo_buf->add( 'span.package-box,' ). lo_buf->add( 'span.path-box,' ). lo_buf->add( 'span.transport-box {' ). lo_buf->add( ' padding: 2px 4px;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-radius: 4px;' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'span.package-box i.icon {' ). lo_buf->add( ' margin-right: 0.15em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* MISC AND REFACTOR */' ). lo_buf->add( '' ). lo_buf->add( '.hidden-submit {' ). lo_buf->add( ' border: 0 none;' ). lo_buf->add( ' height: 0;' ). lo_buf->add( ' width: 0;' ). lo_buf->add( ' padding: 0;' ). lo_buf->add( ' margin: 0;' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' overflow: hidden;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* STATE BLOCK COMMON*/' ). lo_buf->add( '' ). lo_buf->add( 'span.state-block {' ). lo_buf->add( ' margin-left: 1em;' ). lo_buf->add( ' font-family: Consolas, "Lucida Console", Courier, monospace;' ). lo_buf->add( ' font-size: x-small;' ). lo_buf->add( ' vertical-align: 13%;' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( ' white-space: nowrap;' ). lo_buf->add( '}' ). lo_buf->add( 'span.state-block span {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' padding: 0px 3px;' ). lo_buf->add( ' border-width: 1px;' ). lo_buf->add( ' border-style: solid;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* REPOSITORY TABLE*/' ). lo_buf->add( '' ). lo_buf->add( 'div.repo_container {' ). lo_buf->add( ' position: relative;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.repo_banner {' ). lo_buf->add( ' margin: 0em 1em 1em;' ). lo_buf->add( ' padding: 0.5em 0.5em;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( ' font-size: 85%;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.repo_tab {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( ' line-height: 1.2;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_tab th {' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( ' padding: 0.5em;' ). lo_buf->add( ' border-bottom: 1px solid;' ). lo_buf->add( ' font-weight: normal;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_tab td {' ). lo_buf->add( ' vertical-align: middle;' ). lo_buf->add( ' padding-top: 2px;' ). lo_buf->add( ' padding-bottom: 2px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab td.icon {' ). lo_buf->add( ' width: 1px;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( ' padding-left: 8px;' ). lo_buf->add( ' padding-right: 4px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab td.transport {' ). lo_buf->add( ' width: 140px;' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_tab td.type {' ). lo_buf->add( ' width: 4em;' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab td.filename{' ). lo_buf->add( ' padding-left: 1em;' ). lo_buf->add( ' word-break: break-all;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab td.object {' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab td.files {' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( ' line-height: 1.5;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab tr.object_row{' ). lo_buf->add( ' border-top: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab td.cmd, .repo_tab th.cmd {' ). lo_buf->add( ' text-align: right;' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( ' padding-right: 0.7em;' ). lo_buf->add( ' min-width: 70px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab th.cmd .icon{' ). lo_buf->add( ' padding-right: 8px;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_tab tr:first-child td { border-top: 0px; }' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab tr:hover td {' ). lo_buf->add( ' background-image: linear-gradient(rgba(0, 0, 0, 0.075), rgba(0, 0, 0, 0.075));' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* STAGE */' ). lo_buf->add( '' ). lo_buf->add( 'th.stage-status { width: 30px; }' ). lo_buf->add( 'th.stage-objtype { width: 30px; }' ). lo_buf->add( 'input.stage-filter { width: 18em; }' ). lo_buf->add( '' ). lo_buf->add( '.stage_tab {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' margin-top: 0.2em;' ). lo_buf->add( ' line-height: 1.5;' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td {' ). lo_buf->add( ' border-top: 1px solid;' ). lo_buf->add( ' vertical-align: middle;' ). lo_buf->add( ' padding: 2px 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab th {' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( ' font-weight: normal;' ). lo_buf->add( ' padding: 4px 0.5em;' ). lo_buf->add( ' border-bottom: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td.status {' ). lo_buf->add( ' width: 2em;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td.highlight {' ). lo_buf->add( ' font-weight: bold;' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td.name {' ). lo_buf->add( ' word-break: break-all;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.stage_tab tr:first-child td { border-top: 0px; }' ). lo_buf->add( '' ). lo_buf->add( '.stage_tab tr:hover td {' ). lo_buf->add( ' background-image: linear-gradient(rgba(0, 0, 0, 0.075), rgba(0, 0, 0, 0.075));' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.stage_tab td.cmd { cursor: pointer; }' ). lo_buf->add( '.stage_tab td.cmd a { padding: 0px 4px; }' ). lo_buf->add( '.stage_tab th.cmd a { padding: 0px 4px; }' ). lo_buf->add( '.stage_tab tbody tr:first-child td { padding-top: 0.5em; }' ). lo_buf->add( '.stage_tab tbody tr:last-child td { padding-bottom: 0.5em; }' ). lo_buf->add( '' ). lo_buf->add( '/* COMMIT */' ). lo_buf->add( '' ). lo_buf->add( 'div.form-container {' ). lo_buf->add( ' padding: 1em 1em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'form.aligned-form {' ). lo_buf->add( ' display: table;' ). lo_buf->add( ' border-spacing: 2px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'form.aligned-form label {' ). lo_buf->add( ' padding-right: 1em;' ). lo_buf->add( ' vertical-align: middle;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'form.aligned-form select {' ). lo_buf->add( ' padding-right: 1em;' ). lo_buf->add( ' vertical-align: middle;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'form.aligned-form span.sub-title {' ). lo_buf->add( ' font-size: smaller;' ). lo_buf->add( ' padding-top: 8px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'form.aligned-form div.row { display: table-row; }' ). lo_buf->add( 'form.aligned-form label { display: table-cell; }' ). lo_buf->add( 'form.aligned-form input { display: table-cell; }' ). lo_buf->add( 'form.aligned-form input[type="text"] { width: 25em; }' ). lo_buf->add( 'form.aligned-form span.cell { display: table-cell; }' ). lo_buf->add( '' ). lo_buf->add( '/* SETTINGS STYLES */' ). lo_buf->add( '' ). lo_buf->add( 'div.settings_container {' ). lo_buf->add( ' padding: 0.5em 0.5em 1em;' ). lo_buf->add( ' font-size: 10pt;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.settings_section {' ). lo_buf->add( ' margin-left:50px' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.settings td:first-child {' ). lo_buf->add( ' padding-left: 1em;' ). lo_buf->add( ' padding-right: 1em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* DIFF */' ). lo_buf->add( '' ). lo_buf->add( 'div.diff {' ). lo_buf->add( ' padding: 0.7em' ). lo_buf->add( '}' ). lo_buf->add( 'div.diff_head {' ). lo_buf->add( ' padding-bottom: 0.7em;' ). lo_buf->add( '}' ). lo_buf->add( 'span.diff_name {' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( 'span.diff_changed_by {' ). lo_buf->add( ' float: right;' ). lo_buf->add( '}' ). lo_buf->add( 'span.diff_banner {' ). lo_buf->add( ' border-style: solid;' ). lo_buf->add( ' border-width: 1px;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' padding-left: 0.3em;' ). lo_buf->add( ' padding-right: 0.3em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.diff_content {' ). lo_buf->add( ' border-top: 1px solid;' ). lo_buf->add( ' border-bottom: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.diff_content tbody tr td{' ). lo_buf->add( ' width: 50%;' ). lo_buf->add( ' vertical-align: top' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.diff_head span.state-block {' ). lo_buf->add( ' margin-left: 0.5em;' ). lo_buf->add( ' font-size: inherit;' ). lo_buf->add( ' vertical-align: initial;' ). lo_buf->add( '}' ). lo_buf->add( 'div.diff_head span.state-block span {' ). lo_buf->add( ' padding: 0px 4px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* DIFF TABLE */' ). lo_buf->add( '' ). lo_buf->add( 'table.diff_tab {' ). lo_buf->add( ' font-family: Consolas, Courier, monospace;' ). lo_buf->add( ' font-size: 10pt;' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab td,' ). lo_buf->add( 'table.diff_tab th {' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( ' padding-right: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab th {' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( ' font-weight: normal;' ). lo_buf->add( ' padding-top: 3px;' ). lo_buf->add( ' padding-bottom: 3px;' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab thead.header th {' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( ' font-weight: bold;' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( ' font-size: 9pt;' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab td.num, th.num {' ). lo_buf->add( ' width: 1%;' ). lo_buf->add( ' min-width: 2em;' ). lo_buf->add( ' padding-right: 8px;' ). lo_buf->add( ' padding-left: 8px;' ). lo_buf->add( ' text-align: right !important;' ). lo_buf->add( ' border-left: 1px solid;' ). lo_buf->add( ' border-right: 1px solid;' ). lo_buf->add( ' -ms-user-select: none;' ). lo_buf->add( ' user-select: none;' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab td.patch, th.patch {' ). lo_buf->add( ' width: 1%;' ). lo_buf->add( ' min-width: 1.5em;' ). lo_buf->add( ' padding-right: 8px;' ). lo_buf->add( ' padding-left: 8px;' ). lo_buf->add( ' text-align: right !important;' ). lo_buf->add( ' border-left: 1px solid;' ). lo_buf->add( ' border-right: 1px solid;' ). lo_buf->add( ' -ms-user-select: none;' ). lo_buf->add( ' user-select: none;' ). lo_buf->add( ' cursor: pointer;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.diff_tab tr.diff_line:hover td {' ). lo_buf->add( ' background-image: linear-gradient(rgba(0, 0, 0, 0.075), rgba(0, 0, 0, 0.075));' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.diff_tab td.num::before {' ). lo_buf->add( ' content: attr(line-num);' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab code {' ). lo_buf->add( ' font-family: inherit;' ). lo_buf->add( ' white-space: pre;' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab td.code {' ). lo_buf->add( ' word-wrap: break-word;' ). lo_buf->add( ' white-space: pre-wrap;' ). lo_buf->add( ' overflow: visible;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.diff_tab tbody tr:first-child td { padding-top: 0.5em; }' ). lo_buf->add( 'table.diff_tab tbody tr:last-child td { padding-bottom: 0.5em; }' ). lo_buf->add( '' ). lo_buf->add( 'table.diff_tab td.mark, th.mark {' ). lo_buf->add( ' width: 0.1%;' ). lo_buf->add( ' -ms-user-select: none;' ). lo_buf->add( ' user-select: none;' ). lo_buf->add( ' cursor: default;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.diff_select_left td.diff_right,' ). lo_buf->add( '.diff_select_left td.diff_right *,' ). lo_buf->add( '.diff_select_left th.diff_right,' ). lo_buf->add( '.diff_select_left th.diff_right *,' ). lo_buf->add( '.diff_select_right td.diff_left,' ). lo_buf->add( '.diff_select_right td.diff_left *,' ). lo_buf->add( '.diff_select_right th.diff_left,' ). lo_buf->add( '.diff_select_right th.diff_left * {' ). lo_buf->add( ' -ms-user-select: none;' ). lo_buf->add( ' user-select: none;' ). lo_buf->add( ' cursor: text;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.diff_select_left td.diff_left,' ). lo_buf->add( '.diff_select_left td.diff_left *,' ). lo_buf->add( '.diff_select_left th.diff_left,' ). lo_buf->add( '.diff_select_left th.diff_left *,' ). lo_buf->add( '.diff_select_right td.diff_right,' ). lo_buf->add( '.diff_select_right td.diff_right *,' ). lo_buf->add( '.diff_select_right th.diff_right,' ). lo_buf->add( '.diff_select_right th.diff_right * {' ). lo_buf->add( ' -ms-user-select: text;' ). lo_buf->add( ' user-select: text;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'td.diff_others::selection,' ). lo_buf->add( 'td.diff_others *::selection,' ). lo_buf->add( 'th.diff_others::selection,' ). lo_buf->add( 'th.diff_others *::selection {' ). lo_buf->add( ' background-color: transparent;' ). lo_buf->add( ' cursor: default;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.diff_select_left td.diff_right::selection,' ). lo_buf->add( '.diff_select_left td.diff_right *::selection,' ). lo_buf->add( '.diff_select_left th.diff_right::selection,' ). lo_buf->add( '.diff_select_left th.diff_right *::selection,' ). lo_buf->add( '.diff_select_right td.diff_left::selection,' ). lo_buf->add( '.diff_select_right td.diff_left *::selection,' ). lo_buf->add( '.diff_select_right th.diff_left::selection,' ). lo_buf->add( '.diff_select_right th.diff_left *::selection {' ). lo_buf->add( ' background-color: transparent;' ). lo_buf->add( ' cursor: text;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* DEBUG INFO STYLES */' ). lo_buf->add( '' ). lo_buf->add( 'div.debug_container {' ). lo_buf->add( ' padding: 0.5em;' ). lo_buf->add( ' font-size: 10pt;' ). lo_buf->add( ' font-family: Consolas, Courier, monospace;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.debug_container p {' ). lo_buf->add( ' margin: 0px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* *** */' ). lo_buf->add( '' ). lo_buf->add( 'li.action_link.enabled{' ). lo_buf->add( ' visibility: visible;' ). lo_buf->add( ' position: relative;' ). lo_buf->add( ' display: block;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'li.action_link:not(enabled){' ). lo_buf->add( ' visibility: hidden;' ). lo_buf->add( ' position: fixed; /* so it does not take up space when hidden */' ). lo_buf->add( ' display: none;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* TUTORIAL */' ). lo_buf->add( '' ). lo_buf->add( 'div.tutorial {' ). lo_buf->add( ' margin-top: 3px;' ). lo_buf->add( ' padding: 0.5em 1em 0.5em 1em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.tutorial li { margin: 2px 0px }' ). lo_buf->add( 'div.tutorial h1 { font-size: 18pt; }' ). lo_buf->add( 'div.tutorial h2 { font-size: 14pt;}' ). lo_buf->add( '' ). lo_buf->add( '/* MENU */' ). lo_buf->add( '' ). lo_buf->add( '/* Special credits to example at https://codepen.io/philhoyt/pen/ujHzd */' ). lo_buf->add( '/* container div, aligned left, but with .float-right modifier aligns right */' ). lo_buf->add( '' ). lo_buf->add( '.nav-container ul {' ). lo_buf->add( ' list-style: none;' ). lo_buf->add( ' position: relative;' ). lo_buf->add( ' float: left;' ). lo_buf->add( ' margin: 0;' ). lo_buf->add( ' padding: 0;' ). lo_buf->add( ' white-space: nowrap;' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( '}' ). lo_buf->add( '.nav-container.float-right ul { float: right; }' ). lo_buf->add( '' ). lo_buf->add( '.nav-container ul a {' ). lo_buf->add( ' display: block;' ). lo_buf->add( ' text-decoration: none;' ). lo_buf->add( ' line-height: 30px;' ). lo_buf->add( ' padding: 0 12px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* clearfix https://css-tricks.com/snippets/css/clear-fix/ */' ). lo_buf->add( '.nav-container:after {' ). lo_buf->add( ' clear: both;' ). lo_buf->add( ' display: block;' ). lo_buf->add( ' content: "";' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* submenues align to left or right border of the active item' ). lo_buf->add( ' depending on .float-right modifier */' ). lo_buf->add( '.nav-container ul li {' ). lo_buf->add( ' position: relative;' ). lo_buf->add( ' float: left;' ). lo_buf->add( ' margin: 0;' ). lo_buf->add( ' padding: 0;' ). lo_buf->add( '}' ). lo_buf->add( '.nav-container.float-right ul ul { left: auto; right: 0; }' ). lo_buf->add( '.nav-container ul li.current-menu-item { font-weight: 700; }' ). lo_buf->add( '.nav-container ul li.force-nav-hover ul { display: block; }' ). lo_buf->add( '.nav-container ul li:hover > ul { display: block; }' ). lo_buf->add( '' ). lo_buf->add( '/* special selection style for 1st level items (see also .corner below) */' ). lo_buf->add( '' ). lo_buf->add( '.nav-container ul ul {' ). lo_buf->add( ' display: none;' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' top: 100%;' ). lo_buf->add( ' left: 0;' ). lo_buf->add( ' z-index: 1;' ). lo_buf->add( ' padding: 0;' ). lo_buf->add( ' box-shadow: 1px 1px 3px 0px #bbb;' ). lo_buf->add( ' max-height: 700px;' ). lo_buf->add( ' overflow: auto;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.nav-container ul ul li {' ). lo_buf->add( ' float: none;' ). lo_buf->add( ' min-width: 160px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.nav-container ul ul a {' ). lo_buf->add( ' line-height: 120%;' ). lo_buf->add( ' padding: 8px 15px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.nav-container ul ul ul {' ). lo_buf->add( ' top: 0;' ). lo_buf->add( ' left: 100%;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.nav-container.float-right ul ul ul {' ). lo_buf->add( ' left: auto;' ). lo_buf->add( ' right: 100%;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* Minizone to extent hover area,' ). lo_buf->add( ' aligned to the left or to the right of the selected item' ). lo_buf->add( ' depending on .float-right modifier */' ). lo_buf->add( '.nav-container > ul > li > div.minizone {' ). lo_buf->add( ' display: none;' ). lo_buf->add( ' z-index: 1;' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' padding: 0px;' ). lo_buf->add( ' width: 16px;' ). lo_buf->add( ' height: 100%;' ). lo_buf->add( ' bottom: 0px;' ). lo_buf->add( ' left: 100%;' ). lo_buf->add( '}' ). lo_buf->add( '.nav-container > ul > li:hover div.minizone { display: block; }' ). lo_buf->add( '.nav-container.float-right > ul > li > div.minizone {' ). lo_buf->add( ' left: auto;' ). lo_buf->add( ' right: 100%;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* icons - text-align strictly left - otherwise look ugly' ). lo_buf->add( ' + bite a bit of left padding for nicer look' ). lo_buf->add( ' + forbids item text wrapping (maybe can be done differently) */' ). lo_buf->add( '.nav-container ul ul li a .icon {' ). lo_buf->add( ' padding-right: 10px;' ). lo_buf->add( ' margin-left: -3px;' ). lo_buf->add( '}' ). lo_buf->add( '.nav-container ul.with-icons li {' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( ' white-space: nowrap;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* Special .corner modifier - hangs menu at the top right corner' ). lo_buf->add( ' and cancels 1st level background coloring */' ). lo_buf->add( '.nav-container.corner {' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' right: 0px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* Toolbar separator style */' ). lo_buf->add( '.nav-container ul ul li.separator {' ). lo_buf->add( ' font-size: x-small;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( ' padding: 4px 0;' ). lo_buf->add( ' text-transform: uppercase;' ). lo_buf->add( ' border-bottom: 1px solid;' ). lo_buf->add( ' border-top: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( '.nav-container ul ul li.separator:first-child { border-top: none; }' ). lo_buf->add( '' ). lo_buf->add( '/* NEWS ANNOUNCEMENT */' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel {' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' z-index: 99;' ). lo_buf->add( ' top: 36px;' ). lo_buf->add( ' left: 50%;' ). lo_buf->add( ' width: 40em;' ). lo_buf->add( ' margin-left: -20em;' ). lo_buf->add( ' box-shadow: 1px 1px 3px 2px #dcdcdc;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel-fixed {' ). lo_buf->add( ' position: fixed;' ). lo_buf->add( ' top: 15%;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel div.info-hint {' ). lo_buf->add( ' text-transform: uppercase;' ). lo_buf->add( ' font-size: small;' ). lo_buf->add( ' padding: 8px 6px 0px;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel div.info-title {' ). lo_buf->add( ' text-transform: uppercase;' ). lo_buf->add( ' font-size: small;' ). lo_buf->add( ' padding: 6px;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel div.info-title a.close-btn {' ). lo_buf->add( ' padding-left: 12px;' ). lo_buf->add( ' padding-right: 2px;' ). lo_buf->add( ' position: relative;' ). lo_buf->add( ' bottom: 1px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel div.info-list {' ). lo_buf->add( ' padding: 0.8em 0.7em 1em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel ul {' ). lo_buf->add( ' padding-left: 10px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel li {' ). lo_buf->add( ' padding-left: 0px;' ). lo_buf->add( ' list-style-type: none;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel h1:first-child { margin: auto; }' ). lo_buf->add( 'div.info-panel h1 {' ). lo_buf->add( ' font-size: inherit;' ). lo_buf->add( ' padding: 6px 4px;' ). lo_buf->add( ' margin: 4px auto auto;' ). lo_buf->add( ' text-decoration: underline;' ). lo_buf->add( ' font-weight: normal;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel .version-marker {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' margin-left: 20px;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' padding: 0px 6px;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel .update { border: 1px solid; }' ). lo_buf->add( 'div.info-panel div.info-list td { padding-right: 1em }' ). lo_buf->add( '' ). lo_buf->add( '/* ERROR MESSAGE PANEL */' ). lo_buf->add( '' ). lo_buf->add( 'div.message-panel {' ). lo_buf->add( ' z-index: 99;' ). lo_buf->add( ' box-shadow: 2px 2px 4px 0px hsla(0, 0%, 0%, .1);' ). lo_buf->add( ' padding: 0.5em 1em;' ). lo_buf->add( ' position: fixed;' ). lo_buf->add( ' bottom: 12px;' ). lo_buf->add( ' width: 95%;' ). lo_buf->add( ' margin: 0 auto;' ). lo_buf->add( ' max-width: 1248px;' ). lo_buf->add( '' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-radius: 5px;' ). lo_buf->add( ' border-color: hsl(0, 42%, 64%);' ). lo_buf->add( ' background-color: hsla(0, 42%, 90%, 1);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.message-panel-bar {' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' bottom: 10px;' ). lo_buf->add( ' right: 10px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.message-panel-commands {' ). lo_buf->add( ' display: none;' ). lo_buf->add( ' margin-right: 2em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.message-panel-commands a {' ). lo_buf->add( ' padding: 0em 0.5em;' ). lo_buf->add( ' border-left: 1px solid;' ). lo_buf->add( ' border-left-color: #ccc;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.message-panel-commands a:first-child {' ). lo_buf->add( ' padding-left: 0;' ). lo_buf->add( ' border-left: none;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.message-panel:hover .message-panel-commands {' ). lo_buf->add( ' display: block;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* TOOLTIP TEXT */' ). lo_buf->add( '' ). lo_buf->add( '.link-hint {' ). lo_buf->add( ' line-height: 1em;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( ' padding: 5px 15px;' ). lo_buf->add( ' border-radius: 4px;' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' z-index: 1;' ). lo_buf->add( ' margin-top: -30px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.link-hint-a {' ). lo_buf->add( ' margin-left: -60px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.link-hint-input {' ). lo_buf->add( ' margin-left: -30px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.link-hint-i {' ). lo_buf->add( ' margin-left: -30px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.link-hint .pending { color: hsla(0, 0%, 0%, 0.2); }' ). lo_buf->add( '' ). lo_buf->add( '/* Tooltip arrow */' ). lo_buf->add( '.link-hint::after {' ). lo_buf->add( ' content: "";' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' top: 100%;' ). lo_buf->add( ' left: 50%;' ). lo_buf->add( ' margin-left: -5px;' ). lo_buf->add( ' border-width: 5px;' ). lo_buf->add( ' border-style: solid;' ). lo_buf->add( ' border-color: transparent;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* HOTKEYS */' ). lo_buf->add( '' ). lo_buf->add( 'ul.hotkeys {' ). lo_buf->add( ' list-style-type: none;' ). lo_buf->add( ' padding: 0;' ). lo_buf->add( ' margin: 0;' ). lo_buf->add( ' font-size: smaller;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'ul.hotkeys span.key-id {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' padding: 1px 7px;' ). lo_buf->add( ' width: 3em;' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( ' margin-top: 0.2em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'ul.hotkeys span.key-descr {' ). lo_buf->add( ' margin-left: 1.2em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.corner-hint {' ). lo_buf->add( ' position: fixed;' ). lo_buf->add( ' bottom: 10px;' ). lo_buf->add( ' right: 10px;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' padding: 4px;' ). lo_buf->add( ' font-size: smaller;' ). lo_buf->add( ' opacity: 0.5;' ). lo_buf->add( ' z-index: 99;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* Commit popup */' ). lo_buf->add( 'table.commit tr .title {' ). lo_buf->add( ' font-weight: bold;' ). lo_buf->add( ' vertical-align: top;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* Repo overview */' ). lo_buf->add( '.repo-overview {' ). lo_buf->add( ' padding: 0.5em 0.7em;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview table {' ). lo_buf->add( ' font-size: 90%;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview-toolbar {' ). lo_buf->add( ' padding: 1em 1em;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview-toolbar label {' ). lo_buf->add( ' margin-right: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview th {' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( ' font-weight: normal;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview table {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview thead tr {' ). lo_buf->add( ' border-bottom: 1px solid;' ). lo_buf->add( ' line-height: 1.5;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview tfoot tr {' ). lo_buf->add( ' border-top: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview tr.favorite .icon-star {' ). lo_buf->add( ' color: #5e8dc9 !important;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview td,' ). lo_buf->add( '.repo-overview th {' ). lo_buf->add( ' padding: 6px 6px; /* maybe use height ? */' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview .ro-detail { display: none; }' ). lo_buf->add( '.repo-overview .ro-go a {' ). lo_buf->add( ' padding: 0px 0.15em;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview .ro-go a:hover {' ). lo_buf->add( ' color: #ff721e;' ). lo_buf->add( ' text-decoration: none;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview td.labels {' ). lo_buf->add( ' max-width: 18ch;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* REPO LABELS */' ). lo_buf->add( '' ). lo_buf->add( '.repo-label-catalog {' ). lo_buf->add( ' padding: 1em 1em;' ). lo_buf->add( ' margin-top: -1em;' ). lo_buf->add( '}' ). lo_buf->add( '.repo-label-catalog label {' ). lo_buf->add( ' margin-right: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( 'ul.repo-labels {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' list-style-type: none;' ). lo_buf->add( ' padding-inline-start: 0px;' ). lo_buf->add( ' padding-left: 0px;' ). lo_buf->add( ' margin-block-start: 0px;' ). lo_buf->add( ' margin-block-end: 0px;' ). lo_buf->add( ' margin-top: 0px;' ). lo_buf->add( ' margin-bottom: 0px;' ). lo_buf->add( '}' ). lo_buf->add( 'ul.repo-labels li {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' padding: 3px 5px;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' border-style: solid;' ). lo_buf->add( ' border-width: 1px;' ). lo_buf->add( ' margin-bottom: 2px;' ). lo_buf->add( '}' ). lo_buf->add( 'ul.repo-labels li a {' ). lo_buf->add( ' color: inherit;' ). lo_buf->add( '}' ). lo_buf->add( 'ul.repo-labels li:not(:last-child) { margin-right: 0.3em; }' ). lo_buf->add( 'table ul.repo-labels li {' ). lo_buf->add( ' font-size: 90%;' ). lo_buf->add( ' padding: 2px 4px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* LABEL COLORS */' ). lo_buf->add( '' ). lo_buf->add( '.rl-white {' ). lo_buf->add( ' color: hsl(0, 0%, 30%);' ). lo_buf->add( ' background-color: hsl(0, 0%, 100%);' ). lo_buf->add( ' border-color: hsl(0, 0%, 80%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-white-b {' ). lo_buf->add( ' color: hsl(214, 100%, 60%);' ). lo_buf->add( ' background-color: hsl(0, 0%, 100%);' ). lo_buf->add( ' border-color: hsl(214, 89%, 86%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-white-r {' ). lo_buf->add( ' color: hsl(0, 100%, 41%);' ). lo_buf->add( ' background-color: hsl(0, 0%, 100%);' ). lo_buf->add( ' border-color: hsl(0, 100%, 85%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-grey {' ). lo_buf->add( ' color: hsl(0, 0%, 100%);' ). lo_buf->add( ' background-color: hsl(0, 0%, 70%);' ). lo_buf->add( ' border-color: hsl(0, 0%, 60%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-dark-w {' ). lo_buf->add( ' color: hsl(0, 0%, 100%);' ). lo_buf->add( ' background-color: hsl(0, 0%, 25%);' ). lo_buf->add( ' border-color: hsl(0, 0%, 25%);;' ). lo_buf->add( '}' ). lo_buf->add( '.rl-dark-y {' ). lo_buf->add( ' color: hsl(43, 95%, 75%);' ). lo_buf->add( ' background-color: hsl(0, 0%, 25%);' ). lo_buf->add( ' border-color: hsl(0, 0%, 25%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-dark-r {' ). lo_buf->add( ' color: hsl(0, 100%, 74%);' ). lo_buf->add( ' background-color: hsl(0, 0%, 25%);' ). lo_buf->add( ' border-color: hsl(0, 0%, 25%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-dark-b {' ). lo_buf->add( ' color: hsl(227, 92%, 80%);' ). lo_buf->add( ' background-color: hsl(0, 0%, 25%);' ). lo_buf->add( ' border-color: hsl(0, 0%, 25%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-lightblue {' ). lo_buf->add( ' color: hsl(217, 80%, 25%);' ). lo_buf->add( ' background-color: hsl(216, 76%, 84%);' ). lo_buf->add( ' border-color: hsl(216, 76%, 73%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-darkblue {' ). lo_buf->add( ' color: hsl(218, 77%, 88%);' ). lo_buf->add( ' background-color: hsl(217, 66%, 32%);' ). lo_buf->add( ' border-color: hsl(217, 66%, 20%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-lightgreen {' ). lo_buf->add( ' color: hsl(153, 76%, 18%);' ). lo_buf->add( ' background-color: hsl(152, 65%, 82%);' ). lo_buf->add( ' border-color: hsl(152, 65%, 65%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-darkgreen {' ). lo_buf->add( ' color: hsl(0, 0%, 100%);' ). lo_buf->add( ' background-color: hsl(153, 77%, 37%);' ). lo_buf->add( ' border-color: hsl(153, 77%, 30%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-lightred {' ). lo_buf->add( ' color: hsl(8, 86%, 29%);' ). lo_buf->add( ' background-color: hsl(8, 74%, 80%);' ). lo_buf->add( ' border-color: hsl(8, 74%, 70%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-darkred {' ). lo_buf->add( ' color: hsl(7, 76%, 85%);' ). lo_buf->add( ' background-color: hsl(8, 77%, 29%);' ). lo_buf->add( ' border-color: hsl(8, 77%, 20%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-yellow {' ). lo_buf->add( ' color: hsl(44, 87%, 22%);' ). lo_buf->add( ' background-color: hsl(44, 94%, 87%);' ). lo_buf->add( ' border-color: hsl(44, 94%, 70%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-darkyellow {' ). lo_buf->add( ' color: hsl(49, 100%, 24%);' ). lo_buf->add( ' background-color: hsl(49, 100%, 64%);' ). lo_buf->add( ' border-color: hsl(49, 100%, 49%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-orange {' ). lo_buf->add( ' color: hsl(0, 0%, 100%);' ). lo_buf->add( ' background-color: hsl(19, 100%, 61%);' ). lo_buf->add( ' border-color: hsl(19, 100%, 50%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-brown {' ). lo_buf->add( ' color: hsl(33, 100%, 89%);' ). lo_buf->add( ' background-color: hsl(33, 66%, 39%);' ). lo_buf->add( ' border-color: hsl(33, 66%, 30%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-pink {' ). lo_buf->add( ' color: hsl(340, 35%, 45%);' ). lo_buf->add( ' background-color: hsl(340, 85%, 77%);' ). lo_buf->add( ' border-color: hsl(340, 85%, 65%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-teal {' ). lo_buf->add( ' color: hsl(0, 0%, 100%);' ). lo_buf->add( ' background-color: hsl(191, 61%, 45%);' ). lo_buf->add( ' border-color: hsl(191, 61%, 37%);' ). lo_buf->add( '}' ). lo_buf->add( '.rl-darkviolet {' ). lo_buf->add( ' color: hsl(0, 0%, 100%);' ). lo_buf->add( ' background-color: hsl(258, 100%, 80%);' ). lo_buf->add( ' border-color: hsl(258, 100%, 72%);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* FORM FIELD HELP TOOLTIP */' ). lo_buf->add( '' ). lo_buf->add( '.form-field-help-tooltip {' ). lo_buf->add( ' position: relative;' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( '}' ). lo_buf->add( '.form-field-help-tooltip .form-field-help-tooltip-text {' ). lo_buf->add( ' visibility: hidden;' ). lo_buf->add( ' width: 40ch;' ). lo_buf->add( ' border-radius: 5px;' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' z-index: 1;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' padding: 0.4em 0.6em;' ). lo_buf->add( ' text-align: justify;' ). lo_buf->add( '}' ). lo_buf->add( '.form-field-help-tooltip .form-field-help-tooltip-text p {' ). lo_buf->add( ' margin: 0px;' ). lo_buf->add( '}' ). lo_buf->add( '.form-field-help-tooltip .form-field-help-tooltip-text {' ). lo_buf->add( ' background-color: white;' ). lo_buf->add( ' border-color: #888;' ). lo_buf->add( '}' ). lo_buf->add( '.form-field-help-tooltip:hover .form-field-help-tooltip-text {' ). lo_buf->add( ' visibility: visible;' ). lo_buf->add( '}' ). lo_buf->add( '.form-field-help-tooltip code {' ). lo_buf->add( ' border-radius: 5px;' ). lo_buf->add( ' font-size: 90%;' ). lo_buf->add( ' padding: 0.1em 0.4em;' ). lo_buf->add( ' background-color: #e2e2e2;' ). lo_buf->add( ' word-wrap: break-word;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* TABLE COMPONENT DEFAULT STYLE */' ). lo_buf->add( '' ). lo_buf->add( 'div.default-table-container {' ). lo_buf->add( ' padding: 6px 0.5em;' ). lo_buf->add( ' background-color: white;' ). lo_buf->add( ' border-radius: 6px;' ). lo_buf->add( ' overflow-x: hidden;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.default-table {' ). lo_buf->add( ' line-height: 1.5;' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.default-table thead tr:last-child {' ). lo_buf->add( ' border-bottom: #efefef solid 1px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.default-table td,' ). lo_buf->add( 'table.default-table th {' ). lo_buf->add( ' padding: 6px 8px;' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.default-table th {' ). lo_buf->add( ' white-space: nowrap;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.default-table th span.sort-arrow {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' color: hsla(0, 0%, 0%, 0.15);' ). lo_buf->add( ' width: 1em; /*for constant width*/' ). lo_buf->add( ' text-align: right;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.default-table th span.sort-active {' ). lo_buf->add( ' color: #4078c0;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.default-table th {' ). lo_buf->add( ' padding-bottom: 10px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* CODE INSPECTOR */' ). lo_buf->add( '' ). lo_buf->add( 'div.ci {' ). lo_buf->add( ' margin-top: 1px;' ). lo_buf->add( ' margin-bottom: 1px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-msg {' ). lo_buf->add( ' padding: 0.7em 1em 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( 'div.ci-msg span.ci-variant {' ). lo_buf->add( ' font-weight: bold;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-stats {' ). lo_buf->add( ' padding: 0.5em 1em;' ). lo_buf->add( '}' ). lo_buf->add( 'div.ci-stats span.count {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' padding: 2px 6px;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-detail {' ). lo_buf->add( ' padding: 6px 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-detail table td,' ). lo_buf->add( 'div.ci-detail table th {' ). lo_buf->add( ' vertical-align: text-top;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-detail table th[data-cid="kind"],' ). lo_buf->add( 'div.ci-detail table th[data-cid="obj_type"] {' ). lo_buf->add( ' white-space: nowrap' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-detail table td[data-cid="kind"] span {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' width: 1em;' ). lo_buf->add( ' height: 1em;' ). lo_buf->add( ' vertical-align: inherit;' ). lo_buf->add( ' color: transparent;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-detail table td[data-cid="text"] {' ). lo_buf->add( ' font-size: smaller;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* FLOATING BUTTONS */' ). lo_buf->add( '' ). lo_buf->add( '.floating-button {' ). lo_buf->add( ' position: fixed;' ). lo_buf->add( ' top: 8em;' ). lo_buf->add( ' right: 2.8em;' ). lo_buf->add( ' padding: 1em 1.8em;' ). lo_buf->add( ' border-radius: 4px;' ). lo_buf->add( ' border-width: 1px;' ). lo_buf->add( ' border-style: solid;' ). lo_buf->add( ' box-shadow: 2px 2px 6px 0px #ccc;' ). lo_buf->add( ' cursor: pointer;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* COMMAND PALETTE */' ). lo_buf->add( '' ). lo_buf->add( '.cmd-palette {' ). lo_buf->add( ' position: absolute;' ). lo_buf->add( ' z-index: 99;' ). lo_buf->add( ' top: 36px;' ). lo_buf->add( ' left: 50%;' ). lo_buf->add( ' width: 40em;' ). lo_buf->add( ' margin-left: -20em;' ). lo_buf->add( ' box-shadow: 1px 1px 3px 2px #dcdcdc;' ). lo_buf->add( ' background-color: white;' ). lo_buf->add( ' border: solid 2px;' ). lo_buf->add( ' padding: 0px 1px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.cmd-palette input {' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( ' box-sizing: border-box;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.cmd-palette ul {' ). lo_buf->add( ' max-height: 10em;' ). lo_buf->add( ' overflow-y: scroll;' ). lo_buf->add( ' margin: 4px 0;' ). lo_buf->add( ' padding: 2px 4px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.cmd-palette li {' ). lo_buf->add( ' list-style-type: none;' ). lo_buf->add( ' cursor: default;' ). lo_buf->add( ' padding: 4px 6px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.cmd-palette li .icon {' ). lo_buf->add( ' margin-right: 10px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.cmd-palette li .icon:before {' ). lo_buf->add( ' width: 1.1em;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* SETTINGS */' ). lo_buf->add( '' ). lo_buf->add( 'table.settings_tab {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' max-width: 600px;' ). lo_buf->add( ' line-height: 1.5;' ). lo_buf->add( '}' ). lo_buf->add( 'table.settings_tab th {' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( ' padding: 0.5em;' ). lo_buf->add( ' border-bottom: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( 'table.settings_tab td {' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( ' padding: 0.3em 0.5em;' ). lo_buf->add( ' border-top: 1px solid;' ). lo_buf->add( '}' ). lo_buf->add( 'table.settings_tab input {' ). lo_buf->add( ' border: none;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( '}' ). lo_buf->add( 'settings_tab tr:first-child td { border-top: 0px; }' ). lo_buf->add( '' ). lo_buf->add( '/* UNIT TESTS */' ). lo_buf->add( '' ). lo_buf->add( 'table.unit_tests {' ). lo_buf->add( ' line-height: 1.5;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* DIALOGS */' ). lo_buf->add( '' ). lo_buf->add( '.dialog {' ). lo_buf->add( ' margin: 0 auto;' ). lo_buf->add( ' margin-top: 1em;' ). lo_buf->add( ' margin-bottom: 1em;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' padding: 1em 1em;' ). lo_buf->add( ' border-radius: 6px;' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog-form {' ). lo_buf->add( ' width: 600px;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog-form-center {' ). lo_buf->add( ' margin: 1em auto 1em;' ). lo_buf->add( ' max-width: 600px;' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog ul {' ). lo_buf->add( ' padding: 0;' ). lo_buf->add( ' margin: 0;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li {' ). lo_buf->add( ' padding: 5px 10px;' ). lo_buf->add( ' display: block;' ). lo_buf->add( ' list-style: none;' ). lo_buf->add( ' position: relative;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.dialog-commands {' ). lo_buf->add( ' text-align: right;' ). lo_buf->add( ' margin-top: 12px;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.dialog-commands a {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' cursor: pointer;' ). lo_buf->add( ' text-decoration: none;' ). lo_buf->add( ' padding: 6px 12px;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.dialog-commands input[type="button"],' ). lo_buf->add( '.dialog li.dialog-commands input[type="submit"] {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' padding: 6px 12px;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' cursor: pointer;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.dialog-commands a.main,' ). lo_buf->add( '.dialog li.dialog-commands input[type="submit"].main {' ). lo_buf->add( ' border: 1px solid transparent;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog label {' ). lo_buf->add( ' display: block;' ). lo_buf->add( ' font-size: 90%;' ). lo_buf->add( ' margin-top: 6px;' ). lo_buf->add( ' margin-bottom: 6px;' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.error small {' ). lo_buf->add( ' display: block;' ). lo_buf->add( ' font-size: 75%;' ). lo_buf->add( ' margin: 4px 0px;' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.hidden {' ). lo_buf->add( ' padding: 0px 0px;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container {' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' padding: 4px;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog input[type="checkbox"] + label {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog input[type="password"],' ). lo_buf->add( '.dialog input[type="text"] {' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( ' box-sizing: border-box;' ). lo_buf->add( ' height: 2.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog input[type="number"] {' ). lo_buf->add( ' width: 25%;' ). lo_buf->add( ' box-sizing: border-box;' ). lo_buf->add( ' height: 2.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog textarea {' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( ' box-sizing: border-box;' ). lo_buf->add( ' padding: 10px;' ). lo_buf->add( ' font-family: Arial,Helvetica,sans-serif;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container input[type="radio"] {' ). lo_buf->add( ' visibility: hidden;' ). lo_buf->add( ' display: none;' ). lo_buf->add( ' height: 0px;' ). lo_buf->add( ' width: 0px;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container input[type="radio"] + label {' ). lo_buf->add( ' border: 1px solid transparent;' ). lo_buf->add( ' cursor: pointer;' ). lo_buf->add( ' width: auto;' ). lo_buf->add( ' margin: 0px;' ). lo_buf->add( ' padding: 3px 8px;' ). lo_buf->add( ' border-radius: 2px;' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container input[type="radio"]:checked + label {' ). lo_buf->add( ' border: 1px solid transparent;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog table {' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog table thead td {' ). lo_buf->add( ' font-size: 14px;' ). lo_buf->add( ' height: 2.5em;' ). lo_buf->add( ' background-color: #ddd;' ). lo_buf->add( ' border: 1px solid #ccc;' ). lo_buf->add( ' padding: 0px 10px;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog table tbody td {' ). lo_buf->add( ' border: 1px solid #ccc;' ). lo_buf->add( ' background-color: white;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog table td input {' ). lo_buf->add( ' border: 0px;' ). lo_buf->add( ' background: none;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.with-command div.input-container {' ). lo_buf->add( ' display: table-cell;' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.with-command div.command-container {' ). lo_buf->add( ' display: table-cell;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.with-command input[type="button"],' ). lo_buf->add( '.dialog li.with-command input[type="submit"] {' ). lo_buf->add( ' height: 2.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog fieldset {' ). lo_buf->add( ' margin-top: 1em;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-right: none;' ). lo_buf->add( ' border-left: none;' ). lo_buf->add( ' border-bottom: none;' ). lo_buf->add( ' border-radius: 6px; /* does not work in IE ? */' ). lo_buf->add( ' padding-bottom: 1em;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog fieldset:first-child {' ). lo_buf->add( ' margin-top: 0;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog fieldset legend {' ). lo_buf->add( ' font-size: large;' ). lo_buf->add( ' font-weight: bold;' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( ' padding-right: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .dialog-help {' ). lo_buf->add( ' float: left;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* STICKY HEADERS */' ). lo_buf->add( '' ). lo_buf->add( '/* https://www.w3schools.com/howto/howto_js_navbar_sticky.asp */' ). lo_buf->add( '/* Note: We have to use JS since IE does not support CSS position:sticky */' ). lo_buf->add( '' ). lo_buf->add( '/* The sticky class is added to the navbar with JS when it reaches its scroll position */' ). lo_buf->add( '.sticky {' ). lo_buf->add( ' position: fixed;' ). lo_buf->add( ' top: 0;' ). lo_buf->add( ' z-index: 10;' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( ' padding: 0.5em;' ). lo_buf->add( ' margin-bottom: 3px;' ). lo_buf->add( ' max-height: 47px;' ). lo_buf->add( ' max-width: 1265px; /* if set to 1280px, then actual width will be 1296px (strange) */' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.sticky_full_width {' ). lo_buf->add( ' position: fixed;' ). lo_buf->add( ' top: 0;' ). lo_buf->add( ' z-index: 10;' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( ' padding: 0.5em 0.5em;' ). lo_buf->add( ' margin-bottom: 3px;' ). lo_buf->add( ' max-height: 47px;' ). lo_buf->add( '}' ). lo_buf->add( '.sticky_full_width .nav-container {' ). lo_buf->add( ' margin-right: 18px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* Add some top padding to the page content to prevent sudden quick movement' ). lo_buf->add( ' as the navigation bar gets a new position at the top of the page */' ). lo_buf->add( '.sticky + .not_sticky {' ). lo_buf->add( ' padding-top: 50px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.sticky_full_width + .not_sticky {' ). lo_buf->add( ' padding-top: 50px;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* Light toolbar or blocks with separators */' ). lo_buf->add( '.toolbar-light a {' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( ' padding-right: 0.5em;' ). lo_buf->add( ' border-left: 1px solid;' ). lo_buf->add( ' border-left-color: #ccc;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.toolbar-light a:first-child {' ). lo_buf->add( ' padding-left: 0;' ). lo_buf->add( ' border-left: none;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* Warning if wrong browser control is used */' ). lo_buf->add( '.browser-control-warning {' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* MODAL POPUP */' ). lo_buf->add( '/* https://css-tricks.com/considerations-styling-modal/ */' ). lo_buf->add( '' ). lo_buf->add( '.modal {' ). lo_buf->add( ' /* center on screen */' ). lo_buf->add( ' position: fixed;' ). lo_buf->add( ' top: 50%;' ). lo_buf->add( ' left: 50%;' ). lo_buf->add( ' transform: translate(-50%, -50%);' ). lo_buf->add( ' /* size */' ). lo_buf->add( ' max-width: 100%;' ). lo_buf->add( ' max-height: 100%;' ). lo_buf->add( ' /* infront of overlay */' ). lo_buf->add( ' z-index: 1010;' ). lo_buf->add( ' display: block;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.modal-guts {' ). lo_buf->add( ' padding: 6px 6px;' ). lo_buf->add( ' /* let it scroll */' ). lo_buf->add( ' overflow: auto;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.modal-guts .dialog {' ). lo_buf->add( ' box-shadow: 2px 2px 4px 1px rgba(0,0,0,0.3);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.modal-overlay {' ). lo_buf->add( ' /* darken and prevent interactions with background */' ). lo_buf->add( ' z-index: 1000;' ). lo_buf->add( ' position: fixed;' ). lo_buf->add( ' top: 0;' ). lo_buf->add( ' left: 0;' ). lo_buf->add( ' width: 100%;' ). lo_buf->add( ' height: 100%;' ). lo_buf->add( ' background: rgba(0, 0, 0, 0.3);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.modal .radio-container label {' ). lo_buf->add( ' /* hacky, improve later, get rid of !important, hook it to a named style instead */' ). lo_buf->add( ' border-radius: 3px !important;' ). lo_buf->add( ' border: 1px solid rgba(0, 0, 0, 0.3) !important;' ). lo_buf->add( ' margin-bottom: 2px !important;' ). lo_buf->add( '}' ). lo_buf->add( '.modal .radio-container label:hover {' ). lo_buf->add( ' background-color: rgba(0, 0, 0, 0.1);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* WHERE USED PAGE */' ). lo_buf->add( '' ). lo_buf->add( 'div.wu-header {' ). lo_buf->add( ' padding: 8px 0.5em;' ). lo_buf->add( ' margin: 0px 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( 'div.wu {' ). lo_buf->add( ' padding: 8px 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( 'div.wu table thead tr:first-child {' ). lo_buf->add( ' /* TODO: maybe move this to default table style */' ). lo_buf->add( ' color: hsl(0, 0%, 80%);' ). lo_buf->add( ' text-transform: uppercase;' ). lo_buf->add( ' font-size: 90%;' ). lo_buf->add( '}' ). lo_buf->add( 'div.wu table tbody {' ). lo_buf->add( ' font-size: 90%;' ). lo_buf->add( ' vertical-align: baseline; /* for second lines, used type */' ). lo_buf->add( '}' ). lo_buf->add( 'div.wu table td[data-cid="dep_obj_name"] span.used-obj {' ). lo_buf->add( ' display: block;' ). lo_buf->add( ' color: hsl(0, 0%, 70%);' ). lo_buf->add( ' font-size: smaller;' ). lo_buf->add( ' text-transform: lowercase;' ). lo_buf->add( '}' ). lo_buf->add( 'div.wu table td[data-gid="where"],' ). lo_buf->add( 'div.wu table th[data-gid="where"] {' ). lo_buf->add( ' background-color: hsl(0, 0%, 97%);' ). lo_buf->add( '}' ). li_asset_man->register_asset( iv_url = 'css/common.css' iv_type = 'text/css' iv_mime_name = 'ZABAPGIT_CSS_COMMON' iv_inline = lo_buf->join_w_newline_and_flush( ) ). **************************************************** * abapmerge Pragma [include] - ZABAPGIT_CSS_THEME_DEFAULT.W3MI.DATA.CSS **************************************************** lo_buf->add( '/*' ). lo_buf->add( ' * ABAPGIT COLOR THEME CSS - DEFAULT' ). lo_buf->add( ' */' ). lo_buf->add( '' ). lo_buf->add( ':root {' ). lo_buf->add( ' --theme-background-color: #E8E8E8;' ). lo_buf->add( ' --theme-container-background-color: #f2f2f2;' ). lo_buf->add( ' --theme-container-border-color: lightgrey;' ). lo_buf->add( ' --theme-table-background-color: white;' ). lo_buf->add( ' --theme-table-head-background-color: #edf2f9;' ). lo_buf->add( ' --theme-table-border-color: #ddd;' ). lo_buf->add( ' --theme-table-cell-border-color: #eee;' ). lo_buf->add( '' ). lo_buf->add( ' --theme-primary-font: "72", Arial, Helvetica, sans-serif;' ). lo_buf->add( ' --theme-primary-font-color: #333333;' ). lo_buf->add( ' --theme-primary-font-color-reduced: #ccc;' ). lo_buf->add( ' --theme-font-size: 12pt;' ). lo_buf->add( ' --theme-link-color: #4078c0;' ). lo_buf->add( '' ). lo_buf->add( ' --theme-greyscale-dark: #808080;' ). lo_buf->add( ' --theme-greyscale-medium: #b3b3b3;' ). lo_buf->add( ' --theme-greyscale-light: #ccc;' ). lo_buf->add( ' --theme-greyscale-lighter: lightgrey;' ). lo_buf->add( ' --theme-linkhint-background: lightgreen;' ). lo_buf->add( ' --theme-debug-color: #aaa;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* GLOBALS */' ). lo_buf->add( '' ). lo_buf->add( 'body {' ). lo_buf->add( ' background-color: var(--theme-background-color);' ). lo_buf->add( ' font-family: var(--theme-primary-font);' ). lo_buf->add( ' color: var(--theme-primary-font-color);' ). lo_buf->add( ' font-size: var(--theme-font-size);' ). lo_buf->add( '}' ). lo_buf->add( 'a, a:visited { color: var(--theme-link-color); }' ). lo_buf->add( '.link {' ). lo_buf->add( ' color: var(--theme-link-color);' ). lo_buf->add( ' cursor: pointer;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'input, textarea, select { border-color: #ddd; }' ). lo_buf->add( 'input:focus, textarea:focus { border-color: #8cadd9; }' ). lo_buf->add( '' ). lo_buf->add( '/* COLOR PALETTE */' ). lo_buf->add( '' ). lo_buf->add( '.grey { color: var(--theme-greyscale-lighter) !important; }' ). lo_buf->add( '.grey70 { color: var(--theme-greyscale-medium) !important; }' ). lo_buf->add( '.grey80 { color: var(--theme-greyscale-light) !important; }' ). lo_buf->add( '.darkgrey { color: var(--theme-greyscale-dark) !important; }' ). lo_buf->add( '.bgorange { background-color: orange; }' ). lo_buf->add( '.attention { color: red !important; }' ). lo_buf->add( '.error { color: #d41919 !important; }' ). lo_buf->add( '.warning { color: #efb301 !important; }' ). lo_buf->add( '.success { color: green !important; }' ). lo_buf->add( '.blue { color: #5e8dc9 !important; }' ). lo_buf->add( '.red { color: red !important; }' ). lo_buf->add( '.white { color: white !important; }' ). lo_buf->add( '.pink { color: pink !important; }' ). lo_buf->add( '' ). lo_buf->add( '/* FLOATING BUTTONS AND COLOR SETS */' ). lo_buf->add( '' ). lo_buf->add( '.blue-set {' ). lo_buf->add( ' border-color: #abc3e3;' ). lo_buf->add( ' color: #5e8dc9;' ). lo_buf->add( ' background-color: #d9e4f2;' ). lo_buf->add( '}' ). lo_buf->add( '.grey-set {' ). lo_buf->add( ' border-color: #c7c7c7;' ). lo_buf->add( ' color: var(--theme-greyscale-dark);' ). lo_buf->add( ' background-color: #e6e6e6;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* ABAPGIT OBJECTS */' ). lo_buf->add( '' ). lo_buf->add( 'span.user-box {' ). lo_buf->add( ' border-color: #c2d4ea;' ). lo_buf->add( ' background-color: #d9e4f2;' ). lo_buf->add( '}' ). lo_buf->add( 'span.package-box {' ). lo_buf->add( ' border-color: #d3ccd2;' ). lo_buf->add( ' background-color: #ebe3ea;' ). lo_buf->add( '}' ). lo_buf->add( 'span.path-box,' ). lo_buf->add( 'span.transport-box {' ). lo_buf->add( ' border-color: #a7e3cf;' ). lo_buf->add( ' background-color: #dbf3eb;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* PANELS */' ). lo_buf->add( '/* TODO: add warning and error colors */' ). lo_buf->add( '' ). lo_buf->add( 'div.panel.success {' ). lo_buf->add( ' color: #589a58 !important;' ). lo_buf->add( ' background-color: #c5eac5;' ). lo_buf->add( '}' ). lo_buf->add( 'div.panel.error {' ). lo_buf->add( ' color: #d41919;' ). lo_buf->add( ' background-color: #fad6d6;' ). lo_buf->add( '}' ). lo_buf->add( '#debug-output { color: var(--theme-debug-color); }' ). lo_buf->add( 'div.dummydiv { background-color: var(--theme-container-background-color); }' ). lo_buf->add( '' ). lo_buf->add( '/* STRUCTURE DIVS, HEADER & FOOTER */' ). lo_buf->add( '' ). lo_buf->add( 'div#header {' ). lo_buf->add( ' background-color: var(--theme-background-color);' ). lo_buf->add( ' border-bottom-color: var(--theme-container-border-color);' ). lo_buf->add( '}' ). lo_buf->add( 'div#header .page-title { color: var(--theme-greyscale-medium); }' ). lo_buf->add( 'div#footer .version { color: var(--theme-greyscale-medium); }' ). lo_buf->add( 'div#footer { border-top-color: var(--theme-container-border-color); }' ). lo_buf->add( '' ). lo_buf->add( '/* ERROR LOG */' ). lo_buf->add( '' ). lo_buf->add( 'div.log {' ). lo_buf->add( ' background-color: #fee6e6;' ). lo_buf->add( ' border-color: #fdcece;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* REPOSITORY */' ). lo_buf->add( '' ). lo_buf->add( 'div.repo { background-color: var(--theme-container-background-color); }' ). lo_buf->add( '.repo_name span.name { color: #333; }' ). lo_buf->add( '.repo_name span.url { color: var(--theme-primary-font-color-reduced); }' ). lo_buf->add( '.repo_name a.url { color: var(--theme-primary-font-color-reduced); }' ). lo_buf->add( '.repo_name a.url:hover { color: var(--theme-link-color); }' ). lo_buf->add( '.repo_attr { color: grey; }' ). lo_buf->add( '' ). lo_buf->add( '.repo_attr span.bg_marker {' ). lo_buf->add( ' border-color: #d2d2d2;' ). lo_buf->add( ' background-color: #d8d8d8;' ). lo_buf->add( ' color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_attr span.branch_head {' ). lo_buf->add( ' border-color: #d8dff3;' ). lo_buf->add( ' background-color: #eceff9;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'span.branch {' ). lo_buf->add( ' border-color: #d9d9d9;' ). lo_buf->add( ' background-color: #e2e2e2;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'span.branch_branch {' ). lo_buf->add( ' border-color: #e7d9b1;' ). lo_buf->add( ' background-color: #f8f0d8;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* REPOSITORY TABLE*/' ). lo_buf->add( '' ). lo_buf->add( 'table.repo_tab {' ). lo_buf->add( ' border-color: var(--theme-table-border-color);' ). lo_buf->add( ' background-color: var(--theme-table-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '.repo_tab th {' ). lo_buf->add( ' color: var(--theme-link-color);' ). lo_buf->add( ' background-color: #edf2f9;' ). lo_buf->add( ' border-bottom-color: var(--theme-table-border-color);' ). lo_buf->add( '}' ). lo_buf->add( '.repo_tab td {' ). lo_buf->add( ' color: var(--theme-primary-font-color);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab tr.object_row{' ). lo_buf->add( ' border-top-color: var(--theme-table-cell-border-color);' ). lo_buf->add( '}' ). lo_buf->add( '.repo_tab .inactive { color: orange; }' ). lo_buf->add( '.repo_tab tr.unsupported { color: var(--theme-greyscale-lighter); }' ). lo_buf->add( '.repo_tab tr.modified { background-color: #fbf7e9; }' ). lo_buf->add( '.repo_tab td.current_dir { color: var(--theme-primary-font-color-reduced); }' ). lo_buf->add( '' ). lo_buf->add( '/* STAGE */' ). lo_buf->add( '' ). lo_buf->add( '.stage_tab {' ). lo_buf->add( ' border-color: #ddd;' ). lo_buf->add( ' background-color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab th {' ). lo_buf->add( ' color: var(--theme-greyscale-dark);' ). lo_buf->add( ' background-color: #edf2f9;' ). lo_buf->add( ' border-bottom-color: #ddd;' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td {' ). lo_buf->add( ' color: var(--theme-greyscale-medium);' ). lo_buf->add( ' border-top-color: var(--theme-table-cell-border-color);' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td.status {' ). lo_buf->add( ' color: var(--theme-primary-font-color-reduced);' ). lo_buf->add( ' background-color: #fafafa;' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td.highlight { color: #444 !important; }' ). lo_buf->add( '.stage_tab td.method { font-weight: bold; }' ). lo_buf->add( '.stage_tab mark {' ). lo_buf->add( ' color: white;' ). lo_buf->add( ' background-color: #79a0d2;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* COMMIT */' ). lo_buf->add( '' ). lo_buf->add( 'div.form-container { background-color: #F8F8F8; }' ). lo_buf->add( 'form.aligned-form label { color: var(--theme-greyscale-medium); }' ). lo_buf->add( 'form.aligned-form span.sub-title { color: var(--theme-greyscale-medium); }' ). lo_buf->add( '' ). lo_buf->add( '/* SETTINGS STYLES */' ). lo_buf->add( '' ). lo_buf->add( 'div.settings_container {' ). lo_buf->add( ' color: #444;' ). lo_buf->add( ' background-color: var(--theme-container-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* DIFF */' ). lo_buf->add( '' ). lo_buf->add( 'div.diff { background-color: var(--theme-container-background-color); }' ). lo_buf->add( 'span.diff_name { color: grey; }' ). lo_buf->add( 'span.diff_name strong { color: #333; }' ). lo_buf->add( 'span.diff_changed_by { color: grey; }' ). lo_buf->add( 'span.diff_changed_by span.user {' ). lo_buf->add( ' border-color: #c2d4ea;' ). lo_buf->add( ' background-color: #d9e4f2;' ). lo_buf->add( '}' ). lo_buf->add( '.diff_ins {' ). lo_buf->add( ' border-color: #abf2ab;' ). lo_buf->add( ' background-color: #e0ffe0;' ). lo_buf->add( '}' ). lo_buf->add( '.diff_del {' ). lo_buf->add( ' border-color: #ff667d;' ). lo_buf->add( ' background-color: #ffccd4;' ). lo_buf->add( '}' ). lo_buf->add( '.diff_upd {' ). lo_buf->add( ' border-color: #dada00;' ). lo_buf->add( ' background-color: #ffffcc;' ). lo_buf->add( '}' ). lo_buf->add( 'div.diff_content {' ). lo_buf->add( ' background-color: #fff;' ). lo_buf->add( ' border-top-color: #ddd;' ). lo_buf->add( ' border-bottom-color: #ddd;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* STATE BLOCK COLORS */' ). lo_buf->add( '' ). lo_buf->add( 'span.state-block span.added {' ). lo_buf->add( ' background-color: #69ad74;' ). lo_buf->add( ' border-color: #579e64;' ). lo_buf->add( ' color: white;' ). lo_buf->add( '}' ). lo_buf->add( 'span.state-block span.changed {' ). lo_buf->add( ' background-color: #e0c150;' ). lo_buf->add( ' border-color: #d4af25;' ). lo_buf->add( ' color: white;' ). lo_buf->add( '}' ). lo_buf->add( 'span.state-block span.mixed {' ). lo_buf->add( ' background-color: #e0c150;' ). lo_buf->add( ' border-color: #579e64;' ). lo_buf->add( ' color: #69ad74;' ). lo_buf->add( '}' ). lo_buf->add( 'span.state-block span.deleted {' ). lo_buf->add( ' background-color: #c76861;' ). lo_buf->add( ' border-color: #b8605a;' ). lo_buf->add( ' color: white;' ). lo_buf->add( '}' ). lo_buf->add( 'span.state-block span.none {' ). lo_buf->add( ' background-color: #e8e8e8;' ). lo_buf->add( ' border-color: #dbdbdb;' ). lo_buf->add( ' color: #c8c8c8;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* DIFF TABLE */' ). lo_buf->add( '' ). lo_buf->add( 'table.diff_tab td,' ). lo_buf->add( 'table.diff_tab th {' ). lo_buf->add( ' color: #444;' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab thead.header th {' ). lo_buf->add( ' color: #eee;' ). lo_buf->add( ' background-color: var(--theme-greyscale-medium);' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab thead.nav_line {' ). lo_buf->add( ' background-color: #edf2f9;' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab thead.nav_line th {' ). lo_buf->add( ' color: var(--theme-greyscale-medium);' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab td.num, th.num {' ). lo_buf->add( ' color: var(--theme-primary-font-color-reduced);' ). lo_buf->add( ' border-left-color: var(--theme-table-cell-border-color);' ). lo_buf->add( ' border-right-color: var(--theme-table-cell-border-color);' ). lo_buf->add( '}' ). lo_buf->add( 'table.diff_tab td.patch, th.patch {' ). lo_buf->add( ' color: var(--theme-primary-font-color-reduced);' ). lo_buf->add( ' border-left-color: var(--theme-table-cell-border-color);' ). lo_buf->add( ' border-right-color: var(--theme-table-cell-border-color);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* STYLES FOR SYNTAX HIGHLIGHTING */' ). lo_buf->add( '' ). lo_buf->add( '/* ABAP */' ). lo_buf->add( '.syntax-hl span.keyword { color: #0a69ce; }' ). lo_buf->add( '.syntax-hl span.text { color: #48ce4f; }' ). lo_buf->add( '.syntax-hl span.comment { color: var(--theme-greyscale-dark); font-style: italic; }' ). lo_buf->add( '/* XML+HTML */' ). lo_buf->add( '.syntax-hl span.xml_tag { color: #457ce3; }' ). lo_buf->add( '.syntax-hl span.attr { color: #b777fb; }' ). lo_buf->add( '.syntax-hl span.attr_val { color: #7a02f9; }' ). lo_buf->add( '/* CSS+JS */' ). lo_buf->add( '.syntax-hl span.properties { color:#0a69ce; }' ). lo_buf->add( '.syntax-hl span.values { color:blue; }' ). lo_buf->add( '.syntax-hl span.units { color:maroon; }' ). lo_buf->add( '.syntax-hl span.selectors { color:purple; }' ). lo_buf->add( '.syntax-hl span.functions { color:purple; }' ). lo_buf->add( '.syntax-hl span.colors { color:purple; }' ). lo_buf->add( '.syntax-hl span.extensions { color:darkblue; }' ). lo_buf->add( '.syntax-hl span.at_rules { color:darkblue; }' ). lo_buf->add( '.syntax-hl span.html { color:green; }' ). lo_buf->add( '.syntax-hl span.variables { color:purple; }' ). lo_buf->add( '' ). lo_buf->add( '/* DEBUG INFO STYLES */' ). lo_buf->add( '' ). lo_buf->add( 'div.debug_container {' ). lo_buf->add( ' color: #444;' ). lo_buf->add( ' background-color: var(--theme-container-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* Repo overview */' ). lo_buf->add( '' ). lo_buf->add( '.repo-overview { background-color: var(--theme-container-background-color); }' ). lo_buf->add( '.repo-overview table {' ). lo_buf->add( ' background-color: var(--theme-table-background-color);' ). lo_buf->add( ' border-color: var(--theme-table-border-color);' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview th {' ). lo_buf->add( ' color: var(--theme-link-color);' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview thead tr {' ). lo_buf->add( ' background-color: var(--theme-table-head-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview thead tr,' ). lo_buf->add( '.repo-overview tfoot tr {' ). lo_buf->add( ' border-color: var(--theme-table-border-color);' ). lo_buf->add( '}' ). lo_buf->add( '.repo-overview a.remote_repo { color: var(--theme-primary-font-color-reduced); }' ). lo_buf->add( '.repo-overview a.remote_repo:hover { color: var(--theme-link-color); }' ). lo_buf->add( '.repo-overview tbody tr:hover td { background-color: hsla(214, 50%, 50%, 0.05); }' ). lo_buf->add( '.repo-overview tbody tr.selected { background-color: hsla(214, 50%, 75%, 0.33); }' ). lo_buf->add( '' ). lo_buf->add( '/* TUTORIAL */' ). lo_buf->add( '' ). lo_buf->add( 'div.tutorial { background-color: var(--theme-container-background-color); }' ). lo_buf->add( 'div.tutorial hr { border-color: var(--theme-greyscale-light); }' ). lo_buf->add( 'div.tutorial h1, h2 { color: #404040; }' ). lo_buf->add( '' ). lo_buf->add( '/* MENU */' ). lo_buf->add( '' ). lo_buf->add( '.nav-container ul li:hover { background-color: #fff; }' ). lo_buf->add( '.nav-container ul ul li:hover { background-color: #f6f6f6; }' ). lo_buf->add( '.nav-container > ul > li:hover > a { background-color: #ffffff80; }' ). lo_buf->add( '.nav-container ul ul { background-color: #fff; }' ). lo_buf->add( '.nav-container.corner > ul > li:hover > a { background-color: inherit; }' ). lo_buf->add( '' ). lo_buf->add( '.nav-container ul ul li.separator {' ). lo_buf->add( ' color: var(--theme-greyscale-medium);' ). lo_buf->add( ' border-bottom-color: #eee;' ). lo_buf->add( ' border-top-color: #eee;' ). lo_buf->add( '}' ). lo_buf->add( '.nav-container ul ul li.separator:hover { background-color: inherit; }' ). lo_buf->add( '' ). lo_buf->add( '/* NEWS ANNOUNCEMENT */' ). lo_buf->add( '' ). lo_buf->add( 'div.info-panel { background-color: white; }' ). lo_buf->add( 'div.info-panel div.info-hint { color: var(--theme-greyscale-light); }' ). lo_buf->add( 'div.info-panel div.info-title {' ). lo_buf->add( ' color: #f8f8f8;' ). lo_buf->add( ' background-color: #888;' ). lo_buf->add( '}' ). lo_buf->add( 'div.info-panel div.info-title a.close-btn { color: #d8d8d8; }' ). lo_buf->add( 'div.info-panel div.info-list { color: #444; }' ). lo_buf->add( 'div.info-panel .version-marker {' ). lo_buf->add( ' color: white;' ). lo_buf->add( ' border-color: #c0c0c0;' ). lo_buf->add( ' background-color: var(--theme-greyscale-light);' ). lo_buf->add( '}' ). lo_buf->add( 'div.info-panel .update {' ). lo_buf->add( ' border-color: #e8ba30;' ). lo_buf->add( ' background-color: #f5c538;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* TOOLTIPS TEXT */' ). lo_buf->add( '' ). lo_buf->add( '.link-hint { color: var(--theme-primary-font-color); }' ). lo_buf->add( '.link-hint { background-color: var(--theme-linkhint-background) }' ). lo_buf->add( '.link-hint::after { border-top-color: var(--theme-linkhint-background) }' ). lo_buf->add( '' ). lo_buf->add( '/* HOTKEYS */' ). lo_buf->add( '' ). lo_buf->add( 'ul.hotkeys span.key-id {' ). lo_buf->add( ' background-color: #f0f0f0;' ). lo_buf->add( ' border-color: #dcdcdc;' ). lo_buf->add( '}' ). lo_buf->add( 'div.corner-hint {' ). lo_buf->add( ' color: var(--theme-greyscale-medium);' ). lo_buf->add( ' border-color: var(--theme-greyscale-light);' ). lo_buf->add( ' background-color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* CODE INSPECTOR */' ). lo_buf->add( '' ). lo_buf->add( 'div.ci { background-color: var(--theme-container-background-color); }' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-msg span.ci-variant { color: var(--theme-primary-font-color); }' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-stats span.error-count {' ). lo_buf->add( ' border-color: hsl(350, 100%, 80%);' ). lo_buf->add( ' background-color: hsl(350, 100%, 90%);' ). lo_buf->add( '}' ). lo_buf->add( 'div.ci-stats span.warn-count {' ). lo_buf->add( ' border-color: hsl(60, 100%, 42%);' ). lo_buf->add( ' background-color: hsl(60, 100%, 90%);' ). lo_buf->add( '}' ). lo_buf->add( 'div.ci-stats span.info-count {' ). lo_buf->add( ' border-color: hsl(120, 80%, 80%);' ). lo_buf->add( ' background-color: hsl(120, 80%, 94%);' ). lo_buf->add( '}' ). lo_buf->add( 'div.ci-stats span.all-count {' ). lo_buf->add( ' border-color: hsl(235, 100%, 89%);' ). lo_buf->add( ' background-color: hsl(235, 100%, 93%);' ). lo_buf->add( '}' ). lo_buf->add( 'div.ci-detail table td[data-cid="text"] {' ). lo_buf->add( ' color: hsl(0, 0%, 40%);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'div.ci-detail table tr[data-kind="error"] td[data-cid="kind"] span {' ). lo_buf->add( ' background-color: hsl(0, 100%, 68%);' ). lo_buf->add( '}' ). lo_buf->add( 'div.ci-detail table tr[data-kind="warning"] td[data-cid="kind"] span {' ). lo_buf->add( ' background-color:hsl(52, 100%, 49%);' ). lo_buf->add( '}' ). lo_buf->add( 'div.ci-detail table tr[data-kind="info"] td[data-cid="kind"] span {' ). lo_buf->add( ' background-color: hsl(118, 67%, 47%);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* COMMAND PALETTE */' ). lo_buf->add( '' ). lo_buf->add( '.cmd-palette {' ). lo_buf->add( ' border-color: #ccc;' ). lo_buf->add( '}' ). lo_buf->add( '.cmd-palette li.selected {' ). lo_buf->add( ' background-color: hsla(214, 50%, 90%, 1);' ). lo_buf->add( '}' ). lo_buf->add( '.cmd-palette mark {' ). lo_buf->add( ' color: white;' ). lo_buf->add( ' background-color: #79a0d2;' ). lo_buf->add( ' /* todo merge with stage search */' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* SETTINGS */' ). lo_buf->add( '' ). lo_buf->add( 'table.settings_tab {' ). lo_buf->add( ' background-color: #fff;' ). lo_buf->add( ' border-color: #ddd;' ). lo_buf->add( '}' ). lo_buf->add( 'table.settings_tab th {' ). lo_buf->add( ' color: #888888;' ). lo_buf->add( ' border-bottom-color: #ddd;' ). lo_buf->add( '}' ). lo_buf->add( 'table.settings_tab td {' ). lo_buf->add( ' color: #333;' ). lo_buf->add( ' border-top-color: #eee;' ). lo_buf->add( '}' ). lo_buf->add( 'table.settings_tab input {' ). lo_buf->add( ' background-color: #f8f8f8;' ). lo_buf->add( '}' ). lo_buf->add( 'table.settings_tab input:focus {' ). lo_buf->add( ' background-color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* HTML FORMS */' ). lo_buf->add( '' ). lo_buf->add( '.dialog input::placeholder { color: #ccc }' ). lo_buf->add( '.dialog textarea::placeholder { color: #ccc }' ). lo_buf->add( '.dialog input:-ms-input-placeholder { color: #ccc }' ). lo_buf->add( '.dialog textarea:-ms-input-placeholder { color: #ccc }' ). lo_buf->add( '.dialog {' ). lo_buf->add( ' border-color: #ccc;' ). lo_buf->add( ' background-color: #f0f0f0;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.dialog-commands a,' ). lo_buf->add( '.dialog li.dialog-commands input[type="submit"] {' ). lo_buf->add( ' border-color: #ccc;' ). lo_buf->add( ' background-color: #ddd;' ). lo_buf->add( ' color: #000;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.dialog-commands a.main,' ). lo_buf->add( '.dialog li.dialog-commands input[type="submit"].main {' ). lo_buf->add( ' background-color: #64a8ff;' ). lo_buf->add( ' color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog label {' ). lo_buf->add( ' color: #444;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog label em {' ). lo_buf->add( ' color: #64a8ff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.error small {' ). lo_buf->add( ' color: #ff5959;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.error input[type="number"],' ). lo_buf->add( '.dialog li.error input[type="text"] {' ). lo_buf->add( ' border-color: #ff5959;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container {' ). lo_buf->add( ' border-color: #ddd;' ). lo_buf->add( ' background-color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container input[type="radio"] + label {' ). lo_buf->add( ' color: #808080;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container input[type="radio"]:checked + label {' ). lo_buf->add( ' background-color: #64a8ff;' ). lo_buf->add( ' color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.with-command input[type="button"]:hover,' ). lo_buf->add( '.dialog li.with-command input[type="submit"]:hover {' ). lo_buf->add( ' background-color: #64a8ff;' ). lo_buf->add( ' color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog fieldset {' ). lo_buf->add( ' border-color: #dfdfdf;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog fieldset legend {' ). lo_buf->add( ' color: #444;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog input:read-only {' ). lo_buf->add( ' background-color: #f4f4f4;' ). lo_buf->add( ' color: var(--theme-greyscale-dark);' ). lo_buf->add( '}' ). lo_buf->add( '/* for IE */' ). lo_buf->add( '.dialog input[readonly] {' ). lo_buf->add( ' background-color: #f4f4f4;' ). lo_buf->add( ' color: var(--theme-greyscale-dark);' ). lo_buf->add( '}' ). li_asset_man->register_asset( iv_url = 'css/theme-default.css' iv_type = 'text/css' iv_cacheable = abap_false iv_mime_name = 'ZABAPGIT_CSS_THEME_DEFAULT' iv_inline = lo_buf->join_w_newline_and_flush( ) ). **************************************************** * abapmerge Pragma [include] - ZABAPGIT_CSS_THEME_DARK.W3MI.DATA.CSS **************************************************** lo_buf->add( '/*' ). lo_buf->add( ' * ABAPGIT THEME CSS - DARK' ). lo_buf->add( ' */' ). lo_buf->add( '' ). lo_buf->add( '/* https://experience.sap.com/fiori-design-web/colors/ */' ). lo_buf->add( '' ). lo_buf->add( ':root {' ). lo_buf->add( ' --theme-background-color: #333333;' ). lo_buf->add( ' --theme-container-background-color: #444444;' ). lo_buf->add( ' --theme-primary-font: "72", Arial, Helvetica, sans-serif;' ). lo_buf->add( ' --theme-primary-font-color: #cccccc;' ). lo_buf->add( ' --theme-primary-font-color-reduced: #EEEEEE;' ). lo_buf->add( ' --theme-font-size: 11pt;' ). lo_buf->add( ' --theme-link-color: #d9ffff;' ). lo_buf->add( ' --theme-link-color-hover: #f6f6f6;' ). lo_buf->add( ' --theme-container-border-color: #D1E0EE;' ). lo_buf->add( ' --theme-table-border-color: #E5E5E5; /* ALV border color */' ). lo_buf->add( ' --theme-greyscale-dark: #666666;' ). lo_buf->add( ' --theme-greyscale-medium: #999999;' ). lo_buf->add( ' --theme-greyscale-light: #CCCCCC;' ). lo_buf->add( ' --theme-greyscale-lighter: #E5E5E5;' ). lo_buf->add( ' --theme-list-hover-background-color: black;' ). lo_buf->add( '' ). lo_buf->add( ' --theme-table-background-color: #333333;' ). lo_buf->add( ' --theme-table-head-background-color: #202020;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* GLOBALS */' ). lo_buf->add( '' ). lo_buf->add( 'body {' ). lo_buf->add( ' background-color: var(--theme-background-color);' ). lo_buf->add( ' color: var(--theme-primary-font-color);' ). lo_buf->add( '}' ). lo_buf->add( 'select, input, textarea {' ). lo_buf->add( ' color: var(--theme-primary-font-color);' ). lo_buf->add( ' border-color: #ffffff;' ). lo_buf->add( ' background-color: var(--theme-background-color);' ). lo_buf->add( '}' ). lo_buf->add( 'a:hover { color: var(--theme-link-color-hover); }' ). lo_buf->add( '' ). lo_buf->add( '/* HEADER */' ). lo_buf->add( '' ). lo_buf->add( '#header a, #header a:visited { color: var(--theme-link-color); }' ). lo_buf->add( '' ). lo_buf->add( '/* MENU */' ). lo_buf->add( '' ). lo_buf->add( 'div#toc .favorites a { opacity: 1; }' ). lo_buf->add( '.nav-container ul a:hover { text-decoration: underline; }' ). lo_buf->add( '.nav-container ul ul { background-color: #555555; }' ). lo_buf->add( '.nav-container ul li:hover { background-color: #555555; }' ). lo_buf->add( '.nav-container ul ul li:hover { background-color: var(--theme-list-hover-background-color); }' ). lo_buf->add( 'table.repo_tab {' ). lo_buf->add( ' border-color: var(--theme-container-background-color);' ). lo_buf->add( ' background-color: var(--theme-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* ABAPGIT OBJECTS */' ). lo_buf->add( '' ). lo_buf->add( 'span.user-box {' ). lo_buf->add( ' background-color: #4c6782;' ). lo_buf->add( ' border-color: #7491b2;' ). lo_buf->add( '}' ). lo_buf->add( 'span.package-box {' ). lo_buf->add( ' background-color: #705a6d;' ). lo_buf->add( ' border-color: #987095;' ). lo_buf->add( '}' ). lo_buf->add( 'span.path-box,' ). lo_buf->add( 'span.transport-box {' ). lo_buf->add( ' background-color: #456d5d;' ). lo_buf->add( ' border-color: #60a087;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* PANELS */' ). lo_buf->add( '' ). lo_buf->add( '#debug-output { color: var(--theme-greyscale-dark); }' ). lo_buf->add( '' ). lo_buf->add( '/* abapGit logo in header and footer */' ). lo_buf->add( '.logo .icon.icon-abapgit {' ). lo_buf->add( ' color: var(--theme-primary-font-color);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* TUTORIAL */' ). lo_buf->add( '' ). lo_buf->add( 'div.tutorial h1, h2 { color: var(--theme-primary-font-color); }' ). lo_buf->add( '' ). lo_buf->add( '/* REPOSITORY */' ). lo_buf->add( '' ). lo_buf->add( 'div.repo { background-color: var(--theme-container-background-color); }' ). lo_buf->add( '.repo_name span.name { color: var(--theme-primary-font-color-reduced); }' ). lo_buf->add( '.repo_name span.url { color: var(--theme-greyscale-medium); }' ). lo_buf->add( '.repo_name a.url { color: var(--theme-greyscale-medium); }' ). lo_buf->add( '.repo_attr { color: var(--theme-primary-font-color); }' ). lo_buf->add( '' ). lo_buf->add( 'span.branch_branch {' ). lo_buf->add( ' border-color: var(--theme-greyscale-medium);' ). lo_buf->add( ' background-color: #777777;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* REPOSITORY TABLE */' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab td { color: var(--theme-primary-font-color); }' ). lo_buf->add( '.repo_tab tr.unsupported { background-color: #555; }' ). lo_buf->add( '.repo_tab tr.modified { background-color: #555; }' ). lo_buf->add( '.repo_tab tr:hover {background-color: var(--theme-list-hover-background-color) !important;}' ). lo_buf->add( '' ). lo_buf->add( '.repo_tab th {' ). lo_buf->add( ' border-top-color: var(--theme-greyscale-dark);' ). lo_buf->add( ' background-color: black;' ). lo_buf->add( '}' ). lo_buf->add( '.repo_tab td {' ). lo_buf->add( ' border-top-color: var(--theme-greyscale-dark);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* STAGE */' ). lo_buf->add( '' ). lo_buf->add( '.stage_tab {' ). lo_buf->add( ' border-color: var(--theme-greyscale-dark);' ). lo_buf->add( ' background-color: var(--theme-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab th {' ). lo_buf->add( ' border-top-color: var(--theme-greyscale-dark);' ). lo_buf->add( ' background-color: black;' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td {' ). lo_buf->add( ' color: var(--theme-primary-font-color);' ). lo_buf->add( ' border-top-color: var(--theme-greyscale-dark);' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td.status.highlight {' ). lo_buf->add( ' color: var(--theme-primary-font-color) !important;' ). lo_buf->add( ' background-color: var(--theme-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab td.status {' ). lo_buf->add( ' color: #777;' ). lo_buf->add( ' background-color: var(--theme-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '.stage_tab th { background-color: var(--theme-container-background-color); }' ). lo_buf->add( '.stage_tab tr:hover {background-color: var(--theme-list-hover-background-color) !important;}' ). lo_buf->add( '' ). lo_buf->add( '/* COMMIT */' ). lo_buf->add( '' ). lo_buf->add( 'div.form-container { background-color: var(--theme-background-color); }' ). lo_buf->add( '' ). lo_buf->add( '/* SETTINGS STYLES */' ). lo_buf->add( '' ). lo_buf->add( 'div.settings_container { color: var(--theme-primary-font-color); }' ). lo_buf->add( '' ). lo_buf->add( '/* DIFF */' ). lo_buf->add( '' ). lo_buf->add( '.diff_ins { background-color: #352; }' ). lo_buf->add( '.diff_del { background-color: #411; }' ). lo_buf->add( '.diff_upd { background-color: #551; }' ). lo_buf->add( 'div.diff_content { background-color: var(--theme-background-color); }' ). lo_buf->add( '' ). lo_buf->add( '/* DIFF TABLE */' ). lo_buf->add( '' ). lo_buf->add( 'table.diff_tab td,th { color: #fff; }' ). lo_buf->add( 'table.diff_tab thead.nav_line { background-color: var(--theme-container-background-color); }' ). lo_buf->add( '' ). lo_buf->add( '/* STYLES FOR SYNTAX HIGHLIGHTING */' ). lo_buf->add( '' ). lo_buf->add( '/* ABAP */' ). lo_buf->add( '.syntax-hl span.keyword { color: #4af; }' ). lo_buf->add( '.syntax-hl span.text { color: #8f8; }' ). lo_buf->add( '.syntax-hl span.comment { color: #999; }' ). lo_buf->add( '/* XML+HTML */' ). lo_buf->add( '.syntax-hl span.xml_tag { color: #659cff; }' ). lo_buf->add( '.syntax-hl span.attr { color: #bab2f9; }' ). lo_buf->add( '.syntax-hl span.attr_val { color: #b777fb; }' ). lo_buf->add( '/* CSS+JS */' ). lo_buf->add( '.syntax-hl span.properties { color:#0a69ce; }' ). lo_buf->add( '.syntax-hl span.values { color:blue; }' ). lo_buf->add( '.syntax-hl span.units { color:maroon; }' ). lo_buf->add( '.syntax-hl span.selectors { color:purple; }' ). lo_buf->add( '.syntax-hl span.functions { color:purple; }' ). lo_buf->add( '.syntax-hl span.colors { color:purple; }' ). lo_buf->add( '.syntax-hl span.extensions { color:lightblue; }' ). lo_buf->add( '.syntax-hl span.at_rules { color:lightblue; }' ). lo_buf->add( '.syntax-hl span.html { color:green; }' ). lo_buf->add( '.syntax-hl span.variables { color:purple; }' ). lo_buf->add( '' ). lo_buf->add( '/* DEBUG INFO STYLES */' ). lo_buf->add( '' ). lo_buf->add( 'div.debug_container#debug_info { color: var(--theme-primary-font-color); }' ). lo_buf->add( '' ). lo_buf->add( '/* DB ENTRIES */' ). lo_buf->add( '' ). lo_buf->add( 'div.db_list { background-color: var(--theme-container-background-color); }' ). lo_buf->add( 'table.db_tab td { color: var(--theme-primary-font-color); }' ). lo_buf->add( 'table.db_tab td.data { opacity: 0.5; }' ). lo_buf->add( 'table.db_tab tbody tr:hover, tr:active { background-color: var(--theme-list-hover-background-color); }' ). lo_buf->add( 'table.db_tab th {' ). lo_buf->add( ' color: var(--theme-primary-font-color);' ). lo_buf->add( ' border-bottom-color: #333;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'table.db_tab tr.selected {' ). lo_buf->add( ' background: rgba(92, 92, 92, 1) !important;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/* ERROR LOGS */' ). lo_buf->add( '' ). lo_buf->add( 'div.log { color: var(--theme-greyscale-dark); }' ). lo_buf->add( '.close-btn, .message-panel, .message-panel-commands a { color: var(--theme-greyscale-dark); }' ). lo_buf->add( '.message-panel-commands a:hover { color: var(--theme-greyscale-dark); }' ). lo_buf->add( '' ). lo_buf->add( '/* DIALOGS */' ). lo_buf->add( '' ). lo_buf->add( '.dialog {' ). lo_buf->add( ' color: var(--theme-primary-font-color-reduced);' ). lo_buf->add( ' background-color: var(--theme-container-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.dialog-commands a,' ). lo_buf->add( '.dialog li.dialog-commands input[type="submit"] {' ). lo_buf->add( ' border-color: #ccc;' ). lo_buf->add( ' background-color: var(--theme-greyscale-dark);' ). lo_buf->add( ' color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.dialog-commands a.main,' ). lo_buf->add( '.dialog li.dialog-commands input[type="submit"].main {' ). lo_buf->add( ' background-color: #64a8ff;' ). lo_buf->add( ' color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog label {' ). lo_buf->add( ' color: var(--theme-primary-font-color);' ). lo_buf->add( '}' ). lo_buf->add( '.dialog label em {' ). lo_buf->add( ' color: #64a8ff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.error small {' ). lo_buf->add( ' color: #ff5959;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.error input[type="number"],' ). lo_buf->add( '.dialog li.error input[type="text"] {' ). lo_buf->add( ' border-color: #ff5959;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container {' ). lo_buf->add( ' border-color: #ddd;' ). lo_buf->add( ' background-color: var(--theme-greyscale-dark);' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container input[type="radio"] + label {' ). lo_buf->add( ' color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog .radio-container input[type="radio"]:checked + label {' ). lo_buf->add( ' background-color: #64a8ff;' ). lo_buf->add( ' color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog li.with-command input[type="button"]:hover,' ). lo_buf->add( '.dialog li.with-command input[type="submit"]:hover {' ). lo_buf->add( ' background-color: #64a8ff;' ). lo_buf->add( ' color: #fff;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog fieldset {' ). lo_buf->add( ' border-color: #dfdfdf;' ). lo_buf->add( '}' ). lo_buf->add( '.dialog fieldset legend {' ). lo_buf->add( ' color: var(--theme-primary-font-color);' ). lo_buf->add( '}' ). lo_buf->add( '.dialog input:read-only {' ). lo_buf->add( ' background-color: var(--theme-greyscale-dark);' ). lo_buf->add( ' color: var(--theme-greyscale-medium);' ). lo_buf->add( '}' ). lo_buf->add( '/* for IE */' ). lo_buf->add( '.dialog input[readonly] {' ). lo_buf->add( ' background-color: var(--theme-greyscale-dark);' ). lo_buf->add( ' color: var(--theme-greyscale-medium);' ). lo_buf->add( '} ' ). li_asset_man->register_asset( iv_url = 'css/theme-dark.css' iv_type = 'text/css' iv_cacheable = abap_false iv_mime_name = 'ZABAPGIT_CSS_THEME_DARK' iv_inline = lo_buf->join_w_newline_and_flush( ) ). **************************************************** * abapmerge Pragma [include] - ZABAPGIT_CSS_THEME_BELIZE_BLUE.W3MI.DATA.CSS **************************************************** lo_buf->add( '/*' ). lo_buf->add( ' * ABAPGIT THEME CSS - BELIZE BLUE' ). lo_buf->add( ' */' ). lo_buf->add( '' ). lo_buf->add( '/* https://experience.sap.com/fiori-design-web/colors/ */' ). lo_buf->add( '' ). lo_buf->add( ':root {' ). lo_buf->add( ' --fiori-color-global-light-base: #EFF4F9; /* Background in SAP GUI */' ). lo_buf->add( ' --fiori-color-gui-tab-background: #FCFDFE; /* Tabstrip background */' ). lo_buf->add( ' --fiori-color-gui-container-border: #D1E0EE;' ). lo_buf->add( ' --fiori-color-gui-uneditable-background: #F2F2F2; /* Textbox not editable */' ). lo_buf->add( ' --fiori-color-gui-editable-background: #FFFFFF; /* Textbox editable */' ). lo_buf->add( ' --fiori-color-font-primary: #333333; /* Grayscale 1 */' ). lo_buf->add( ' --fiori-color-font-secondary: #666666; /* Grayscale 2 */' ). lo_buf->add( ' --fiori-color-font-highlighted: #003D84;' ). lo_buf->add( ' --fiori-color-message-box-background: #2F3C48; /* Bottom message container */' ). lo_buf->add( '' ). lo_buf->add( ' --theme-background-color: var(--fiori-color-global-light-base);' ). lo_buf->add( ' --theme-container-background-color: var(--fiori-color-gui-tab-background);' ). lo_buf->add( ' --theme-primary-font: "72", Arial, Helvetica, sans-serif;' ). lo_buf->add( ' --theme-primary-font-color: var(--fiori-color-font-primary);' ). lo_buf->add( ' --theme-primary-font-color-reduced: var(--fiori-color-font-secondary);' ). lo_buf->add( ' --theme-font-size: 11pt;' ). lo_buf->add( ' --theme-link-color: var(--fiori-color-font-highlighted);' ). lo_buf->add( ' --theme-container-border-color: var(--fiori-color-gui-container-border);' ). lo_buf->add( ' --theme-table-border-color: #E5E5E5; /* ALV border color */' ). lo_buf->add( ' --theme-greyscale-dark: #666666;' ). lo_buf->add( ' --theme-greyscale-medium: #BFBFBF;' ). lo_buf->add( ' --theme-greyscale-light: #CCCCCC;' ). lo_buf->add( ' --theme-greyscale-lighter: #E5E5E5;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '#header a, #header a:visited {' ). lo_buf->add( ' color: #346187;' ). lo_buf->add( '}' ). li_asset_man->register_asset( iv_url = 'css/theme-belize-blue.css' iv_type = 'text/css' iv_cacheable = abap_false iv_mime_name = 'ZABAPGIT_CSS_THEME_BELIZE_BLUE' iv_inline = lo_buf->join_w_newline_and_flush( ) ). **************************************************** * abapmerge Pragma [include] - ZABAPGIT_JS_COMMON.W3MI.DATA.JS **************************************************** lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * abapGit JavaScript Function Library' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' Global variables used from outside' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '/* exported setInitialFocus */' ). lo_buf->add( '/* exported setInitialFocusWithQuerySelector */' ). lo_buf->add( '/* exported submitFormById */' ). lo_buf->add( '/* exported errorStub */' ). lo_buf->add( '/* exported confirmInitialized */' ). lo_buf->add( '/* exported perfOut */' ). lo_buf->add( '/* exported perfLog */' ). lo_buf->add( '/* exported perfClear */' ). lo_buf->add( '/* exported enableArrowListNavigation */' ). lo_buf->add( '/* exported activateLinkHints */' ). lo_buf->add( '/* exported setKeyBindings */' ). lo_buf->add( '/* exported preparePatch */' ). lo_buf->add( '/* exported registerStagePatch */' ). lo_buf->add( '/* exported toggleRepoListDetail */' ). lo_buf->add( '/* exported onTagTypeChange */' ). lo_buf->add( '/* exported getIndocStyleSheet */' ). lo_buf->add( '/* exported addMarginBottom */' ). lo_buf->add( '/* exported enumerateJumpAllFiles */' ). lo_buf->add( '/* exported createRepoCatalogEnumerator */' ). lo_buf->add( '/* exported enumerateUiActions */' ). lo_buf->add( '/* exported onDiffCollapse */' ). lo_buf->add( '/* exported restoreScrollPosition */' ). lo_buf->add( '/* exported toggleBrowserControlWarning */' ). lo_buf->add( '/* exported displayBrowserControlFooter */' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Polyfills' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '// Bind polyfill (for IE7), taken from https://developer.mozilla.org/' ). lo_buf->add( 'if (!Function.prototype.bind) {' ). lo_buf->add( ' Function.prototype.bind = function(oThis) {' ). lo_buf->add( ' if (typeof this !== "function") {' ). lo_buf->add( ' throw new TypeError("Function.prototype.bind - subject is not callable");' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' var aArgs = Array.prototype.slice.call(arguments, 1);' ). lo_buf->add( ' var fToBind = this;' ). lo_buf->add( ' var fNOP = function() { };' ). lo_buf->add( ' var fBound = function() {' ). lo_buf->add( ' return fToBind.apply(' ). lo_buf->add( ' this instanceof fNOP ? this : oThis,' ). lo_buf->add( ' aArgs.concat(Array.prototype.slice.call(arguments))' ). lo_buf->add( ' );' ). lo_buf->add( ' };' ). lo_buf->add( '' ). lo_buf->add( ' if (this.prototype) {' ). lo_buf->add( ' fNOP.prototype = this.prototype;' ). lo_buf->add( ' }' ). lo_buf->add( ' fBound.prototype = new fNOP();' ). lo_buf->add( '' ). lo_buf->add( ' return fBound;' ). lo_buf->add( ' };' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// String includes polyfill, taken from https://developer.mozilla.org' ). lo_buf->add( 'if (!String.prototype.includes) {' ). lo_buf->add( ' String.prototype.includes = function(search, start) {' ). lo_buf->add( ' "use strict";' ). lo_buf->add( ' if (typeof start !== "number") {' ). lo_buf->add( ' start = 0;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' if (start + search.length > this.length) {' ). lo_buf->add( ' return false;' ). lo_buf->add( ' } else {' ). lo_buf->add( ' return this.indexOf(search, start) !== -1;' ). lo_buf->add( ' }' ). lo_buf->add( ' };' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// String startsWith polyfill, taken from https://developer.mozilla.org' ). lo_buf->add( 'if (!String.prototype.startsWith) {' ). lo_buf->add( ' Object.defineProperty(String.prototype, "startsWith", {' ). lo_buf->add( ' value: function(search, pos) {' ). lo_buf->add( ' pos = !pos || pos < 0 ? 0 : +pos;' ). lo_buf->add( '' ). lo_buf->add( ' return this.substring(pos, pos + search.length) === search;' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// forEach polyfill, taken from https://developer.mozilla.org' ). lo_buf->add( '// used for querySelectorAll results' ). lo_buf->add( 'if (window.NodeList && !NodeList.prototype.forEach) {' ). lo_buf->add( ' NodeList.prototype.forEach = Array.prototype.forEach;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Common functions' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '// Output text to the debug div' ). lo_buf->add( 'function debugOutput(text, dstID) {' ). lo_buf->add( ' var stdout = document.getElementById(dstID || "debug-output");' ). lo_buf->add( ' var wrapped = "

" + text + "

";' ). lo_buf->add( '' ). lo_buf->add( ' stdout.innerHTML = stdout.innerHTML + wrapped;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// Use a supplied form, a pre-created form or create a hidden form' ). lo_buf->add( '// and submit with sapevent' ). lo_buf->add( 'function submitSapeventForm(params, action, method, form) {' ). lo_buf->add( '' ). lo_buf->add( ' function getSapeventPrefix() {' ). lo_buf->add( ' // Depending on the used browser control and its version, different URL schemes' ). lo_buf->add( ' // are used which we distinguish here' ). lo_buf->add( ' if (document.querySelector(''a[href*="file:///SAPEVENT:"]'')) {' ). lo_buf->add( ' // Prefix for old (SAPGUI <= 8.00 PL3) chromium based browser control' ). lo_buf->add( ' return "file:///";' ). lo_buf->add( ' } else if (document.querySelector(''a[href^="sap-cust"]'')) {' ). lo_buf->add( ' // Prefix for new (SAPGUI >= 8.00 PL3 Hotfix 1) chromium based browser control' ). lo_buf->add( ' return "sap-cust://sap-place-holder/";' ). lo_buf->add( ' } else {' ). lo_buf->add( ' return ""; // No prefix for old IE control' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' var stub_form_id = "form_" + action;' ). lo_buf->add( '' ). lo_buf->add( ' form = form' ). lo_buf->add( ' || document.getElementById(stub_form_id)' ). lo_buf->add( ' || document.createElement("form");' ). lo_buf->add( '' ). lo_buf->add( ' form.setAttribute("method", method || "post");' ). lo_buf->add( ' if (/sapevent/i.test(action)) {' ). lo_buf->add( ' form.setAttribute("action", action);' ). lo_buf->add( ' } else {' ). lo_buf->add( ' form.setAttribute("action", getSapeventPrefix() + "SAPEVENT:" + action);' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' for (var key in params) {' ). lo_buf->add( ' var hiddenField = document.createElement("input");' ). lo_buf->add( ' hiddenField.setAttribute("type", "hidden");' ). lo_buf->add( ' hiddenField.setAttribute("name", key);' ). lo_buf->add( ' hiddenField.setAttribute("value", params[key]);' ). lo_buf->add( ' form.appendChild(hiddenField);' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' var formExistsInDOM = form.id && Boolean(document.querySelector("#" + form.id));' ). lo_buf->add( '' ). lo_buf->add( ' if (form.id !== stub_form_id && !formExistsInDOM) {' ). lo_buf->add( ' document.body.appendChild(form);' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' form.submit();' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// Set focus to a control' ). lo_buf->add( 'function setInitialFocus(id) {' ). lo_buf->add( ' document.getElementById(id).focus();' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// Set focus to an element with query selector' ). lo_buf->add( 'function setInitialFocusWithQuerySelector(sSelector, bFocusParent) {' ). lo_buf->add( ' var oSelected = document.querySelector(sSelector);' ). lo_buf->add( '' ). lo_buf->add( ' if (oSelected) {' ). lo_buf->add( ' if (bFocusParent) {' ). lo_buf->add( ' oSelected.parentElement.focus();' ). lo_buf->add( ' } else {' ). lo_buf->add( ' oSelected.focus();' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// Submit an existing form' ). lo_buf->add( 'function submitFormById(id) {' ). lo_buf->add( ' document.getElementById(id).submit();' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// JS error stub' ). lo_buf->add( 'function errorStub(event) {' ). lo_buf->add( ' var element = event.target || event.srcElement;' ). lo_buf->add( ' var targetName = element.id || element.name || "???";' ). lo_buf->add( ' alert("JS Error, please log an issue (@" + targetName + ")");' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// Confirm JS initialization' ). lo_buf->add( 'function confirmInitialized() {' ). lo_buf->add( ' var errorBanner = document.getElementById("js-error-banner");' ). lo_buf->add( ' if (errorBanner) {' ). lo_buf->add( ' errorBanner.style.display = "none";' ). lo_buf->add( ' }' ). lo_buf->add( ' debugOutput("js: OK"); // Final final confirmation :)' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Performance utils (for debugging)' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( 'var gPerf = [];' ). lo_buf->add( '' ). lo_buf->add( 'function perfOut(prefix) {' ). lo_buf->add( ' var totals = {};' ). lo_buf->add( ' for (var i = gPerf.length - 1; i >= 0; i--) {' ). lo_buf->add( ' if (!totals[gPerf[i].name]) totals[gPerf[i].name] = { count: 0, time: 0 };' ). lo_buf->add( '' ). lo_buf->add( ' totals[gPerf[i].name].time += gPerf[i].time;' ). lo_buf->add( ' totals[gPerf[i].name].count += 1;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' var keys = Object.keys(totals);' ). lo_buf->add( ' for (var j = keys.length - 1; j >= 0; j--) {' ). lo_buf->add( ' console.log(prefix' ). lo_buf->add( ' + " " + keys[j] + ": "' ). lo_buf->add( ' + totals[keys[j]].time.toFixed(3) + "ms"' ). lo_buf->add( ' + " (" + totals[keys[j]].count.toFixed() + ")");' ). lo_buf->add( ' }' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function perfLog(name, startTime) {' ). lo_buf->add( ' gPerf.push({ name: name, time: window.performance.now() - startTime });' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function perfClear() {' ). lo_buf->add( ' gPerf = [];' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Repo Overview Logic' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( 'function findStyleSheetByName(name) {' ). lo_buf->add( ' for (var s = 0; s < document.styleSheets.length; s++) {' ). lo_buf->add( ' var styleSheet = document.styleSheets[s];' ). lo_buf->add( ' var classes = styleSheet.cssRules || styleSheet.rules;' ). lo_buf->add( ' for (var i = 0; i < classes.length; i++) {' ). lo_buf->add( ' if (classes[i].selectorText === name) return classes[i];' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function getIndocStyleSheet() {' ). lo_buf->add( ' for (var s = 0; s < document.styleSheets.length; s++) {' ). lo_buf->add( ' if (!document.styleSheets[s].href) return document.styleSheets[s]; // One with empty href' ). lo_buf->add( ' }' ). lo_buf->add( ' // None found ? create one' ). lo_buf->add( ' var style = document.createElement("style");' ). lo_buf->add( ' document.head.appendChild(style);' ). lo_buf->add( ' return style.sheet;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function RepoOverViewHelper(opts) {' ). lo_buf->add( ' if (opts && opts.focusFilterKey) {' ). lo_buf->add( ' this.focusFilterKey = opts.focusFilterKey;' ). lo_buf->add( ' }' ). lo_buf->add( ' this.setHooks();' ). lo_buf->add( ' this.pageId = "RepoOverViewHelperState"; // constant is OK for this case' ). lo_buf->add( ' this.isDetailsDisplayed = false;' ). lo_buf->add( ' this.isOnlyFavoritesDisplayed = false;' ). lo_buf->add( ' this.detailCssClass = findStyleSheetByName(".repo-overview .ro-detail");' ). lo_buf->add( '' ). lo_buf->add( ' var icon = document.getElementById("icon-filter-detail");' ). lo_buf->add( ' this.toggleFilterIcon(icon, this.isDetailsDisplayed);' ). lo_buf->add( ' this.registerRowSelection();' ). lo_buf->add( ' this.registerKeyboardShortcuts();' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.setHooks = function() {' ). lo_buf->add( ' window.onload = this.onPageLoad.bind(this);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.onPageLoad = function() {' ). lo_buf->add( ' var data = window.localStorage && JSON.parse(window.localStorage.getItem(this.pageId));' ). lo_buf->add( ' if (data) {' ). lo_buf->add( ' if (data.isDetailsDisplayed) {' ). lo_buf->add( ' this.toggleItemsDetail(true);' ). lo_buf->add( ' }' ). lo_buf->add( ' if (data.selectedRepoKey) {' ). lo_buf->add( ' this.selectRowByRepoKey(data.selectedRepoKey);' ). lo_buf->add( ' } else {' ). lo_buf->add( ' this.selectRowByIndex(0);' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.registerKeyboardShortcuts = function() {' ). lo_buf->add( ' var self = this;' ). lo_buf->add( ' document.addEventListener("keypress", function(event) {' ). lo_buf->add( ' if (document.activeElement.id === "filter") {' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( ' if (self.focusFilterKey && event.key === self.focusFilterKey && !CommandPalette.isVisible()) {' ). lo_buf->add( ' var filterInput = document.getElementById("filter");' ). lo_buf->add( ' if (filterInput) filterInput.focus();' ). lo_buf->add( ' event.preventDefault();' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' var keycode = event.keyCode;' ). lo_buf->add( ' var rows = Array.prototype.slice.call(self.getVisibleRows());' ). lo_buf->add( ' var selected = document.querySelector(".repo-overview tr.selected");' ). lo_buf->add( ' var indexOfSelected = rows.indexOf(selected);' ). lo_buf->add( ' var lastRow = rows.length - 1;' ). lo_buf->add( '' ). lo_buf->add( ' if (keycode == 13 && document.activeElement.tagName.toLowerCase() != "input") {' ). lo_buf->add( ' // "enter" to open, unless command field has focus' ). lo_buf->add( ' self.openSelectedRepo();' ). lo_buf->add( ' } else if ((keycode == 52 || keycode == 56) && indexOfSelected > 0) {' ). lo_buf->add( ' // "4,8" for previous, digits are the numlock keys' ). lo_buf->add( ' // NB: numpad must be activated, keypress does not detect arrows' ). lo_buf->add( ' // if we need arrows it will be keydown. But then mind the keycodes, they may change !' ). lo_buf->add( ' // e.g. 100 is ''d'' with keypress (and conflicts with diff hotkey), and also it is arrow-left keydown' ). lo_buf->add( ' self.selectRowByIndex(indexOfSelected - 1);' ). lo_buf->add( ' } else if ((keycode == 54 || keycode == 50) && indexOfSelected < lastRow) {' ). lo_buf->add( ' // "6,2" for next' ). lo_buf->add( ' self.selectRowByIndex(indexOfSelected + 1);' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.openSelectedRepo = function() {' ). lo_buf->add( ' this.selectedRepoKey = document.querySelector(".repo-overview tr.selected").dataset.key;' ). lo_buf->add( ' this.saveLocalStorage();' ). lo_buf->add( ' document.querySelector(".repo-overview tr.selected td.ro-go a").click();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.selectRowByIndex = function(index) {' ). lo_buf->add( ' var rows = this.getVisibleRows();' ). lo_buf->add( ' if (rows.length >= index) {' ). lo_buf->add( ' var selectedRow = rows[index];' ). lo_buf->add( ' if (selectedRow.classList.contains("selected")) {' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' this.deselectAllRows();' ). lo_buf->add( ' rows[index].classList.add("selected");' ). lo_buf->add( ' this.selectedRepoKey = selectedRow.dataset.key;' ). lo_buf->add( ' this.updateActionLinks(selectedRow);' ). lo_buf->add( ' this.saveLocalStorage();' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.selectRowByRepoKey = function(key) {' ). lo_buf->add( ' var attributeQuery = "[data-key=''" + key + "'']";' ). lo_buf->add( ' var row = document.querySelector(".repo-overview tbody tr" + attributeQuery);' ). lo_buf->add( ' // navigation to already selected repo' ). lo_buf->add( ' if (row.dataset.key === key && row.classList.contains("selected")) {' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' this.deselectAllRows();' ). lo_buf->add( ' row.classList.add("selected");' ). lo_buf->add( ' this.selectedRepoKey = key;' ). lo_buf->add( ' this.updateActionLinks(row);' ). lo_buf->add( ' this.saveLocalStorage();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.updateActionLinks = function(selectedRow) {' ). lo_buf->add( ' // now we have a repo selected, determine which action buttons are relevant' ). lo_buf->add( ' var selectedRepoKey = selectedRow.dataset.key;' ). lo_buf->add( ' var selectedRepoIsOffline = selectedRow.dataset.offline === "X";' ). lo_buf->add( '' ). lo_buf->add( ' var actionLinks = document.querySelectorAll("a.action_link");' ). lo_buf->add( ' actionLinks.forEach(function(link) {' ). lo_buf->add( ' // adjust repo key in urls' ). lo_buf->add( ' link.href = link.href.replace(/\?key=(#|\d+)/, "?key=" + selectedRepoKey);' ). lo_buf->add( '' ). lo_buf->add( ' // toggle button visibility' ). lo_buf->add( ' if (link.classList.contains("action_offline_repo")) {' ). lo_buf->add( ' if (selectedRepoIsOffline) {' ). lo_buf->add( ' link.parentElement.classList.add("enabled");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' link.parentElement.classList.remove("enabled");' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' else if (link.classList.contains("action_online_repo")) {' ). lo_buf->add( ' if (!selectedRepoIsOffline) {' ). lo_buf->add( ' link.parentElement.classList.add("enabled");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' link.parentElement.classList.remove("enabled");' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' else {' ). lo_buf->add( ' // if the action is for both repository types, it will only have the .action_link class' ). lo_buf->add( ' // it still needs to be toggled as we want to hide everything if no repo is selected' ). lo_buf->add( ' link.parentElement.classList.add("enabled");' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.deselectAllRows = function() {' ). lo_buf->add( ' document.querySelectorAll(".repo-overview tbody tr").forEach(function(x) {' ). lo_buf->add( ' x.classList.remove("selected");' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.getVisibleRows = function() {' ). lo_buf->add( ' return document.querySelectorAll(".repo-overview tbody tr:not(.nodisplay)");' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.registerRowSelection = function() {' ). lo_buf->add( ' var self = this;' ). lo_buf->add( ' document.querySelectorAll(".repo-overview tr td:not(.ro-go)").forEach(function(repoListRowCell) {' ). lo_buf->add( ' repoListRowCell.addEventListener("click", function() {' ). lo_buf->add( ' self.selectRowByRepoKey(this.parentElement.dataset.key);' ). lo_buf->add( ' });' ). lo_buf->add( ' });' ). lo_buf->add( '' ). lo_buf->add( ' document.querySelectorAll(".repo-overview tr td.ro-go").forEach(function(openRepoIcon) {' ). lo_buf->add( ' openRepoIcon.addEventListener("click", function() {' ). lo_buf->add( ' var selectedRow = this.parentElement;' ). lo_buf->add( ' self.selectRowByRepoKey(selectedRow.dataset.key);' ). lo_buf->add( ' self.openSelectedRepo();' ). lo_buf->add( ' });' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.toggleRepoListDetail = function(forceDisplay) {' ). lo_buf->add( ' if (this.detailCssClass) {' ). lo_buf->add( ' this.toggleItemsDetail(forceDisplay);' ). lo_buf->add( ' this.saveLocalStorage();' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.toggleItemsDetail = function(forceDisplay) {' ). lo_buf->add( ' if (this.detailCssClass) {' ). lo_buf->add( ' this.isDetailsDisplayed = forceDisplay || !this.isDetailsDisplayed;' ). lo_buf->add( '' ). lo_buf->add( ' // change layout to wide if details are displayed' ). lo_buf->add( ' if (this.isDetailsDisplayed) {' ). lo_buf->add( ' document.body.classList.remove("centered");' ). lo_buf->add( ' document.body.classList.add("full_width");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' document.body.classList.add("centered");' ). lo_buf->add( ' document.body.classList.remove("full_width");' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' this.detailCssClass.style.display = this.isDetailsDisplayed ? "" : "none";' ). lo_buf->add( '' ). lo_buf->add( ' var icon = document.getElementById("icon-filter-detail");' ). lo_buf->add( ' this.toggleFilterIcon(icon, this.isDetailsDisplayed);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.toggleFilterIcon = function(icon, isEnabled) {' ). lo_buf->add( ' if (isEnabled) {' ). lo_buf->add( ' icon.classList.remove("grey");' ). lo_buf->add( ' icon.classList.add("blue");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' icon.classList.remove("blue");' ). lo_buf->add( ' icon.classList.add("grey");' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'RepoOverViewHelper.prototype.saveLocalStorage = function() {' ). lo_buf->add( ' if (!window.localStorage) return;' ). lo_buf->add( ' var data = {' ). lo_buf->add( ' isDetailsDisplayed : this.isDetailsDisplayed,' ). lo_buf->add( ' isOnlyFavoritesDisplayed: this.isOnlyFavoritesDisplayed,' ). lo_buf->add( ' selectedRepoKey : this.selectedRepoKey,' ). lo_buf->add( ' };' ). lo_buf->add( ' window.localStorage.setItem(this.pageId, JSON.stringify(data));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Staging Logic' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '// Stage helper constructor' ). lo_buf->add( 'function StageHelper(params) {' ). lo_buf->add( ' this.pageSeed = params.seed;' ). lo_buf->add( ' this.formAction = params.formAction;' ). lo_buf->add( ' this.patchAction = params.patchAction;' ). lo_buf->add( ' this.user = params.user;' ). lo_buf->add( ' this.ids = params.ids;' ). lo_buf->add( ' this.selectedCount = 0;' ). lo_buf->add( ' this.filteredCount = 0;' ). lo_buf->add( ' this.lastFilterValue = "";' ). lo_buf->add( ' this.focusFilterKey = params.focusFilterKey;' ). lo_buf->add( '' ). lo_buf->add( ' // DOM nodes' ). lo_buf->add( ' this.dom = {' ). lo_buf->add( ' stageTab : document.getElementById(params.ids.stageTab),' ). lo_buf->add( ' commitAllBtn : document.getElementById(params.ids.commitAllBtn),' ). lo_buf->add( ' commitSelectedBtn: document.getElementById(params.ids.commitSelectedBtn),' ). lo_buf->add( ' commitFilteredBtn: document.getElementById(params.ids.commitFilteredBtn),' ). lo_buf->add( ' patchBtn : document.getElementById(params.ids.patchBtn),' ). lo_buf->add( ' objectSearch : document.getElementById(params.ids.objectSearch),' ). lo_buf->add( ' selectedCounter : null,' ). lo_buf->add( ' filteredCounter : null,' ). lo_buf->add( ' };' ). lo_buf->add( ' this.findCounters();' ). lo_buf->add( '' ). lo_buf->add( ' // Table columns (autodetection)' ). lo_buf->add( ' this.colIndex = this.detectColumns();' ). lo_buf->add( ' this.filterTargets = ["name", "user", "transport"];' ). lo_buf->add( '' ). lo_buf->add( ' // Constants' ). lo_buf->add( ' this.HIGHLIGHT_STYLE = "highlight";' ). lo_buf->add( ' this.STATUS = {' ). lo_buf->add( ' add : "A",' ). lo_buf->add( ' remove : "R",' ). lo_buf->add( ' ignore : "I",' ). lo_buf->add( ' reset : "?",' ). lo_buf->add( ' isValid: function(status) { return "ARI?".indexOf(status) == -1 }' ). lo_buf->add( ' };' ). lo_buf->add( '' ). lo_buf->add( ' this.TEMPLATES = {' ). lo_buf->add( ' cmdReset : "reset",' ). lo_buf->add( ' cmdLocal : "add",' ). lo_buf->add( ' cmdRemote: "ignoreremove"' ). lo_buf->add( ' };' ). lo_buf->add( '' ). lo_buf->add( ' this.setHooks();' ). lo_buf->add( ' if (this.user) this.injectFilterMe();' ). lo_buf->add( ' Hotkeys.addHotkeyToHelpSheet("^Enter", "Commit");' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'StageHelper.prototype.findCounters = function() {' ). lo_buf->add( ' this.dom.selectedCounter = this.dom.commitSelectedBtn.querySelector("span.counter");' ). lo_buf->add( ' this.dom.filteredCounter = this.dom.commitFilteredBtn.querySelector("span.counter");' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'StageHelper.prototype.injectFilterMe = function() {' ). lo_buf->add( ' var tabFirstHead = this.dom.stageTab.tHead.rows[0];' ). lo_buf->add( ' if (!tabFirstHead || tabFirstHead.className !== "local") {' ). lo_buf->add( ' return; // for the case only "remove part" is displayed' ). lo_buf->add( ' }' ). lo_buf->add( ' var changedByHead = tabFirstHead.cells[this.colIndex.user];' ). lo_buf->add( '' ). lo_buf->add( ' changedByHead.innerText = changedByHead.innerText + " (";' ). lo_buf->add( '' ). lo_buf->add( ' var a = document.createElement("A");' ). lo_buf->add( ' a.appendChild(document.createTextNode("me"));' ). lo_buf->add( ' a.onclick = this.onFilterMe.bind(this);' ). lo_buf->add( ' a.href = "#";' ). lo_buf->add( ' changedByHead.appendChild(a);' ). lo_buf->add( ' changedByHead.appendChild(document.createTextNode(")"));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'StageHelper.prototype.onFilterMe = function() {' ). lo_buf->add( ' this.dom.objectSearch.value = this.user;' ). lo_buf->add( ' this.onFilter({ type: "keypress", which: 13, target: this.dom.objectSearch });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Hook global click listener on table, load/unload actions' ). lo_buf->add( 'StageHelper.prototype.setHooks = function() {' ). lo_buf->add( ' window.onkeypress = this.onCtrlEnter.bind(this);' ). lo_buf->add( ' this.dom.stageTab.onclick = this.onTableClick.bind(this);' ). lo_buf->add( ' this.dom.commitSelectedBtn.onclick = this.submit.bind(this);' ). lo_buf->add( ' this.dom.commitFilteredBtn.onclick = this.submitVisible.bind(this);' ). lo_buf->add( ' this.dom.patchBtn.onclick = this.submitPatch.bind(this);' ). lo_buf->add( ' this.dom.objectSearch.oninput = this.onFilter.bind(this);' ). lo_buf->add( ' this.dom.objectSearch.onkeypress = this.onFilter.bind(this);' ). lo_buf->add( ' window.onbeforeunload = this.onPageUnload.bind(this);' ). lo_buf->add( ' window.onload = this.onPageLoad.bind(this);' ). lo_buf->add( '' ). lo_buf->add( ' var self = this;' ). lo_buf->add( ' document.addEventListener("keypress", function(event) {' ). lo_buf->add( ' if (document.activeElement.id !== self.ids.objectSearch' ). lo_buf->add( ' && self.focusFilterKey && event.key === self.focusFilterKey' ). lo_buf->add( ' && !CommandPalette.isVisible()) {' ). lo_buf->add( '' ). lo_buf->add( ' self.dom.objectSearch.focus();' ). lo_buf->add( ' event.preventDefault();' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Detect column index' ). lo_buf->add( 'StageHelper.prototype.detectColumns = function() {' ). lo_buf->add( ' var dataRow = this.dom.stageTab.tBodies[0].rows[0];' ). lo_buf->add( ' var colIndex = {};' ). lo_buf->add( '' ). lo_buf->add( ' for (var i = dataRow.cells.length - 1; i >= 0; i--) {' ). lo_buf->add( ' if (dataRow.cells[i].className) colIndex[dataRow.cells[i].className] = i;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' return colIndex;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Store table state on leaving the page' ). lo_buf->add( 'StageHelper.prototype.onPageUnload = function() {' ). lo_buf->add( ' if (!window.sessionStorage) return;' ). lo_buf->add( '' ). lo_buf->add( ' var data = this.collectData();' ). lo_buf->add( ' window.sessionStorage.setItem(this.pageSeed, JSON.stringify(data));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Re-store table state on entering the page' ). lo_buf->add( 'StageHelper.prototype.onPageLoad = function() {' ). lo_buf->add( ' var data = window.sessionStorage && JSON.parse(window.sessionStorage.getItem(this.pageSeed));' ). lo_buf->add( '' ). lo_buf->add( ' this.iterateStageTab(true, function(row) {' ). lo_buf->add( ' var status = data && data[row.cells[this.colIndex["name"]].innerText];' ). lo_buf->add( ' this.updateRow(row, status || this.STATUS.reset);' ). lo_buf->add( ' });' ). lo_buf->add( '' ). lo_buf->add( ' this.updateMenu();' ). lo_buf->add( ' if (this.dom.objectSearch.value) {' ). lo_buf->add( ' this.applyFilterValue(this.dom.objectSearch.value);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Table event handler, change status' ). lo_buf->add( 'StageHelper.prototype.onTableClick = function(event) {' ). lo_buf->add( ' var target = event.target || event.srcElement;' ). lo_buf->add( ' if (!target) return;' ). lo_buf->add( '' ). lo_buf->add( ' var td;' ). lo_buf->add( ' if (target.tagName === "A") {' ). lo_buf->add( ' td = target.parentNode;' ). lo_buf->add( ' } else if (target.tagName === "TD") {' ). lo_buf->add( ' td = target;' ). lo_buf->add( ' if (td.children.length === 1 && td.children[0].tagName === "A") {' ). lo_buf->add( ' target = td.children[0];' ). lo_buf->add( ' } else return;' ). lo_buf->add( ' } else return;' ). lo_buf->add( '' ). lo_buf->add( ' if (["TD", "TH"].indexOf(td.tagName) == -1 || td.className != "cmd") return;' ). lo_buf->add( '' ). lo_buf->add( ' var status = this.STATUS[target.innerText]; // Convert anchor text to status' ). lo_buf->add( ' var targetRow = td.parentNode;' ). lo_buf->add( '' ). lo_buf->add( ' if (td.tagName === "TD") {' ). lo_buf->add( ' this.updateRow(targetRow, status);' ). lo_buf->add( ' } else { // TH' ). lo_buf->add( ' this.iterateStageTab(true, function(row) {' ). lo_buf->add( ' if (row.style.display !== "none" // Not filtered out' ). lo_buf->add( ' && row.className === targetRow.className // Same context as header' ). lo_buf->add( ' ) {' ). lo_buf->add( ' this.updateRow(row, status);' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' this.updateMenu();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'StageHelper.prototype.onCtrlEnter = function(e) {' ). lo_buf->add( ' if (e.ctrlKey && (e.which === 10 || e.key === "Enter")) {' ). lo_buf->add( ' var clickMap = {' ). lo_buf->add( ' "default" : this.dom.commitAllBtn,' ). lo_buf->add( ' "selected": this.dom.commitSelectedBtn,' ). lo_buf->add( ' "filtered": this.dom.commitFilteredBtn' ). lo_buf->add( ' };' ). lo_buf->add( ' clickMap[this.calculateActiveCommitCommand()].click();' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Search object' ). lo_buf->add( 'StageHelper.prototype.onFilter = function(e) {' ). lo_buf->add( ' if ( // Enter hit or clear, IE SUCKS !' ). lo_buf->add( ' e.type === "input" && !e.target.value && this.lastFilterValue' ). lo_buf->add( ' || e.type === "keypress" && (e.which === 13 || e.key === "Enter") && !e.ctrlKey) {' ). lo_buf->add( '' ). lo_buf->add( ' this.applyFilterValue(e.target.value);' ). lo_buf->add( ' submitSapeventForm({ filterValue: e.target.value }, "stage_filter", "post");' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'StageHelper.prototype.applyFilterValue = function(sFilterValue) {' ). lo_buf->add( ' this.lastFilterValue = sFilterValue;' ). lo_buf->add( ' this.filteredCount = this.iterateStageTab(true, this.applyFilterToRow, sFilterValue);' ). lo_buf->add( ' this.updateMenu();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Apply filter to a single stage line - hide or show' ). lo_buf->add( 'StageHelper.prototype.applyFilterToRow = function(row, filter) {' ). lo_buf->add( ' // Collect data cells' ). lo_buf->add( ' var targets = this.filterTargets.map(function(attr) {' ). lo_buf->add( ' // Get the innermost tag with the text we want to filter' ). lo_buf->add( ' // text: elem = td-tag' ). lo_buf->add( ' // text: elem = a-tag' ). lo_buf->add( ' var elem = row.cells[this.colIndex[attr]];' ). lo_buf->add( ' var elemA = elem.getElementsByTagName("A")[0];' ). lo_buf->add( '' ). lo_buf->add( ' if (elemA) elem = elemA;' ). lo_buf->add( ' return {' ). lo_buf->add( ' elem : elem,' ). lo_buf->add( ' plainText: elem.innerText.replace(/ /g, "\u00a0"), // without tags, with encoded spaces' ). lo_buf->add( ' curHtml : elem.innerHTML' ). lo_buf->add( ' };' ). lo_buf->add( ' }, this);' ). lo_buf->add( '' ). lo_buf->add( ' var isVisible = false;' ). lo_buf->add( '' ). lo_buf->add( ' // Apply filter to cells, mark filtered text' ). lo_buf->add( ' for (var i = targets.length - 1; i >= 0; i--) {' ). lo_buf->add( ' var target = targets[i];' ). lo_buf->add( ' // Ignore case of filter' ). lo_buf->add( ' var regFilter = new RegExp("(" + filter + ")", "gi");' ). lo_buf->add( '' ). lo_buf->add( ' target.newHtml = (filter)' ). lo_buf->add( ' ? target.plainText.replace(regFilter, "$1")' ). lo_buf->add( ' : target.plainText;' ). lo_buf->add( ' target.isChanged = target.newHtml !== target.curHtml;' ). lo_buf->add( ' isVisible = isVisible || !filter || target.newHtml !== target.plainText;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Update DOM' ). lo_buf->add( ' row.style.display = isVisible ? "" : "none";' ). lo_buf->add( ' for (var j = targets.length - 1; j >= 0; j--) {' ). lo_buf->add( ' if (targets[j].isChanged) targets[j].elem.innerHTML = targets[j].newHtml;' ). lo_buf->add( ' }' ). lo_buf->add( ' return isVisible ? 1 : 0;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Get how status should affect object counter' ). lo_buf->add( 'StageHelper.prototype.getStatusImpact = function(status) {' ). lo_buf->add( ' if (typeof status !== "string"' ). lo_buf->add( ' || status.length !== 1' ). lo_buf->add( ' || this.STATUS.isValid(status)) {' ). lo_buf->add( ' alert("Unknown status");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' return (status !== this.STATUS.reset) ? 1: 0;' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Update table line' ). lo_buf->add( 'StageHelper.prototype.updateRow = function(row, newStatus) {' ). lo_buf->add( ' var oldStatus = row.cells[this.colIndex["status"]].innerText;' ). lo_buf->add( '' ). lo_buf->add( ' if (oldStatus !== newStatus) {' ). lo_buf->add( ' this.updateRowStatus(row, newStatus);' ). lo_buf->add( ' this.updateRowCommand(row, newStatus);' ). lo_buf->add( ' } else if (!row.cells[this.colIndex["cmd"]].children.length) {' ). lo_buf->add( ' this.updateRowCommand(row, newStatus); // For initial run' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' this.selectedCount += this.getStatusImpact(newStatus) - this.getStatusImpact(oldStatus);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Update Status cell (render set of commands)' ). lo_buf->add( 'StageHelper.prototype.updateRowStatus = function(row, status) {' ). lo_buf->add( ' row.cells[this.colIndex["status"]].innerText = status;' ). lo_buf->add( ' if (status === this.STATUS.reset) {' ). lo_buf->add( ' row.cells[this.colIndex["status"]].classList.remove(this.HIGHLIGHT_STYLE);' ). lo_buf->add( ' } else {' ). lo_buf->add( ' row.cells[this.colIndex["status"]].classList.add(this.HIGHLIGHT_STYLE);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Update Command cell (render set of commands)' ). lo_buf->add( 'StageHelper.prototype.updateRowCommand = function(row, status) {' ). lo_buf->add( ' var cell = row.cells[this.colIndex["cmd"]];' ). lo_buf->add( ' if (status === this.STATUS.reset) {' ). lo_buf->add( ' cell.innerHTML = (row.className == "local")' ). lo_buf->add( ' ? this.TEMPLATES.cmdLocal' ). lo_buf->add( ' : this.TEMPLATES.cmdRemote;' ). lo_buf->add( ' } else {' ). lo_buf->add( ' cell.innerHTML = this.TEMPLATES.cmdReset;' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'StageHelper.prototype.calculateActiveCommitCommand = function() {' ). lo_buf->add( ' var active;' ). lo_buf->add( ' if (this.selectedCount > 0) {' ). lo_buf->add( ' active = "selected";' ). lo_buf->add( ' } else if (this.lastFilterValue) {' ). lo_buf->add( ' active = "filtered";' ). lo_buf->add( ' } else {' ). lo_buf->add( ' active = "default";' ). lo_buf->add( ' }' ). lo_buf->add( ' return active;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Update menu items visibility' ). lo_buf->add( 'StageHelper.prototype.updateMenu = function() {' ). lo_buf->add( ' var display = this.calculateActiveCommitCommand();' ). lo_buf->add( '' ). lo_buf->add( ' if (display === "selected") this.dom.selectedCounter.innerText = this.selectedCount.toString();' ). lo_buf->add( ' if (display === "filtered") this.dom.filteredCounter.innerText = this.filteredCount.toString();' ). lo_buf->add( '' ). lo_buf->add( ' this.dom.commitAllBtn.style.display = display === "default" ? "" : "none";' ). lo_buf->add( ' this.dom.commitSelectedBtn.style.display = display === "selected" ? "" : "none";' ). lo_buf->add( ' this.dom.commitFilteredBtn.style.display = display === "filtered" ? "" : "none";' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Submit stage state to the server' ). lo_buf->add( 'StageHelper.prototype.submit = function() {' ). lo_buf->add( ' submitSapeventForm(this.collectData(), this.formAction);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'StageHelper.prototype.submitVisible = function() {' ). lo_buf->add( ' this.markVisiblesAsAdded();' ). lo_buf->add( ' submitSapeventForm(this.collectData(), this.formAction);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'StageHelper.prototype.submitPatch = function() {' ). lo_buf->add( ' submitSapeventForm(this.collectData(), this.patchAction);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Extract data from the table' ). lo_buf->add( 'StageHelper.prototype.collectData = function() {' ). lo_buf->add( ' var data = {};' ). lo_buf->add( ' this.iterateStageTab(false, function(row) {' ). lo_buf->add( ' data[row.cells[this.colIndex["name"]].innerText] = row.cells[this.colIndex["status"]].innerText;' ). lo_buf->add( ' });' ). lo_buf->add( ' return data;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'StageHelper.prototype.markVisiblesAsAdded = function() {' ). lo_buf->add( ' this.iterateStageTab(false, function(row) {' ). lo_buf->add( ' // TODO refactor, unify updateRow logic' ). lo_buf->add( ' if (row.style.display === "" && row.className === "local") { // visible' ). lo_buf->add( ' this.updateRow(row, this.STATUS.add);' ). lo_buf->add( ' } else {' ). lo_buf->add( ' this.updateRow(row, this.STATUS.reset);' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Table iteration helper' ). lo_buf->add( 'StageHelper.prototype.iterateStageTab = function(changeMode, cb /*, ...*/) {' ). lo_buf->add( ' var restArgs = Array.prototype.slice.call(arguments, 2);' ). lo_buf->add( ' var table = this.dom.stageTab;' ). lo_buf->add( ' var retTotal = 0;' ). lo_buf->add( '' ). lo_buf->add( ' if (changeMode) {' ). lo_buf->add( ' var scrollOffset = window.pageYOffset;' ). lo_buf->add( '' ). lo_buf->add( ' this.dom.stageTab.style.display = "none";' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' for (var b = 0, bN = table.tBodies.length; b < bN; b++) {' ). lo_buf->add( ' var tbody = table.tBodies[b];' ). lo_buf->add( ' for (var r = 0, rN = tbody.rows.length; r < rN; r++) {' ). lo_buf->add( ' var args = [tbody.rows[r]].concat(restArgs);' ). lo_buf->add( ' var retVal = cb.apply(this, args); // callback' ). lo_buf->add( '' ). lo_buf->add( ' if (typeof retVal === "number") retTotal += retVal;' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' if (changeMode) {' ). lo_buf->add( ' this.dom.stageTab.style.display = "";' ). lo_buf->add( ' window.scrollTo(0, scrollOffset);' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' return retTotal;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Check List Wrapper' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( 'function CheckListWrapper(id, cbAction, cbActionOnlyMyChanges) {' ). lo_buf->add( ' this.id = document.getElementById(id);' ). lo_buf->add( ' this.cbAction = cbAction;' ). lo_buf->add( ' this.cbActionOnlyMyChanges = cbActionOnlyMyChanges;' ). lo_buf->add( ' this.id.onclick = this.onClick.bind(this);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'CheckListWrapper.prototype.onClick = function(e) { // eslint-disable-line no-unused-vars' ). lo_buf->add( ' // Get nodes' ). lo_buf->add( ' var target = event.target || event.srcElement;' ). lo_buf->add( ' if (!target) return;' ). lo_buf->add( ' if (target.tagName !== "A") { target = target.parentNode } // icon clicked' ). lo_buf->add( ' if (target.tagName !== "A") return;' ). lo_buf->add( ' if (target.parentNode.tagName !== "LI") return;' ). lo_buf->add( '' ). lo_buf->add( ' var nodeA = target;' ). lo_buf->add( ' var nodeLi = target.parentNode;' ). lo_buf->add( ' var nodeIcon = target.children[0];' ). lo_buf->add( ' if (!nodeIcon.classList.contains("icon")) return;' ). lo_buf->add( '' ). lo_buf->add( ' // Node updates' ). lo_buf->add( ' var option = nodeA.innerText;' ). lo_buf->add( ' var oldState = nodeLi.getAttribute("data-check");' ). lo_buf->add( ' if (oldState === null) return; // no data-check attribute - non-checkbox' ). lo_buf->add( ' var newState = oldState === "X" ? false : true;' ). lo_buf->add( '' ). lo_buf->add( ' if (newState) {' ). lo_buf->add( ' nodeIcon.classList.remove("grey");' ). lo_buf->add( ' nodeIcon.classList.add("blue");' ). lo_buf->add( ' nodeLi.setAttribute("data-check", "X");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' nodeIcon.classList.remove("blue");' ). lo_buf->add( ' nodeIcon.classList.add("grey");' ). lo_buf->add( ' nodeLi.setAttribute("data-check", "");' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Action callback, special handling for "Only My Changes"' ). lo_buf->add( ' if (option === "Only my changes") {' ). lo_buf->add( ' this.cbActionOnlyMyChanges(nodeLi.getAttribute("data-aux"), newState);' ). lo_buf->add( '' ). lo_buf->add( ' // hide "Changed By" menu' ). lo_buf->add( ' } else {' ). lo_buf->add( ' this.cbAction(nodeLi.getAttribute("data-aux"), option, newState);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Diff Page Logic' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '// Diff helper constructor' ). lo_buf->add( 'function DiffHelper(params) {' ). lo_buf->add( ' this.pageSeed = params.seed;' ). lo_buf->add( ' this.counter = 0;' ). lo_buf->add( ' this.stageAction = params.stageAction;' ). lo_buf->add( '' ). lo_buf->add( ' // DOM nodes' ). lo_buf->add( ' this.dom = {' ). lo_buf->add( ' diffList : document.getElementById(params.ids.diffList),' ). lo_buf->add( ' stageButton: document.getElementById(params.ids.stageButton)' ). lo_buf->add( ' };' ). lo_buf->add( '' ). lo_buf->add( ' this.repoKey = this.dom.diffList.getAttribute("data-repo-key");' ). lo_buf->add( ' if (!this.repoKey) return; // Unexpected' ). lo_buf->add( '' ). lo_buf->add( ' this.dom.jump = document.getElementById(params.ids.jump);' ). lo_buf->add( ' this.dom.jump.onclick = this.onJump.bind(this);' ). lo_buf->add( '' ). lo_buf->add( ' // Checklist wrapper' ). lo_buf->add( ' if (document.getElementById(params.ids.filterMenu)) {' ). lo_buf->add( ' this.checkList = new CheckListWrapper(params.ids.filterMenu, this.onFilter.bind(this), this.onFilterOnlyMyChanges.bind(this));' ). lo_buf->add( ' this.dom.filterButton = document.getElementById(params.ids.filterMenu).parentNode;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Hijack stage command' ). lo_buf->add( ' if (this.dom.stageButton) {' ). lo_buf->add( ' this.dom.stageButton.href = "#";' ). lo_buf->add( ' this.dom.stageButton.onclick = this.onStage.bind(this);' ). lo_buf->add( ' }' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// Action on jump click' ). lo_buf->add( 'DiffHelper.prototype.onJump = function(e) {' ). lo_buf->add( ' var text = ((e.target && e.target.text) || e);' ). lo_buf->add( ' if (!text) return;' ). lo_buf->add( '' ). lo_buf->add( ' var elFile = document.querySelector("[data-file*=''" + text + "'']");' ). lo_buf->add( ' if (!elFile) return;' ). lo_buf->add( '' ). lo_buf->add( ' setTimeout(function() {' ). lo_buf->add( ' elFile.scrollIntoView();' ). lo_buf->add( ' }, 100);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Action on filter click' ). lo_buf->add( 'DiffHelper.prototype.onFilter = function(attr, target, state) {' ). lo_buf->add( ' this.applyFilter(attr, target, state);' ). lo_buf->add( ' this.highlightButton(state);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'DiffHelper.prototype.onFilterOnlyMyChanges = function(username, state) {' ). lo_buf->add( ' this.applyOnlyMyChangesFilter(username, state);' ). lo_buf->add( ' this.counter = 0;' ). lo_buf->add( '' ). lo_buf->add( ' if (state) {' ). lo_buf->add( ' this.dom.filterButton.classList.add("bgorange");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' this.dom.filterButton.classList.remove("bgorange");' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // apply logic on Changed By list items' ). lo_buf->add( ' var changedByListItems = Array.prototype.slice.call(document.querySelectorAll("[data-aux*=changed-by]"));' ). lo_buf->add( '' ). lo_buf->add( ' changedByListItems' ). lo_buf->add( ' .map(function(item) {' ). lo_buf->add( ' var nodeIcon = item.children[0].children[0];' ). lo_buf->add( '' ). lo_buf->add( ' if (state === true) {' ). lo_buf->add( ' if (item.innerText === username) { // current user' ). lo_buf->add( ' item.style.display = "";' ). lo_buf->add( ' item.setAttribute("data-check", "X");' ). lo_buf->add( '' ). lo_buf->add( ' if (nodeIcon) {' ). lo_buf->add( ' nodeIcon.classList.remove("grey");' ). lo_buf->add( ' nodeIcon.classList.add("blue");' ). lo_buf->add( ' }' ). lo_buf->add( ' } else { // other users' ). lo_buf->add( ' item.style.display = "none";' ). lo_buf->add( ' item.setAttribute("data-check", "");' ). lo_buf->add( ' }' ). lo_buf->add( ' } else {' ). lo_buf->add( ' item.style.display = "";' ). lo_buf->add( ' item.setAttribute("data-check", "X");' ). lo_buf->add( '' ). lo_buf->add( ' if (nodeIcon) {' ). lo_buf->add( ' nodeIcon.classList.remove("grey");' ). lo_buf->add( ' nodeIcon.classList.add("blue");' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'DiffHelper.prototype.applyOnlyMyChangesFilter = function(username, state) {' ). lo_buf->add( ' var jumpListItems = Array.prototype.slice.call(document.querySelectorAll("[id*=li_jump]"));' ). lo_buf->add( '' ). lo_buf->add( ' this.iterateDiffList(function(div) {' ). lo_buf->add( ' if (state === true) { // switching on "Only my changes" filter' ). lo_buf->add( ' if (div.getAttribute("data-changed-by") === username) {' ). lo_buf->add( ' div.style.display = state ? "" : "none";' ). lo_buf->add( ' } else {' ). lo_buf->add( ' div.style.display = state ? "none" : "";' ). lo_buf->add( ' }' ). lo_buf->add( ' } else { // disabling' ). lo_buf->add( ' div.style.display = "";' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // hide the file in the jump list' ). lo_buf->add( ' var dataFile = div.getAttribute("data-file");' ). lo_buf->add( ' jumpListItems' ). lo_buf->add( ' .filter(function(item) { return dataFile.includes(item.text) })' ). lo_buf->add( ' .map(function(item) { item.style.display = div.style.display });' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Hide/show diff based on params' ). lo_buf->add( 'DiffHelper.prototype.applyFilter = function(attr, target, state) {' ). lo_buf->add( ' var jumpListItems = Array.prototype.slice.call(document.querySelectorAll("[id*=li_jump]"));' ). lo_buf->add( '' ). lo_buf->add( ' this.iterateDiffList(function(div) {' ). lo_buf->add( ' if (div.getAttribute("data-" + attr) === target) {' ). lo_buf->add( ' div.style.display = state ? "" : "none";' ). lo_buf->add( '' ). lo_buf->add( ' // hide the file in the jump list' ). lo_buf->add( ' var dataFile = div.getAttribute("data-file");' ). lo_buf->add( ' jumpListItems' ). lo_buf->add( ' .filter(function(item) { return dataFile.includes(item.text) })' ). lo_buf->add( ' .map(function(item) { item.style.display = div.style.display });' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Action on stage -> save visible diffs as state for stage page' ). lo_buf->add( 'DiffHelper.prototype.onStage = function(e) { // eslint-disable-line no-unused-vars' ). lo_buf->add( ' if (window.sessionStorage) {' ). lo_buf->add( ' var data = this.buildStageCache();' ). lo_buf->add( ' window.sessionStorage.setItem(this.pageSeed, JSON.stringify(data));' ). lo_buf->add( ' }' ). lo_buf->add( ' var getParams = { key: this.repoKey, seed: this.pageSeed };' ). lo_buf->add( ' submitSapeventForm(getParams, this.stageAction, "get");' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Collect visible diffs' ). lo_buf->add( 'DiffHelper.prototype.buildStageCache = function() {' ). lo_buf->add( ' var list = {};' ). lo_buf->add( ' this.iterateDiffList(function(div) {' ). lo_buf->add( ' var filename = div.getAttribute("data-file");' ). lo_buf->add( ' if (!div.style.display && filename) { // No display override - visible !!' ). lo_buf->add( ' list[filename] = "A"; // Add' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( ' return list;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Table iterator' ). lo_buf->add( 'DiffHelper.prototype.iterateDiffList = function(cb /*, ...*/) {' ). lo_buf->add( ' var restArgs = Array.prototype.slice.call(arguments, 1);' ). lo_buf->add( ' var diffList = this.dom.diffList;' ). lo_buf->add( '' ). lo_buf->add( ' for (var i = 0, iN = diffList.children.length; i < iN; i++) {' ). lo_buf->add( ' var div = diffList.children[i];' ). lo_buf->add( ' if (div.className !== "diff") continue;' ). lo_buf->add( ' var args = [div].concat(restArgs);' ). lo_buf->add( ' cb.apply(this, args);// callback' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Highlight filter button if filter is activated' ). lo_buf->add( 'DiffHelper.prototype.highlightButton = function(state) {' ). lo_buf->add( ' this.counter += state ? -1 : 1;' ). lo_buf->add( ' if (this.counter > 0) {' ). lo_buf->add( ' this.dom.filterButton.classList.add("bgorange");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' this.dom.filterButton.classList.remove("bgorange");' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Collapse or expand diffs' ). lo_buf->add( 'function onDiffCollapse(event) {' ). lo_buf->add( ' var source = event.target || event.srcElement;' ). lo_buf->add( ' var nextDiffContent = source.parentElement.nextElementSibling;' ). lo_buf->add( ' var hide;' ). lo_buf->add( '' ). lo_buf->add( ' if (source.classList.contains("icon-chevron-down")) {' ). lo_buf->add( ' source.classList.remove("icon-chevron-down");' ). lo_buf->add( ' source.classList.add("icon-chevron-right");' ). lo_buf->add( ' hide = true;' ). lo_buf->add( ' } else {' ). lo_buf->add( ' source.classList.remove("icon-chevron-right");' ). lo_buf->add( ' source.classList.add("icon-chevron-down");' ). lo_buf->add( ' hide = false;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' hide ? nextDiffContent.classList.add("nodisplay"): nextDiffContent.classList.remove("nodisplay");' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// Add bottom margin, so that we can scroll to the top of the last file' ). lo_buf->add( 'function addMarginBottom() {' ). lo_buf->add( ' document.getElementsByTagName("body")[0].style.marginBottom = screen.height + "px";' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Diff Page Column Selection' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( 'function DiffColumnSelection() {' ). lo_buf->add( ' this.selectedColumnIdx = -1;' ). lo_buf->add( ' this.lineNumColumnIdx = -1;' ). lo_buf->add( ' //https://stackoverflow.com/questions/2749244/javascript-setinterval-and-this-solution' ). lo_buf->add( ' document.addEventListener("mousedown", this.mousedownEventListener.bind(this));' ). lo_buf->add( ' document.addEventListener("copy", this.copyEventListener.bind(this));' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'DiffColumnSelection.prototype.mousedownEventListener = function(e) {' ). lo_buf->add( ' // Select text in a column of an HTML table and copy to clipboard (in DIFF view)' ). lo_buf->add( ' // (https://stackoverflow.com/questions/6619805/select-text-in-a-column-of-an-html-table)' ). lo_buf->add( ' // Process mousedown event for all TD elements -> apply CSS class at TABLE level.' ). lo_buf->add( ' // (https://stackoverflow.com/questions/40956717/how-to-addeventlistener-to-multiple-elements-in-a-single-line)' ). lo_buf->add( ' var unifiedLineNumColumnIdx = 0;' ). lo_buf->add( ' var unifiedCodeColumnIdx = 3;' ). lo_buf->add( ' var splitLineNumLeftColumnIdx = 0;' ). lo_buf->add( ' var splitCodeLeftColumnIdx = 2;' ). lo_buf->add( ' var splitLineNumRightColumnIdx = 3;' ). lo_buf->add( ' var splitCodeRightColumnIdx = 5;' ). lo_buf->add( '' ). lo_buf->add( ' if (e.button !== 0) return; // function is only valid for left button, not right button' ). lo_buf->add( '' ). lo_buf->add( ' var td = e.target;' ). lo_buf->add( '' ). lo_buf->add( ' while (td != undefined && td.tagName != "TD" && td.tagName != "TBODY") td = td.parentElement;' ). lo_buf->add( ' if (td == undefined) return;' ). lo_buf->add( ' var table = td.parentElement.parentElement;' ). lo_buf->add( '' ). lo_buf->add( ' var patchColumnCount = 0;' ). lo_buf->add( ' if (td.parentElement.cells[0].classList.contains("patch")) {' ). lo_buf->add( ' patchColumnCount = 1;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' if (td.classList.contains("diff_left")) {' ). lo_buf->add( ' table.classList.remove("diff_select_right");' ). lo_buf->add( ' table.classList.add("diff_select_left");' ). lo_buf->add( ' if (window.getSelection() && this.selectedColumnIdx != splitCodeLeftColumnIdx + patchColumnCount) {' ). lo_buf->add( ' // De-select to avoid effect of dragging selection in case the right column was first selected' ). lo_buf->add( ' if (document.body.createTextRange) { // All IE but Edge' ). lo_buf->add( ' // document.getSelection().removeAllRanges() may trigger error' ). lo_buf->add( ' // so use this code which is equivalent but does not fail' ). lo_buf->add( ' // (https://stackoverflow.com/questions/22914075/javascript-error-800a025e-using-range-selector)' ). lo_buf->add( ' range = document.body.createTextRange();' ). lo_buf->add( ' range.collapse();' ). lo_buf->add( ' range.select();' ). lo_buf->add( ' } else {' ). lo_buf->add( ' document.getSelection().removeAllRanges();' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' this.selectedColumnIdx = splitCodeLeftColumnIdx + patchColumnCount;' ). lo_buf->add( ' this.lineNumColumnIdx = splitLineNumLeftColumnIdx + patchColumnCount;' ). lo_buf->add( '' ). lo_buf->add( ' } else if (td.classList.contains("diff_right")) {' ). lo_buf->add( ' table.classList.remove("diff_select_left");' ). lo_buf->add( ' table.classList.add("diff_select_right");' ). lo_buf->add( ' if (window.getSelection() && this.selectedColumnIdx != splitCodeRightColumnIdx + patchColumnCount) {' ). lo_buf->add( ' if (document.body.createTextRange) { // All IE but Edge' ). lo_buf->add( ' // document.getSelection().removeAllRanges() may trigger error' ). lo_buf->add( ' // so use this code which is equivalent but does not fail' ). lo_buf->add( ' // (https://stackoverflow.com/questions/22914075/javascript-error-800a025e-using-range-selector)' ). lo_buf->add( ' var range = document.body.createTextRange();' ). lo_buf->add( ' range.collapse();' ). lo_buf->add( ' range.select();' ). lo_buf->add( ' } else {' ). lo_buf->add( ' document.getSelection().removeAllRanges();' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' this.selectedColumnIdx = splitCodeRightColumnIdx + patchColumnCount;' ). lo_buf->add( ' this.lineNumColumnIdx = splitLineNumRightColumnIdx + patchColumnCount;' ). lo_buf->add( '' ). lo_buf->add( ' } else if (td.classList.contains("diff_unified")) {' ). lo_buf->add( ' this.selectedColumnIdx = unifiedCodeColumnIdx;' ). lo_buf->add( ' this.lineNumColumnIdx = unifiedLineNumColumnIdx;' ). lo_buf->add( '' ). lo_buf->add( ' } else {' ). lo_buf->add( ' this.selectedColumnIdx = -1;' ). lo_buf->add( ' this.lineNumColumnIdx = -1;' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'DiffColumnSelection.prototype.copyEventListener = function(e) {' ). lo_buf->add( ' // Select text in a column of an HTML table and copy to clipboard (in DIFF view)' ). lo_buf->add( ' // (https://stackoverflow.com/questions/6619805/select-text-in-a-column-of-an-html-table)' ). lo_buf->add( ' var td = e.target;' ). lo_buf->add( '' ). lo_buf->add( ' while (td != undefined && td.tagName != "TD" && td.tagName != "TBODY") td = td.parentElement;' ). lo_buf->add( ' if (td != undefined) {' ). lo_buf->add( ' // Use window.clipboardData instead of e.clipboardData' ). lo_buf->add( ' // (https://stackoverflow.com/questions/23470958/ie-10-copy-paste-issue)' ). lo_buf->add( ' var clipboardData = (e.clipboardData == undefined ? window.clipboardData : e.clipboardData);' ). lo_buf->add( ' var text = this.getSelectedText();' ). lo_buf->add( ' clipboardData.setData("text", text);' ). lo_buf->add( ' e.preventDefault();' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'DiffColumnSelection.prototype.getSelectedText = function() {' ). lo_buf->add( ' // Select text in a column of an HTML table and copy to clipboard (in DIFF view)' ). lo_buf->add( ' // (https://stackoverflow.com/questions/6619805/select-text-in-a-column-of-an-html-table)' ). lo_buf->add( ' var sel = window.getSelection();' ). lo_buf->add( ' var range = sel.getRangeAt(0);' ). lo_buf->add( ' var doc = range.cloneContents();' ). lo_buf->add( ' var nodes = doc.querySelectorAll("tr");' ). lo_buf->add( ' var text = "";' ). lo_buf->add( ' if (nodes.length === 0) {' ). lo_buf->add( ' text = doc.textContent;' ). lo_buf->add( ' } else {' ). lo_buf->add( ' var newline = "";' ). lo_buf->add( ' var realThis = this;' ). lo_buf->add( ' var copySide = "";' ). lo_buf->add( ' [].forEach.call(nodes, function(tr, i) {' ). lo_buf->add( ' var cellIdx = (i == 0 ? 0 : realThis.selectedColumnIdx);' ). lo_buf->add( ' if (tr.cells.length > cellIdx) {' ). lo_buf->add( ' var tdSelected = tr.cells[cellIdx];' ). lo_buf->add( ' // decide which side to copy based on first line of selection' ). lo_buf->add( ' if (i == 0) {' ). lo_buf->add( ' copySide = (tdSelected.classList.contains("new") ? "new" : "old" );' ). lo_buf->add( ' }' ). lo_buf->add( ' // copy is interesting only for one side of code, do not copy lines which exist on other side' ). lo_buf->add( ' if (i == 0 || copySide == "new" && !tdSelected.classList.contains("old") || copySide == "old" && !tdSelected.classList.contains("new")) {' ). lo_buf->add( ' text += newline + tdSelected.textContent;' ). lo_buf->add( ' // special processing for TD tag which sometimes contains newline' ). lo_buf->add( ' // (expl: /src/ui/zabapgit_js_common.w3mi.data.js) so do not add newline again in that case.' ). lo_buf->add( ' var lastChar = tdSelected.textContent[tdSelected.textContent.length - 1];' ). lo_buf->add( ' if (lastChar == "\n") newline = "";' ). lo_buf->add( ' else newline = "\n";' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' });' ). lo_buf->add( ' }' ). lo_buf->add( ' return text;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Display Helper' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '// Toggle display of changelog (news) and message popups' ). lo_buf->add( 'function toggleDisplay(divId) {' ). lo_buf->add( ' var div = document.getElementById(divId);' ). lo_buf->add( '' ). lo_buf->add( ' if (div) div.style.display = (div.style.display) ? "" : "none";' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Keyboard Navigation' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( 'function KeyNavigation() { }' ). lo_buf->add( '' ). lo_buf->add( 'KeyNavigation.prototype.onkeydown = function(event) {' ). lo_buf->add( ' if (event.defaultPrevented) return;' ). lo_buf->add( '' ). lo_buf->add( ' // navigate with arrows through list items and support pressing links with enter and space' ). lo_buf->add( ' var isHandled = false;' ). lo_buf->add( ' if (event.key === "Enter" || event.key === "") {' ). lo_buf->add( ' isHandled = this.onEnterOrSpace();' ). lo_buf->add( ' } else if (/Down$/.test(event.key)) {' ). lo_buf->add( ' isHandled = this.onArrowDown();' ). lo_buf->add( ' } else if (/Up$/.test(event.key)) {' ). lo_buf->add( ' isHandled = this.onArrowUp();' ). lo_buf->add( ' } else if (event.key === "Backspace") {' ). lo_buf->add( ' isHandled = this.onBackspace();' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' if (isHandled) event.preventDefault();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'KeyNavigation.prototype.onEnterOrSpace = function() {' ). lo_buf->add( ' if (document.activeElement.nodeName !== "A") return;' ). lo_buf->add( ' var anchor = document.activeElement;' ). lo_buf->add( '' ). lo_buf->add( ' if (anchor.href.replace(/#$/, "") === document.location.href.replace(/#$/, "")' ). lo_buf->add( ' && !anchor.onclick' ). lo_buf->add( ' && anchor.parentElement' ). lo_buf->add( ' && anchor.parentElement.nodeName === "LI") {' ). lo_buf->add( ' anchor.parentElement.classList.toggle("force-nav-hover");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' anchor.click();' ). lo_buf->add( ' }' ). lo_buf->add( ' return true;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'KeyNavigation.prototype.focusListItem = function(li) {' ). lo_buf->add( ' var anchor = li.firstElementChild;' ). lo_buf->add( ' if (!anchor || anchor.nodeName !== "A") return false;' ). lo_buf->add( ' anchor.focus();' ). lo_buf->add( ' return true;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'KeyNavigation.prototype.closeDropdown = function(dropdownLi) {' ). lo_buf->add( ' dropdownLi.classList.remove("force-nav-hover");' ). lo_buf->add( ' if (dropdownLi.firstElementChild.nodeName === "A") dropdownLi.firstElementChild.focus();' ). lo_buf->add( ' return true;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'KeyNavigation.prototype.onBackspace = function() {' ). lo_buf->add( ' var activeElement = document.activeElement;' ). lo_buf->add( '' ). lo_buf->add( ' // Detect opened subsequent dropdown' ). lo_buf->add( ' if (activeElement.nodeName === "A"' ). lo_buf->add( ' && activeElement.parentElement' ). lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). lo_buf->add( ' && activeElement.parentElement.classList.contains("force-nav-hover")) {' ). lo_buf->add( ' return this.closeDropdown(activeElement.parentElement);' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Detect opened parent dropdown' ). lo_buf->add( ' if (activeElement.nodeName === "A"' ). lo_buf->add( ' && activeElement.parentElement' ). lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). lo_buf->add( ' && activeElement.parentElement.parentElement' ). lo_buf->add( ' && activeElement.parentElement.parentElement.nodeName === "UL"' ). lo_buf->add( ' && activeElement.parentElement.parentElement.parentElement' ). lo_buf->add( ' && activeElement.parentElement.parentElement.parentElement.nodeName === "LI"' ). lo_buf->add( ' && activeElement.parentElement.parentElement.parentElement.classList.contains("force-nav-hover")) {' ). lo_buf->add( ' return this.closeDropdown(activeElement.parentElement.parentElement.parentElement);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'KeyNavigation.prototype.onArrowDown = function() {' ). lo_buf->add( ' var activeElement = document.activeElement;' ). lo_buf->add( '' ). lo_buf->add( ' // Start of dropdown list: LI > selected A :: UL > LI > A' ). lo_buf->add( ' if (activeElement.nodeName === "A"' ). lo_buf->add( ' && activeElement.parentElement' ). lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). lo_buf->add( ' && activeElement.parentElement.classList.contains("force-nav-hover") // opened dropdown' ). lo_buf->add( ' && activeElement.nextElementSibling' ). lo_buf->add( ' && activeElement.nextElementSibling.nodeName === "UL"' ). lo_buf->add( ' && activeElement.nextElementSibling.firstElementChild' ). lo_buf->add( ' && activeElement.nextElementSibling.firstElementChild.nodeName === "LI") {' ). lo_buf->add( ' return this.focusListItem(activeElement.nextElementSibling.firstElementChild);' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Next item of dropdown list: ( LI > selected A ) :: LI > A' ). lo_buf->add( ' if (activeElement.nodeName === "A"' ). lo_buf->add( ' && activeElement.parentElement' ). lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). lo_buf->add( ' && activeElement.parentElement.nextElementSibling' ). lo_buf->add( ' && activeElement.parentElement.nextElementSibling.nodeName === "LI") {' ). lo_buf->add( ' return this.focusListItem(activeElement.parentElement.nextElementSibling);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'KeyNavigation.prototype.onArrowUp = function() {' ). lo_buf->add( ' var activeElement = document.activeElement;' ). lo_buf->add( '' ). lo_buf->add( ' // Prev item of dropdown list: ( LI > selected A ) <:: LI > A' ). lo_buf->add( ' if (activeElement.nodeName === "A"' ). lo_buf->add( ' && activeElement.parentElement' ). lo_buf->add( ' && activeElement.parentElement.nodeName === "LI"' ). lo_buf->add( ' && activeElement.parentElement.previousElementSibling' ). lo_buf->add( ' && activeElement.parentElement.previousElementSibling.nodeName === "LI") {' ). lo_buf->add( ' return this.focusListItem(activeElement.parentElement.previousElementSibling);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'KeyNavigation.prototype.getHandler = function() {' ). lo_buf->add( ' return this.onkeydown.bind(this);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// this function enables the navigation with arrows through list items (li)' ). lo_buf->add( '// e.g. in dropdown menus' ). lo_buf->add( 'function enableArrowListNavigation() {' ). lo_buf->add( ' document.addEventListener("keydown", new KeyNavigation().getHandler());' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Link Hints (Vimium-like)' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( 'function LinkHints(linkHintHotKey) {' ). lo_buf->add( ' this.linkHintHotKey = linkHintHotKey;' ). lo_buf->add( ' this.areHintsDisplayed = false;' ). lo_buf->add( ' this.pendingPath = ""; // already typed code prefix' ). lo_buf->add( ' this.hintsMap = this.deployHintContainers();' ). lo_buf->add( ' this.activatedDropdown = null;' ). lo_buf->add( ' this.yankModeActive = false;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.getHintStartValue = function(targetsCount) {' ). lo_buf->add( ' // e.g. if we have 89 tooltips we start from 10' ). lo_buf->add( ' // if we have 90 tooltips we start from 100' ). lo_buf->add( ' // if we have 900 tooltips we start from 1000' ). lo_buf->add( ' var' ). lo_buf->add( ' baseLength = Math.pow(10, targetsCount.toString().length - 1),' ). lo_buf->add( ' maxHintStringLength = (targetsCount + baseLength).toString().length;' ). lo_buf->add( ' return Math.pow(10, maxHintStringLength - 1);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.deployHintContainers = function() {' ). lo_buf->add( '' ). lo_buf->add( ' var hintTargets = document.querySelectorAll("a, input, textarea, i");' ). lo_buf->add( ' var codeCounter = this.getHintStartValue(hintTargets.length);' ). lo_buf->add( ' var hintsMap = { first: codeCounter };' ). lo_buf->add( '' ). lo_buf->add( ' // ' ). lo_buf->add( ' // 123' ). lo_buf->add( ' // ' ). lo_buf->add( ' for (var i = 0, N = hintTargets.length; i < N; i++) {' ). lo_buf->add( ' // skip hidden fields' ). lo_buf->add( ' if (hintTargets[i].type === "HIDDEN") {' ). lo_buf->add( ' continue;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' var hint = {};' ). lo_buf->add( '' ). lo_buf->add( ' hint.container = document.createElement("span");' ). lo_buf->add( ' hint.pendingSpan = document.createElement("span");' ). lo_buf->add( ' hint.remainingSpan = document.createElement("span");' ). lo_buf->add( ' hint.parent = hintTargets[i];' ). lo_buf->add( ' hint.code = codeCounter.toString();' ). lo_buf->add( '' ). lo_buf->add( ' hint.container.appendChild(hint.pendingSpan);' ). lo_buf->add( ' hint.container.appendChild(hint.remainingSpan);' ). lo_buf->add( '' ). lo_buf->add( ' hint.pendingSpan.classList.add("pending");' ). lo_buf->add( ' hint.container.classList.add("link-hint");' ). lo_buf->add( ' if (hint.parent.nodeName === "INPUT" || hint.parent.nodeName === "TEXTAREA") {' ). lo_buf->add( ' hint.container.classList.add("link-hint-input");' ). lo_buf->add( ' } else if (hint.parent.nodeName === "A") {' ). lo_buf->add( ' hint.container.classList.add("link-hint-a");' ). lo_buf->add( ' } else if (hint.parent.nodeName === "I" && hint.parent.classList.contains("cursor-pointer")) {' ). lo_buf->add( ' hint.container.classList.add("link-hint-i");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' continue;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' hint.container.classList.add("nodisplay"); // hide by default' ). lo_buf->add( ' hint.container.dataset.code = codeCounter.toString(); // not really needed, more for debug' ). lo_buf->add( '' ). lo_buf->add( ' if (hintTargets[i].nodeName === "INPUT" || hintTargets[i].nodeName === "TEXTAREA") {' ). lo_buf->add( ' // does not work if inside the input node' ). lo_buf->add( ' if (hintTargets[i].type === "checkbox" || hintTargets[i].type === "radio") {' ). lo_buf->add( ' if (hintTargets[i].nextElementSibling && hintTargets[i].nextElementSibling.nodeName === "LABEL") {' ). lo_buf->add( ' // insert at end of label' ). lo_buf->add( ' hintTargets[i].nextElementSibling.appendChild(hint.container);' ). lo_buf->add( ' } else {' ). lo_buf->add( ' // inserting right after' ). lo_buf->add( ' hintTargets[i].insertAdjacentElement("afterend", hint.container);' ). lo_buf->add( ' }' ). lo_buf->add( ' } else {' ). lo_buf->add( ' // inserting right after' ). lo_buf->add( ' hintTargets[i].insertAdjacentElement("afterend", hint.container);' ). lo_buf->add( ' }' ). lo_buf->add( ' } else {' ). lo_buf->add( ' hintTargets[i].appendChild(hint.container);' ). lo_buf->add( ' }' ). lo_buf->add( ' hintsMap[codeCounter++] = hint;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' hintsMap.last = codeCounter - 1;' ). lo_buf->add( ' return hintsMap;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.getHandler = function() {' ). lo_buf->add( ' return this.handleKey.bind(this);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.handleKey = function(event) {' ). lo_buf->add( ' if (event.defaultPrevented) {' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' if (event.key === "y") {' ). lo_buf->add( ' this.yankModeActive = !this.yankModeActive;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' if (event.key === this.linkHintHotKey && Hotkeys.isHotkeyCallPossible()) {' ). lo_buf->add( '' ). lo_buf->add( ' // on user hide hints, close an opened dropdown too' ). lo_buf->add( ' if (this.areHintsDisplayed && this.activatedDropdown) this.closeActivatedDropdown();' ). lo_buf->add( ' if (this.areHintsDisplayed) this.yankModeActive = false;' ). lo_buf->add( '' ). lo_buf->add( ' this.pendingPath = "";' ). lo_buf->add( ' this.displayHints(!this.areHintsDisplayed);' ). lo_buf->add( '' ). lo_buf->add( ' } else if (this.areHintsDisplayed) {' ). lo_buf->add( '' ). lo_buf->add( ' // the user tries to reach a hint' ). lo_buf->add( ' this.pendingPath += event.key;' ). lo_buf->add( '' ). lo_buf->add( ' var hint = this.hintsMap[this.pendingPath];' ). lo_buf->add( '' ). lo_buf->add( ' if (hint) { // we are there, we have a fully specified tooltip. Let us activate or yank it' ). lo_buf->add( ' this.displayHints(false);' ). lo_buf->add( ' event.preventDefault();' ). lo_buf->add( ' if (this.yankModeActive) {' ). lo_buf->add( ' submitSapeventForm({ clipboard: hint.parent.firstChild.textContent }, "yank_to_clipboard");' ). lo_buf->add( ' this.yankModeActive = false;' ). lo_buf->add( ' } else {' ). lo_buf->add( ' this.hintActivate(hint);' ). lo_buf->add( ' }' ). lo_buf->add( ' } else {' ). lo_buf->add( ' // we are not there yet, but let us filter the link so that only' ). lo_buf->add( ' // the partially matched are shown' ). lo_buf->add( ' var visibleHints = this.filterHints();' ). lo_buf->add( ' if (!visibleHints) {' ). lo_buf->add( ' this.displayHints(false);' ). lo_buf->add( ' if (this.activatedDropdown) this.closeActivatedDropdown();' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.closeActivatedDropdown = function() {' ). lo_buf->add( ' if (!this.activatedDropdown) return;' ). lo_buf->add( ' this.activatedDropdown.classList.remove("force-nav-hover");' ). lo_buf->add( ' this.activatedDropdown = null;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.displayHints = function(isActivate) {' ). lo_buf->add( ' this.areHintsDisplayed = isActivate;' ). lo_buf->add( ' for (var i = this.hintsMap.first; i <= this.hintsMap.last; i++) {' ). lo_buf->add( ' var hint = this.hintsMap[i];' ). lo_buf->add( ' if (isActivate) {' ). lo_buf->add( ' hint.container.classList.remove("nodisplay");' ). lo_buf->add( ' hint.pendingSpan.innerText = "";' ). lo_buf->add( ' hint.remainingSpan.innerText = hint.code;' ). lo_buf->add( ' } else {' ). lo_buf->add( ' hint.container.classList.add("nodisplay");' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.hintActivate = function(hint) {' ). lo_buf->add( ' if (hint.parent.nodeName === "A"' ). lo_buf->add( ' // hint.parent.href doesn`t have a # at the end while accessing dropdowns the first time.' ). lo_buf->add( ' // Seems like a idiosyncrasy of SAP GUI`s IE. So let`s ignore the last character.' ). lo_buf->add( ' && (hint.parent.href.substr(0, hint.parent.href.length - 1) === document.location.href)// href is #' ). lo_buf->add( ' && !hint.parent.onclick // no handler' ). lo_buf->add( ' && hint.parent.parentElement && hint.parent.parentElement.nodeName === "LI") {' ). lo_buf->add( ' // probably it is a dropdown ...' ). lo_buf->add( ' this.activatedDropdown = hint.parent.parentElement;' ). lo_buf->add( ' this.activatedDropdown.classList.toggle("force-nav-hover");' ). lo_buf->add( ' hint.parent.focus();' ). lo_buf->add( ' } else if (hint.parent.type === "checkbox") {' ). lo_buf->add( ' this.toggleCheckbox(hint);' ). lo_buf->add( ' } else if (hint.parent.type === "radio") {' ). lo_buf->add( ' this.toggleRadioButton(hint);' ). lo_buf->add( ' } else if (hint.parent.type === "submit") {' ). lo_buf->add( ' hint.parent.click();' ). lo_buf->add( ' } else if (hint.parent.nodeName === "INPUT" || hint.parent.nodeName === "TEXTAREA") {' ). lo_buf->add( ' hint.parent.focus();' ). lo_buf->add( ' } else {' ). lo_buf->add( ' hint.parent.click();' ). lo_buf->add( ' if (this.activatedDropdown) this.closeActivatedDropdown();' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.toggleCheckbox = function(hint) {' ). lo_buf->add( ' var checked = hint.parent.checked;' ). lo_buf->add( ' this.triggerClickHandler(hint.parent.parentElement);' ). lo_buf->add( ' if (checked === hint.parent.checked) {' ). lo_buf->add( ' // fallback if no handler is registered' ). lo_buf->add( ' hint.parent.checked = !hint.parent.checked;' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.toggleRadioButton = function(hint) {' ). lo_buf->add( ' this.triggerClickHandler(hint.parent);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.triggerClickHandler = function(el) {' ). lo_buf->add( ' // ensures that onclick handler is executed' ). lo_buf->add( ' // https://stackoverflow.com/questions/41981509/trigger-an-event-when-a-checkbox-is-changed-programmatically-via-javascript' ). lo_buf->add( ' var event = document.createEvent("HTMLEvents");' ). lo_buf->add( ' event.initEvent("click", false, true);' ). lo_buf->add( ' el.dispatchEvent(event);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'LinkHints.prototype.filterHints = function() {' ). lo_buf->add( ' var visibleHints = 0;' ). lo_buf->add( ' for (var i = this.hintsMap.first; i <= this.hintsMap.last; i++) {' ). lo_buf->add( ' var hint = this.hintsMap[i];' ). lo_buf->add( ' if (i.toString().startsWith(this.pendingPath)) {' ). lo_buf->add( ' hint.pendingSpan.innerText = this.pendingPath;' ). lo_buf->add( ' hint.remainingSpan.innerText = hint.code.substring(this.pendingPath.length);' ). lo_buf->add( ' // hint.container.classList.remove("nodisplay"); // for backspace' ). lo_buf->add( ' visibleHints++;' ). lo_buf->add( ' } else {' ). lo_buf->add( ' hint.container.classList.add("nodisplay");' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' return visibleHints;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'function activateLinkHints(linkHintHotKey) {' ). lo_buf->add( ' if (!linkHintHotKey) return;' ). lo_buf->add( ' var oLinkHint = new LinkHints(linkHintHotKey);' ). lo_buf->add( ' document.addEventListener("keypress", oLinkHint.getHandler());' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Hotkeys' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( 'function Hotkeys(oKeyMap) {' ). lo_buf->add( ' this.oKeyMap = oKeyMap || {};' ). lo_buf->add( '' ). lo_buf->add( ' // these are the hotkeys provided by the backend' ). lo_buf->add( ' Object.keys(this.oKeyMap).forEach(function(sKey) {' ). lo_buf->add( '' ). lo_buf->add( ' var action = this.oKeyMap[sKey];' ). lo_buf->add( '' ). lo_buf->add( ' // add a tooltip/title with the hotkey, currently only sapevents are supported' ). lo_buf->add( ' this.getAllSapEventsForSapEventName(action).forEach(function(elAnchor) {' ). lo_buf->add( ' elAnchor.title = elAnchor.title + " [" + sKey + "]";' ). lo_buf->add( ' });' ). lo_buf->add( '' ). lo_buf->add( ' // We replace the actions with callback functions to unify' ). lo_buf->add( ' // the hotkey execution' ). lo_buf->add( ' this.oKeyMap[sKey] = function(oEvent) {' ). lo_buf->add( '' ). lo_buf->add( ' // gHelper is only valid for diff page' ). lo_buf->add( ' var diffHelper = (window.gHelper || {});' ). lo_buf->add( '' ). lo_buf->add( ' // We have either a js function on this' ). lo_buf->add( ' if (this[action]) {' ). lo_buf->add( ' this[action].call(this);' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Or a method of the helper object for the diff page' ). lo_buf->add( ' if (diffHelper[action]) {' ). lo_buf->add( ' diffHelper[action].call(diffHelper);' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Or a global function' ). lo_buf->add( ' if (window[action] && typeof (window[action]) === "function") {' ). lo_buf->add( ' window[action].call(this);' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Or a SAP event link' ). lo_buf->add( ' var sUiSapEventHref = this.getSapEventHref(action);' ). lo_buf->add( ' if (sUiSapEventHref) {' ). lo_buf->add( ' submitSapeventForm({}, sUiSapEventHref, "post");' ). lo_buf->add( ' oEvent.preventDefault();' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Or an SAP event input' ). lo_buf->add( ' var sUiSapEventInputAction = this.getSapEventInputAction(action);' ). lo_buf->add( ' if (sUiSapEventInputAction) {' ). lo_buf->add( ' submitSapeventForm({}, sUiSapEventInputAction, "post");' ). lo_buf->add( ' oEvent.preventDefault();' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // Or an SAP event main form' ). lo_buf->add( ' var elForm = this.getSapEventForm(action);' ). lo_buf->add( ' if (elForm) {' ). lo_buf->add( ' elForm.submit();' ). lo_buf->add( ' oEvent.preventDefault();' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' };' ). lo_buf->add( '' ). lo_buf->add( ' }.bind(this));' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'Hotkeys.prototype.showHotkeys = function() {' ). lo_buf->add( ' var elHotkeys = document.querySelector("#hotkeys");' ). lo_buf->add( '' ). lo_buf->add( ' if (elHotkeys) {' ). lo_buf->add( ' elHotkeys.style.display = (elHotkeys.style.display) ? "" : "none";' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Hotkeys.prototype.getAllSapEventsForSapEventName = function (sSapEvent) {' ). lo_buf->add( ' if (/^#+$/.test(sSapEvent)){' ). lo_buf->add( ' // sSapEvent contains only #. Nothing sensible can be done here' ). lo_buf->add( ' return [];' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' var includesSapEvent = function(text){' ). lo_buf->add( ' return (text.includes("sapevent") || text.includes("SAPEVENT"));' ). lo_buf->add( ' };' ). lo_buf->add( '' ). lo_buf->add( ' return [].slice' ). lo_buf->add( ' .call(document.querySelectorAll("a[href*="+ sSapEvent +"], input[formaction*="+ sSapEvent+"]"))' ). lo_buf->add( ' .filter(function (elem) {' ). lo_buf->add( ' return (elem.nodeName === "A" && includesSapEvent(elem.href)' ). lo_buf->add( ' || (elem.nodeName === "INPUT" && includesSapEvent(elem.formAction)));' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Hotkeys.prototype.getSapEventHref = function(sSapEvent) {' ). lo_buf->add( ' return this.getAllSapEventsForSapEventName(sSapEvent)' ). lo_buf->add( ' .filter(function(el) {' ). lo_buf->add( ' // only anchors' ). lo_buf->add( ' return (!!el.href);' ). lo_buf->add( ' })' ). lo_buf->add( ' .map(function(oSapEvent) {' ). lo_buf->add( ' return oSapEvent.href;' ). lo_buf->add( ' })' ). lo_buf->add( ' .filter(this.eliminateSapEventFalsePositives(sSapEvent))' ). lo_buf->add( ' .pop();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Hotkeys.prototype.getSapEventInputAction = function(sSapEvent) {' ). lo_buf->add( ' return this.getAllSapEventsForSapEventName(sSapEvent)' ). lo_buf->add( ' .filter(function(el) {' ). lo_buf->add( ' // input forms' ). lo_buf->add( ' return (el.type === "submit");' ). lo_buf->add( ' })' ). lo_buf->add( ' .map(function(oSapEvent) {' ). lo_buf->add( ' return oSapEvent.formAction;' ). lo_buf->add( ' })' ). lo_buf->add( ' .filter(this.eliminateSapEventFalsePositives(sSapEvent))' ). lo_buf->add( ' .pop();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Hotkeys.prototype.getSapEventForm = function(sSapEvent) {' ). lo_buf->add( ' return this.getAllSapEventsForSapEventName(sSapEvent)' ). lo_buf->add( ' .filter(function(el) {' ). lo_buf->add( ' // forms' ). lo_buf->add( ' var parentForm = el.parentNode.parentNode.parentNode;' ). lo_buf->add( ' return (el.type === "submit" && parentForm.nodeName === "FORM");' ). lo_buf->add( ' })' ). lo_buf->add( ' .map(function(oSapEvent) {' ). lo_buf->add( ' return oSapEvent.parentNode.parentNode.parentNode;' ). lo_buf->add( ' })' ). lo_buf->add( ' .pop();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Hotkeys.prototype.eliminateSapEventFalsePositives = function(sapEvent) {' ). lo_buf->add( ' return function(sapEventAttr) {' ). lo_buf->add( ' return sapEventAttr.match(new RegExp("\\b" + sapEvent + "\\b"));' ). lo_buf->add( ' };' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Hotkeys.prototype.onkeydown = function(oEvent) {' ). lo_buf->add( ' if (oEvent.defaultPrevented) {' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' if (!Hotkeys.isHotkeyCallPossible()) {' ). lo_buf->add( ' return;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' var' ). lo_buf->add( ' sKey = oEvent.key || String.fromCharCode(oEvent.keyCode),' ). lo_buf->add( ' fnHotkey = this.oKeyMap[sKey];' ). lo_buf->add( '' ). lo_buf->add( ' if (fnHotkey) {' ). lo_buf->add( ' fnHotkey.call(this, oEvent);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Hotkeys.isHotkeyCallPossible = function() {' ). lo_buf->add( ' var activeElementType = ((document.activeElement && document.activeElement.nodeName) || "");' ). lo_buf->add( ' var activeElementReadOnly = ((document.activeElement && document.activeElement.readOnly) || false);' ). lo_buf->add( '' ). lo_buf->add( ' return (activeElementReadOnly || (activeElementType !== "INPUT" && activeElementType !== "TEXTAREA"));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Hotkeys.addHotkeyToHelpSheet = function(key, description) {' ). lo_buf->add( ' var hotkeysUl = document.querySelector("#hotkeys ul.hotkeys");' ). lo_buf->add( ' if (!hotkeysUl) return;' ). lo_buf->add( '' ). lo_buf->add( ' var li = document.createElement("li");' ). lo_buf->add( ' var spanId = document.createElement("span");' ). lo_buf->add( ' var spanDescr = document.createElement("span");' ). lo_buf->add( '' ). lo_buf->add( ' spanId.className = "key-id";' ). lo_buf->add( ' spanId.innerText = key;' ). lo_buf->add( ' spanDescr.className = "key-descr";' ). lo_buf->add( ' spanDescr.innerText = description;' ). lo_buf->add( ' li.appendChild(spanId);' ). lo_buf->add( ' li.appendChild(spanDescr);' ). lo_buf->add( '' ). lo_buf->add( ' hotkeysUl.appendChild(li);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'function setKeyBindings(oKeyMap) {' ). lo_buf->add( ' var oHotkeys = new Hotkeys(oKeyMap);' ). lo_buf->add( '' ). lo_buf->add( ' document.addEventListener("keypress", oHotkeys.onkeydown.bind(oHotkeys));' ). lo_buf->add( ' setTimeout(function() {' ). lo_buf->add( ' var div = document.getElementById("hotkeys-hint");' ). lo_buf->add( ' if (div) div.style.opacity = 0.2;' ). lo_buf->add( ' }, 4900);' ). lo_buf->add( ' setTimeout(function() { toggleDisplay("hotkeys-hint") }, 5000);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Patch Logic (git add -p)' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '/*' ). lo_buf->add( ' We have three type of cascading checkboxes.' ). lo_buf->add( ' Which means that by clicking a file or section checkbox all corresponding line checkboxes are checked.' ). lo_buf->add( '' ). lo_buf->add( ' The id of the checkbox indicates its semantics and its membership.' ). lo_buf->add( '*/' ). lo_buf->add( '' ). lo_buf->add( '/*' ). lo_buf->add( ' 1) file links' ). lo_buf->add( '' ). lo_buf->add( ' example id of file link' ). lo_buf->add( '' ). lo_buf->add( ' patch_file_zcl_abapgit_user_exit.clas.abap' ). lo_buf->add( ' \________/ \_____________________________/' ). lo_buf->add( ' | |' ). lo_buf->add( ' | |____ file name' ). lo_buf->add( ' |' ). lo_buf->add( ' |' ). lo_buf->add( ' |' ). lo_buf->add( ' constant prefix' ). lo_buf->add( '*/' ). lo_buf->add( '' ). lo_buf->add( 'function PatchFile(sId) {' ). lo_buf->add( ' var oRegex = new RegExp("(" + this.ID + ")_(.*$)");' ). lo_buf->add( ' var oMatch = sId.match(oRegex);' ). lo_buf->add( '' ). lo_buf->add( ' this.id = sId;' ). lo_buf->add( ' this.prefix = oMatch[1];' ). lo_buf->add( ' this.file_name = oMatch[2];' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'PatchFile.prototype.ID = "patch_file";' ). lo_buf->add( '' ). lo_buf->add( '/*' ). lo_buf->add( ' 2) section links within a file' ). lo_buf->add( '' ). lo_buf->add( ' example id of section link' ). lo_buf->add( '' ). lo_buf->add( ' patch_section_zcl_abapgit_user_exit.clas.abap_1' ). lo_buf->add( ' \___________/ \_____________________________/ ^' ). lo_buf->add( ' | | |' ). lo_buf->add( ' | file name |' ). lo_buf->add( ' | |' ). lo_buf->add( ' | ------ section' ). lo_buf->add( ' |' ). lo_buf->add( ' constant prefix' ). lo_buf->add( '*/' ). lo_buf->add( '' ). lo_buf->add( 'function PatchSection(sId) {' ). lo_buf->add( ' var oRegex = new RegExp("(" + this.ID + ")_(.*)_(\\d+$)");' ). lo_buf->add( ' var oMatch = sId.match(oRegex);' ). lo_buf->add( '' ). lo_buf->add( ' this.id = sId;' ). lo_buf->add( ' this.prefix = oMatch[1];' ). lo_buf->add( ' this.file_name = oMatch[2];' ). lo_buf->add( ' this.section = oMatch[3];' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'PatchSection.prototype.ID = "patch_section";' ). lo_buf->add( '' ). lo_buf->add( '/*' ). lo_buf->add( ' 3) line links within a section' ). lo_buf->add( '' ). lo_buf->add( ' example id of line link' ). lo_buf->add( '' ). lo_buf->add( ' patch_line_zcl_abapgit_user_exit.clas.abap_1_25' ). lo_buf->add( ' \________/ \_____________________________/ ^ ^' ). lo_buf->add( ' ^ ^ | |' ). lo_buf->add( ' | | | ------- line number' ). lo_buf->add( ' | file name |' ). lo_buf->add( ' | section' ). lo_buf->add( ' |' ). lo_buf->add( ' |' ). lo_buf->add( ' constant prefix' ). lo_buf->add( '*/' ). lo_buf->add( '' ). lo_buf->add( 'function PatchLine() { }' ). lo_buf->add( '' ). lo_buf->add( 'PatchLine.prototype.ID = "patch_line";' ). lo_buf->add( '' ). lo_buf->add( 'function Patch() { }' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.ID = {' ). lo_buf->add( ' STAGE: "stage"' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.ACTION = {' ). lo_buf->add( ' PATCH_STAGE : "patch_stage",' ). lo_buf->add( ' REFRESH_LOCAL: "refresh_local",' ). lo_buf->add( ' REFRESH_ALL : "refresh_all"' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.escape = function(sFileName) {' ). lo_buf->add( ' return sFileName' ). lo_buf->add( ' .replace(/\./g, "\\.")' ). lo_buf->add( ' .replace(/#/g, "\\#");' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.preparePatch = function() {' ). lo_buf->add( ' this.registerClickHandlerForFiles();' ). lo_buf->add( ' this.registerClickHandlerForSections();' ). lo_buf->add( ' this.registerClickHandlerForLines();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.buildSelectorInputStartsWithId = function(sId) {' ). lo_buf->add( ' return "input[id^=''" + sId + "'']";' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.registerClickHandlerForFiles = function() {' ). lo_buf->add( ' this.registerClickHandlerForSelectorParent(this.buildSelectorInputStartsWithId(PatchFile.prototype.ID), this.onClickFileCheckbox);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.registerClickHandlerForSections = function() {' ). lo_buf->add( ' this.registerClickHandlerForSelectorParent(this.buildSelectorInputStartsWithId(PatchSection.prototype.ID), this.onClickSectionCheckbox);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.registerClickHandlerForLines = function() {' ). lo_buf->add( ' this.registerClickHandlerForSelectorParent(this.buildSelectorInputStartsWithId(PatchLine.prototype.ID), this.onClickLineCheckbox);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.registerClickHandlerForSelectorParent = function(sSelector, fnCallback) {' ). lo_buf->add( ' var elAll = document.querySelectorAll(sSelector);' ). lo_buf->add( '' ). lo_buf->add( ' [].forEach.call(elAll, function(elem) {' ). lo_buf->add( ' elem.parentElement.addEventListener("click", fnCallback.bind(this));' ). lo_buf->add( ' }.bind(this));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.getAllLineCheckboxesForFile = function(oFile) {' ). lo_buf->add( ' return this.getAllLineCheckboxesForId(oFile.id, PatchFile.prototype.ID);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.getAllSectionCheckboxesForFile = function(oFile) {' ). lo_buf->add( ' return this.getAllSectionCheckboxesForId(oFile.id, PatchFile.prototype.ID);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.getAllLineCheckboxesForSection = function(oSection) {' ). lo_buf->add( ' return this.getAllLineCheckboxesForId(oSection.id, PatchSection.prototype.ID);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.getAllLineCheckboxesForId = function(sId, sIdPrefix) {' ). lo_buf->add( ' return this.getAllCheckboxesForId(sId, sIdPrefix, PatchLine.prototype.ID);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.getAllSectionCheckboxesForId = function(sId, sIdPrefix) {' ). lo_buf->add( ' return this.getAllCheckboxesForId(sId, sIdPrefix, PatchSection.prototype.ID);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.getAllCheckboxesForId = function(sId, sIdPrefix, sNewIdPrefix) {' ). lo_buf->add( ' var oRegex = new RegExp("^" + sIdPrefix);' ). lo_buf->add( '' ). lo_buf->add( ' sId = sId.replace(oRegex, sNewIdPrefix);' ). lo_buf->add( ' return document.querySelectorAll(this.buildSelectorInputStartsWithId(this.escape(sId)));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.getToggledCheckbox = function(oEvent) {' ). lo_buf->add( ' var elCheckbox = null;' ). lo_buf->add( '' ). lo_buf->add( ' // We have either an input element or any element with input child' ). lo_buf->add( ' // in the latter case we have to toggle the checkbox manually' ). lo_buf->add( ' if (oEvent.srcElement.nodeName === "INPUT") {' ). lo_buf->add( ' elCheckbox = oEvent.srcElement;' ). lo_buf->add( ' } else {' ). lo_buf->add( ' elCheckbox = this.toggleCheckbox(oEvent.srcElement.querySelector("INPUT"));' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' return elCheckbox;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.toggleCheckbox = function(elCheckbox) {' ). lo_buf->add( ' elCheckbox.checked = !elCheckbox.checked;' ). lo_buf->add( ' return elCheckbox;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.onClickFileCheckbox = function(oEvent) {' ). lo_buf->add( ' var elCheckbox = this.getToggledCheckbox(oEvent);' ). lo_buf->add( ' var oFile = new PatchFile(elCheckbox.id);' ). lo_buf->add( ' var elAllLineCheckboxesOfFile = this.getAllLineCheckboxesForFile(oFile);' ). lo_buf->add( ' var elAllSectionCheckboxesOfFile = this.getAllSectionCheckboxesForFile(oFile);' ). lo_buf->add( '' ). lo_buf->add( ' [].forEach.call(elAllLineCheckboxesOfFile, function(elem) {' ). lo_buf->add( ' elem.checked = elCheckbox.checked;' ). lo_buf->add( ' }.bind(this));' ). lo_buf->add( '' ). lo_buf->add( ' [].forEach.call(elAllSectionCheckboxesOfFile, function(elem) {' ). lo_buf->add( ' elem.checked = elCheckbox.checked;' ). lo_buf->add( ' }.bind(this));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.onClickSectionCheckbox = function(oEvent) {' ). lo_buf->add( ' var elSrcElement = this.getToggledCheckbox(oEvent);' ). lo_buf->add( ' var oSection = new PatchSection(elSrcElement.id);' ). lo_buf->add( ' this.clickAllLineCheckboxesInSection(oSection, elSrcElement.checked);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.onClickLineCheckbox = function(oEvent) {' ). lo_buf->add( ' this.getToggledCheckbox(oEvent);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.clickAllLineCheckboxesInSection = function(oSection, bChecked) {' ). lo_buf->add( ' var elAllLineCheckboxesOfSection = this.getAllLineCheckboxesForSection(oSection);' ). lo_buf->add( '' ). lo_buf->add( ' [].forEach.call(elAllLineCheckboxesOfSection, function(elem) {' ). lo_buf->add( ' elem.checked = bChecked;' ). lo_buf->add( ' }.bind(this));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.registerStagePatch = function() {' ). lo_buf->add( ' var elStage = document.querySelector("#" + this.ID.STAGE);' ). lo_buf->add( ' var REFRESH_PREFIX = "refresh";' ). lo_buf->add( '' ). lo_buf->add( ' elStage.addEventListener("click", this.submitPatch.bind(this, this.ACTION.PATCH_STAGE));' ). lo_buf->add( '' ). lo_buf->add( ' var aRefresh = document.querySelectorAll("[id*=" + REFRESH_PREFIX + "]");' ). lo_buf->add( ' [].forEach.call(aRefresh, function(el) {' ). lo_buf->add( ' el.addEventListener("click", memorizeScrollPosition(this.submitPatch.bind(this, el.id)).bind(this));' ). lo_buf->add( ' }.bind(this));' ). lo_buf->add( '' ). lo_buf->add( ' // for hotkeys' ). lo_buf->add( ' window.stagePatch = function() {' ). lo_buf->add( ' this.submitPatch(this.ACTION.PATCH_STAGE);' ). lo_buf->add( ' }.bind(this);' ). lo_buf->add( '' ). lo_buf->add( ' window.refreshLocal = memorizeScrollPosition(function() {' ). lo_buf->add( ' this.submitPatch(this.ACTION.REFRESH_LOCAL);' ). lo_buf->add( ' }.bind(this));' ). lo_buf->add( '' ). lo_buf->add( ' window.refreshAll = memorizeScrollPosition(function() {' ). lo_buf->add( ' this.submitPatch(this.ACTION.REFRESH_ALL);' ). lo_buf->add( ' }.bind(this));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.submitPatch = function(action) {' ). lo_buf->add( ' // Collect add and remove info and submit to backend' ). lo_buf->add( ' var aAddPatch = this.collectElementsForCheckboxId(PatchLine.prototype.ID, true);' ). lo_buf->add( ' var aRemovePatch = this.collectElementsForCheckboxId(PatchLine.prototype.ID, false);' ). lo_buf->add( '' ). lo_buf->add( ' submitSapeventForm({ add: aAddPatch, remove: aRemovePatch }, action, "post");' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'Patch.prototype.collectElementsForCheckboxId = function(sId, bChecked) {' ). lo_buf->add( ' var sSelector = this.buildSelectorInputStartsWithId(sId);' ). lo_buf->add( '' ). lo_buf->add( ' return [].slice.call(document.querySelectorAll(sSelector))' ). lo_buf->add( ' .filter(function(elem) {' ). lo_buf->add( ' return (elem.checked === bChecked);' ). lo_buf->add( ' }).map(function(elem) {' ). lo_buf->add( ' return elem.id;' ). lo_buf->add( ' });' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'function preparePatch() {' ). lo_buf->add( ' var oPatch = new Patch();' ). lo_buf->add( ' oPatch.preparePatch();' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function registerStagePatch() {' ). lo_buf->add( ' var oPatch = new Patch();' ). lo_buf->add( ' oPatch.registerStagePatch();' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Command Palette (F1)' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '// fuzzy match helper' ). lo_buf->add( '// return non empty marked string in case it fits the filter' ). lo_buf->add( '// abc + b = abc' ). lo_buf->add( 'function fuzzyMatchAndMark(str, filter) {' ). lo_buf->add( ' var markedStr = "";' ). lo_buf->add( ' var filterLower = filter.toLowerCase();' ). lo_buf->add( ' var strLower = str.toLowerCase();' ). lo_buf->add( ' var cur = 0;' ). lo_buf->add( '' ). lo_buf->add( ' for (var i = 0; i < filter.length; i++) {' ). lo_buf->add( ' while (filterLower[i] !== strLower[cur] && cur < str.length) {' ). lo_buf->add( ' markedStr += str[cur++];' ). lo_buf->add( ' }' ). lo_buf->add( ' if (cur === str.length) break;' ). lo_buf->add( ' markedStr += "" + str[cur++] + "";' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' var matched = i === filter.length;' ). lo_buf->add( '' ). lo_buf->add( ' if (matched && cur < str.length) markedStr += str.substring(cur);' ). lo_buf->add( ' return matched ? markedStr: null;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function CommandPalette(commandEnumerator, opts) {' ). lo_buf->add( ' if (typeof commandEnumerator !== "function") throw Error("commandEnumerator must be a function");' ). lo_buf->add( ' if (typeof opts !== "object") throw Error("opts must be an object");' ). lo_buf->add( ' if (typeof opts.toggleKey !== "string" || !opts.toggleKey) throw Error("toggleKey must be a string");' ). lo_buf->add( ' this.commands = commandEnumerator();' ). lo_buf->add( ' if (!this.commands) return;' ). lo_buf->add( ' // this.commands = [{' ). lo_buf->add( ' // action: "sap_event_action_code_with_params"' ). lo_buf->add( ' // iconClass: "icon icon_x ..."' ). lo_buf->add( ' // title: "my command X"' ). lo_buf->add( ' // }, ...];' ). lo_buf->add( '' ). lo_buf->add( ' if (opts.toggleKey[0] === "^") {' ). lo_buf->add( ' this.toggleKeyCtrl = true;' ). lo_buf->add( ' this.toggleKey = opts.toggleKey.substring(1);' ). lo_buf->add( ' if (!this.toggleKey) throw Error("Incorrect toggleKey");' ). lo_buf->add( ' } else {' ). lo_buf->add( ' this.toggleKeyCtrl = false;' ). lo_buf->add( ' this.toggleKey = opts.toggleKey;' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' this.hotkeyDescription = opts.hotkeyDescription;' ). lo_buf->add( ' this.elements = {' ). lo_buf->add( ' palette: null,' ). lo_buf->add( ' ul : null,' ). lo_buf->add( ' input : null' ). lo_buf->add( ' };' ). lo_buf->add( ' this.selectIndex = -1; // not selected' ). lo_buf->add( ' this.filter = "";' ). lo_buf->add( ' this.renderAndBindElements();' ). lo_buf->add( ' this.hookEvents();' ). lo_buf->add( ' Hotkeys.addHotkeyToHelpSheet(opts.toggleKey, opts.hotkeyDescription);' ). lo_buf->add( '' ). lo_buf->add( ' if (!CommandPalette.instances) {' ). lo_buf->add( ' CommandPalette.instances = [];' ). lo_buf->add( ' }' ). lo_buf->add( ' CommandPalette.instances.push(this);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.hookEvents = function() {' ). lo_buf->add( ' document.addEventListener("keydown", this.handleToggleKey.bind(this));' ). lo_buf->add( ' this.elements.input.addEventListener("keyup", this.handleInputKey.bind(this));' ). lo_buf->add( ' this.elements.ul.addEventListener("click", this.handleUlClick.bind(this));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.renderCommandItem = function(cmd) {' ). lo_buf->add( ' var li = document.createElement("li");' ). lo_buf->add( ' if (cmd.iconClass) {' ). lo_buf->add( ' var icon = document.createElement("i");' ). lo_buf->add( '' ). lo_buf->add( ' icon.className = cmd.iconClass;' ). lo_buf->add( ' li.appendChild(icon);' ). lo_buf->add( ' }' ). lo_buf->add( ' var titleSpan = document.createElement("span");' ). lo_buf->add( ' li.appendChild(titleSpan);' ). lo_buf->add( ' cmd.element = li;' ). lo_buf->add( ' cmd.titleSpan = titleSpan;' ). lo_buf->add( ' return li;' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.renderAndBindElements = function() {' ). lo_buf->add( ' var div = document.createElement("div");' ). lo_buf->add( ' var input = document.createElement("input");' ). lo_buf->add( ' var ul = document.createElement("ul");' ). lo_buf->add( '' ). lo_buf->add( ' div.className = "cmd-palette";' ). lo_buf->add( ' div.style.display = "none";' ). lo_buf->add( ' input.placeholder = this.hotkeyDescription;' ). lo_buf->add( ' for (var i = 0; i < this.commands.length; i++) ul.appendChild(this.renderCommandItem(this.commands[i]));' ). lo_buf->add( ' div.appendChild(input);' ). lo_buf->add( ' div.appendChild(ul);' ). lo_buf->add( '' ). lo_buf->add( ' this.elements.palette = div;' ). lo_buf->add( ' this.elements.input = input;' ). lo_buf->add( ' this.elements.ul = ul;' ). lo_buf->add( ' document.body.appendChild(div);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.handleToggleKey = function(event) {' ). lo_buf->add( ' if (event.key !== this.toggleKey) return;' ). lo_buf->add( ' if (this.toggleKeyCtrl && !event.ctrlKey) return;' ). lo_buf->add( ' this.toggleDisplay();' ). lo_buf->add( ' event.preventDefault();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.handleInputKey = function(event) {' ). lo_buf->add( ' if (event.key === "ArrowUp" || event.key === "Up") {' ). lo_buf->add( ' this.selectPrev();' ). lo_buf->add( ' } else if (event.key === "ArrowDown" || event.key === "Down") {' ). lo_buf->add( ' this.selectNext();' ). lo_buf->add( ' } else if (event.key === "Enter") {' ). lo_buf->add( ' this.exec(this.getSelected());' ). lo_buf->add( ' } else if (event.key === "Backspace" && !this.filter) {' ). lo_buf->add( ' this.toggleDisplay(false);' ). lo_buf->add( ' } else if (this.filter !== this.elements.input.value) {' ). lo_buf->add( ' this.filter = this.elements.input.value;' ). lo_buf->add( ' this.applyFilter();' ). lo_buf->add( ' this.selectFirst();' ). lo_buf->add( ' }' ). lo_buf->add( ' event.preventDefault();' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.applyFilter = function() {' ). lo_buf->add( ' for (var i = 0; i < this.commands.length; i++) {' ). lo_buf->add( ' var cmd = this.commands[i];' ). lo_buf->add( ' if (!this.filter) {' ). lo_buf->add( ' cmd.element.style.display = "";' ). lo_buf->add( ' cmd.titleSpan.innerText = cmd.title;' ). lo_buf->add( ' } else {' ). lo_buf->add( ' var matchedTitle = fuzzyMatchAndMark(cmd.title, this.filter);' ). lo_buf->add( ' if (matchedTitle) {' ). lo_buf->add( ' cmd.titleSpan.innerHTML = matchedTitle;' ). lo_buf->add( ' cmd.element.style.display = "";' ). lo_buf->add( ' } else {' ). lo_buf->add( ' cmd.element.style.display = "none";' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.applySelectIndex = function(newIndex) {' ). lo_buf->add( ' if (newIndex !== this.selectIndex) {' ). lo_buf->add( ' if (this.selectIndex >= 0) this.commands[this.selectIndex].element.classList.remove("selected");' ). lo_buf->add( ' var newCmd = this.commands[newIndex];' ). lo_buf->add( ' newCmd.element.classList.add("selected");' ). lo_buf->add( ' this.selectIndex = newIndex;' ). lo_buf->add( ' this.adjustScrollPosition(newCmd.element);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.selectFirst = function() {' ). lo_buf->add( ' for (var i = 0; i < this.commands.length; i++) {' ). lo_buf->add( ' if (this.commands[i].element.style.display === "none") continue; // skip hidden' ). lo_buf->add( ' this.applySelectIndex(i);' ). lo_buf->add( ' break;' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.selectNext = function() {' ). lo_buf->add( ' for (var i = this.selectIndex + 1; i < this.commands.length; i++) {' ). lo_buf->add( ' if (this.commands[i].element.style.display === "none") continue; // skip hidden' ). lo_buf->add( ' this.applySelectIndex(i);' ). lo_buf->add( ' break;' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.selectPrev = function() {' ). lo_buf->add( ' for (var i = this.selectIndex - 1; i >= 0; i--) {' ). lo_buf->add( ' if (this.commands[i].element.style.display === "none") continue; // skip hidden' ). lo_buf->add( ' this.applySelectIndex(i);' ). lo_buf->add( ' break;' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.getSelected = function() {' ). lo_buf->add( ' return this.commands[this.selectIndex];' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.adjustScrollPosition = function(itemElement) {' ). lo_buf->add( ' var bItem = itemElement.getBoundingClientRect();' ). lo_buf->add( ' var bContainer = this.elements.ul.getBoundingClientRect();' ). lo_buf->add( '' ). lo_buf->add( ' bItem.top = Math.round(bItem.top);' ). lo_buf->add( ' bItem.bottom = Math.round(bItem.bottom);' ). lo_buf->add( ' bItem.height = Math.round(bItem.height);' ). lo_buf->add( ' bItem.mid = Math.round(bItem.top + bItem.height / 2);' ). lo_buf->add( ' bContainer.top = Math.round(bContainer.top);' ). lo_buf->add( ' bContainer.bottom = Math.round(bContainer.bottom);' ). lo_buf->add( '' ). lo_buf->add( ' if (bItem.mid > bContainer.bottom - 2) {' ). lo_buf->add( ' this.elements.ul.scrollTop += bItem.bottom - bContainer.bottom;' ). lo_buf->add( ' } else if (bItem.mid < bContainer.top + 2) {' ). lo_buf->add( ' this.elements.ul.scrollTop += bItem.top - bContainer.top;' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.toggleDisplay = function(forceState) {' ). lo_buf->add( ' var isDisplayed = (this.elements.palette.style.display !== "none");' ). lo_buf->add( ' var tobeDisplayed = (forceState !== undefined) ? forceState : !isDisplayed;' ). lo_buf->add( '' ). lo_buf->add( ' if (tobeDisplayed) {' ). lo_buf->add( ' // auto close other command palettes' ). lo_buf->add( ' CommandPalette.instances.forEach(function(instance) {' ). lo_buf->add( ' instance.elements.palette.style.display = "none";' ). lo_buf->add( ' });' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' this.elements.palette.style.display = tobeDisplayed ? "" : "none";' ). lo_buf->add( ' if (tobeDisplayed) {' ). lo_buf->add( ' this.elements.input.value = "";' ). lo_buf->add( ' this.elements.input.focus();' ). lo_buf->add( ' this.applyFilter();' ). lo_buf->add( ' this.selectFirst();' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.getCommandByElement = function(element) {' ). lo_buf->add( ' for (var i = 0; i < this.commands.length; i++) {' ). lo_buf->add( ' if (this.commands[i].element === element) return this.commands[i];' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.handleUlClick = function(event) {' ). lo_buf->add( ' var element = event.target || event.srcElement;' ). lo_buf->add( ' if (!element) return;' ). lo_buf->add( ' if (element.nodeName === "SPAN") element = element.parentNode;' ). lo_buf->add( '' ). lo_buf->add( ' if (element.nodeName === "I") element = element.parentNode;' ). lo_buf->add( '' ). lo_buf->add( ' if (element.nodeName !== "LI") return;' ). lo_buf->add( ' this.exec(this.getCommandByElement(element));' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( 'CommandPalette.prototype.exec = function(cmd) {' ). lo_buf->add( ' if (!cmd) return;' ). lo_buf->add( ' this.toggleDisplay(false);' ). lo_buf->add( ' if (typeof cmd.action === "function") {' ). lo_buf->add( ' cmd.action();' ). lo_buf->add( ' } else {' ). lo_buf->add( ' submitSapeventForm(null, cmd.action);' ). lo_buf->add( ' }' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '// Is any command palette visible?' ). lo_buf->add( 'CommandPalette.isVisible = function() {' ). lo_buf->add( ' return CommandPalette.instances.reduce(function(result, instance) { return result || instance.elements.palette.style.display !== "none" }, false);' ). lo_buf->add( '};' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Command Enumerators' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( 'function createRepoCatalogEnumerator(catalog, action) {' ). lo_buf->add( ' // expecting [{ key, isOffline, displayName }]' ). lo_buf->add( ' return function() {' ). lo_buf->add( ' return catalog.map(function(i) {' ). lo_buf->add( ' return {' ). lo_buf->add( ' action : action + "?key=" + i.key,' ). lo_buf->add( ' iconClass: i.isOffline ? "icon icon-plug darkgrey" : "icon icon-cloud-upload-alt blue",' ). lo_buf->add( ' title : i.displayName' ). lo_buf->add( ' };' ). lo_buf->add( ' });' ). lo_buf->add( ' };' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function enumerateUiActions() {' ). lo_buf->add( ' var items = [];' ). lo_buf->add( ' function processUL(ulNode, prefix) {' ). lo_buf->add( ' for (var i = 0; i < ulNode.children.length; i++) {' ). lo_buf->add( ' var item = ulNode.children[i];' ). lo_buf->add( ' if (item.nodeName !== "LI") continue; // unexpected node' ). lo_buf->add( ' if (item.children.length >= 2 && item.children[1].nodeName === "UL") {' ). lo_buf->add( ' // submenu detected' ). lo_buf->add( ' var menutext = item.children[0].innerText;' ). lo_buf->add( ' // special treatment for menus without text' ). lo_buf->add( ' if (!menutext) {' ). lo_buf->add( ' menutext = item.children[0].getAttribute("title");' ). lo_buf->add( ' }' ). lo_buf->add( ' processUL(item.children[1], menutext);' ). lo_buf->add( ' } else if (item.firstElementChild && item.firstElementChild.nodeName === "A") {' ). lo_buf->add( ' var anchor = item.firstElementChild;' ). lo_buf->add( ' if (anchor.href && anchor.href !== "#") items.push([anchor, prefix]);' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' // toolbars' ). lo_buf->add( ' [].slice.call(document.querySelectorAll(".nav-container > ul[id*=toolbar]"))' ). lo_buf->add( ' .filter(function(toolbar) {' ). lo_buf->add( ' return (toolbar && toolbar.nodeName === "UL");' ). lo_buf->add( ' }).forEach(function(toolbar) {' ). lo_buf->add( ' processUL(toolbar);' ). lo_buf->add( ' });' ). lo_buf->add( '' ). lo_buf->add( ' items = items.map(function(item) {' ). lo_buf->add( ' var action = "";' ). lo_buf->add( ' var anchor = item[0];' ). lo_buf->add( ' if (anchor.href.includes("#")) {' ). lo_buf->add( ' action = function() {' ). lo_buf->add( ' anchor.click();' ). lo_buf->add( ' };' ). lo_buf->add( ' } else {' ). lo_buf->add( ' action = anchor.href.replace("sapevent:", "");' ). lo_buf->add( ' }' ). lo_buf->add( ' var prefix = item[1];' ). lo_buf->add( ' return {' ). lo_buf->add( ' action: action,' ). lo_buf->add( ' title : (prefix ? prefix + ": " : "") + anchor.innerText.trim()' ). lo_buf->add( ' };' ). lo_buf->add( ' });' ). lo_buf->add( '' ). lo_buf->add( ' // forms' ). lo_buf->add( ' [].slice.call(document.querySelectorAll("input[type=''submit'']"))' ). lo_buf->add( ' .forEach(function(input) {' ). lo_buf->add( ' items.push({' ). lo_buf->add( ' action: function() {' ). lo_buf->add( ' if (input.form.action.includes(input.formAction) || input.classList.contains("main")) {' ). lo_buf->add( ' input.form.submit();' ). lo_buf->add( ' } else {' ). lo_buf->add( ' submitSapeventForm({}, input.formAction, "post", input.form);' ). lo_buf->add( ' }' ). lo_buf->add( ' },' ). lo_buf->add( ' title: (input.value === "Submit Query" ? input.title : input.value + " " + input.title.replace(/\[.*\]/, ""))' ). lo_buf->add( ' });' ). lo_buf->add( ' });' ). lo_buf->add( '' ). lo_buf->add( ' // radio buttons' ). lo_buf->add( ' [].slice.call(document.querySelectorAll("input[type=''radio'']"))' ). lo_buf->add( ' .forEach(function(input) {' ). lo_buf->add( ' items.push({' ). lo_buf->add( ' action: function() {' ). lo_buf->add( ' input.click();' ). lo_buf->add( ' },' ). lo_buf->add( ' title: document.querySelector("label[for=''" + input.id + "'']").textContent' ). lo_buf->add( ' });' ). lo_buf->add( ' });' ). lo_buf->add( '' ). lo_buf->add( ' // others:' ). lo_buf->add( ' // - links inside forms' ). lo_buf->add( ' // - label links' ). lo_buf->add( ' // - command links' ). lo_buf->add( ' // - other header links' ). lo_buf->add( ' [].slice.call(document.querySelectorAll("form a, a.command:not(.unlisted), #header ul:not([id*=''toolbar'']) a"))' ). lo_buf->add( ' .filter(function(anchor) {' ). lo_buf->add( ' return !!anchor.title || !!anchor.text;' ). lo_buf->add( ' }).forEach(function(anchor) {' ). lo_buf->add( ' items.push({' ). lo_buf->add( ' action: function() {' ). lo_buf->add( ' anchor.click();' ). lo_buf->add( ' },' ). lo_buf->add( ' title: (function() {' ). lo_buf->add( ' var result = anchor.title + anchor.text;' ). lo_buf->add( ' if (anchor.href.includes("label")) {' ). lo_buf->add( ' result = "Label: " + result;' ). lo_buf->add( ' }' ). lo_buf->add( ' return result.trim();' ). lo_buf->add( ' })()' ). lo_buf->add( ' });' ). lo_buf->add( ' });' ). lo_buf->add( '' ). lo_buf->add( ' return items;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function enumerateJumpAllFiles() {' ). lo_buf->add( ' var root = document.getElementById("jump");' ). lo_buf->add( ' if (!root || root.nodeName !== "UL") return null;' ). lo_buf->add( '' ). lo_buf->add( ' return Array' ). lo_buf->add( ' .prototype.slice.call(root.children)' ). lo_buf->add( ' .filter(function(elem) { return elem.nodeName === "LI" })' ). lo_buf->add( ' .map(function(listItem) {' ). lo_buf->add( ' var title = listItem.children[0].childNodes[0].textContent;' ). lo_buf->add( ' return {' ). lo_buf->add( ' action: root.onclick.bind(null, title),' ). lo_buf->add( ' title : title' ). lo_buf->add( ' };' ). lo_buf->add( ' });' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Save Scroll Position' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( 'function saveScrollPosition() {' ). lo_buf->add( ' // Not supported by Java GUI' ). lo_buf->add( ' try { if (!window.sessionStorage) { return } }' ). lo_buf->add( ' catch (err) { return err }' ). lo_buf->add( '' ). lo_buf->add( ' window.sessionStorage.setItem("scrollTop", document.querySelector("html").scrollTop);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function restoreScrollPosition() {' ). lo_buf->add( ' // Not supported by Java GUI' ). lo_buf->add( ' try { if (!window.sessionStorage) { return } }' ). lo_buf->add( ' catch (err) { return err }' ). lo_buf->add( '' ). lo_buf->add( ' var scrollTop = window.sessionStorage.getItem("scrollTop");' ). lo_buf->add( ' if (scrollTop) {' ). lo_buf->add( ' document.querySelector("html").scrollTop = scrollTop;' ). lo_buf->add( ' }' ). lo_buf->add( ' window.sessionStorage.setItem("scrollTop", 0);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( 'function memorizeScrollPosition(fn) {' ). lo_buf->add( ' return function() {' ). lo_buf->add( ' saveScrollPosition();' ). lo_buf->add( ' return fn.call(this, fn.args);' ). lo_buf->add( ' }.bind(this);' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Sticky Header' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '/* https://www.w3schools.com/howto/howto_js_navbar_sticky.asp */' ). lo_buf->add( '/* Note: We have to use JS since IE does not support CSS position:sticky */' ). lo_buf->add( '' ). lo_buf->add( '// When the user scrolls the page, execute toggleSticky' ). lo_buf->add( 'window.onscroll = function() { toggleSticky() };' ). lo_buf->add( '' ). lo_buf->add( '// Add the sticky class to the navbar when you reach its scroll position.' ). lo_buf->add( '// Remove "sticky" when you leave the scroll position' ). lo_buf->add( 'function toggleSticky() {' ). lo_buf->add( ' var body = document.getElementsByTagName("body")[0];' ). lo_buf->add( ' var header = document.getElementById("header");' ). lo_buf->add( ' var sticky = header.offsetTop;' ). lo_buf->add( '' ). lo_buf->add( ' var stickyClass = "sticky";' ). lo_buf->add( ' if (body.classList.contains("full_width")) {' ). lo_buf->add( ' stickyClass = "sticky_full_width";' ). lo_buf->add( ' }' ). lo_buf->add( '' ). lo_buf->add( ' if (window.pageYOffset >= sticky) {' ). lo_buf->add( ' header.classList.add(stickyClass);' ). lo_buf->add( ' } else {' ). lo_buf->add( ' header.classList.remove(stickyClass);' ). lo_buf->add( ' }' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '/**********************************************************' ). lo_buf->add( ' * Browser Control' ). lo_buf->add( ' **********************************************************/' ). lo_buf->add( '' ). lo_buf->add( '// Toggle display of warning message when using Edge (based on Chromium) browser control' ). lo_buf->add( '// Todo: Remove once https://github.com/abapGit/abapGit/issues/4841 is fixed' ). lo_buf->add( 'function toggleBrowserControlWarning(){' ). lo_buf->add( ' if (!navigator.userAgent.includes("Edg")){' ). lo_buf->add( ' var elBrowserControlWarning = document.getElementById("browser-control-warning");' ). lo_buf->add( ' if (elBrowserControlWarning) {' ). lo_buf->add( ' elBrowserControlWarning.style.display = "none";' ). lo_buf->add( ' }' ). lo_buf->add( ' }' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '// Output type of HTML control in the abapGit footer' ). lo_buf->add( 'function displayBrowserControlFooter() {' ). lo_buf->add( ' var out = document.getElementById("browser-control-footer");' ). lo_buf->add( ' out.innerHTML = " - " + ( navigator.userAgent.includes("Edg") ? "Edge" : "IE" );' ). lo_buf->add( '}' ). li_asset_man->register_asset( iv_url = 'js/common.js' iv_type = 'text/javascript' iv_mime_name = 'ZABAPGIT_JS_COMMON' iv_inline = lo_buf->join_w_newline_and_flush( ) ). **************************************************** * abapmerge Pragma [include] - ZABAPGIT_ICON_FONT_CSS.W3MI.DATA.CSS **************************************************** lo_buf->add( '@font-face {' ). lo_buf->add( ' font-family: "ag-icons";' ). lo_buf->add( ' font-weight: normal;' ). lo_buf->add( ' font-style: normal;' ). lo_buf->add( ' src: url("../font/ag-icons.woff") format("woff");' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.icon {' ). lo_buf->add( ' line-height: 1;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.icon:before {' ). lo_buf->add( ' font-family: ag-icons !important;' ). lo_buf->add( ' font-style: normal;' ). lo_buf->add( ' font-weight: normal !important;' ). lo_buf->add( '' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' text-decoration: none;' ). lo_buf->add( ' text-align: center;' ). lo_buf->add( ' vertical-align: text-top;' ). lo_buf->add( ' /* width: 1.1em; */' ). lo_buf->add( ' /* padding-right: 0.2em */' ). lo_buf->add( '' ). lo_buf->add( ' /* For safety - reset parent styles, that can break glyph codes*/' ). lo_buf->add( ' font-variant: normal;' ). lo_buf->add( ' text-transform: none;' ). lo_buf->add( '}' ). lo_buf->add( '' ). lo_buf->add( '.icon.large { font-size: 200%; }' ). lo_buf->add( '' ). lo_buf->add( '.icon-abapgit:before { content: "\f101"; }' ). lo_buf->add( '.icon-abaplint:before { content: "\f102"; }' ). lo_buf->add( '.icon-arrow-circle-up:before { content: "\f103"; }' ). lo_buf->add( '.icon-bars:before { content: "\f104"; }' ). lo_buf->add( '.icon-bolt:before { content: "\f105"; }' ). lo_buf->add( '.icon-box:before { content: "\f106"; }' ). lo_buf->add( '.icon-briefcase:before { content: "\f107"; }' ). lo_buf->add( '.icon-bug-solid:before { content: "\f108"; }' ). lo_buf->add( '.icon-check:before { content: "\f109"; }' ). lo_buf->add( '.icon-chevron-down:before { content: "\f10a"; }' ). lo_buf->add( '.icon-chevron-left:before { content: "\f10b"; }' ). lo_buf->add( '.icon-chevron-right:before { content: "\f10c"; }' ). lo_buf->add( '.icon-chevron-up:before { content: "\f10d"; }' ). lo_buf->add( '.icon-circle-dot-regular:before { content: "\f10e"; }' ). lo_buf->add( '.icon-circle-play-regular:before { content: "\f10f"; }' ). lo_buf->add( '.icon-circle-solid:before { content: "\f110"; }' ). lo_buf->add( '.icon-cloud-commit:before { content: "\f111"; }' ). lo_buf->add( '.icon-cloud-solid:before { content: "\f112"; }' ). lo_buf->add( '.icon-cloud-upload-alt:before { content: "\f113"; }' ). lo_buf->add( '.icon-code-branch:before { content: "\f114"; }' ). lo_buf->add( '.icon-code-commit:before { content: "\f115"; }' ). lo_buf->add( '.icon-code-pull-request-solid:before { content: "\f116"; }' ). lo_buf->add( '.icon-code-solid:before { content: "\f117"; }' ). lo_buf->add( '.icon-cog:before { content: "\f118"; }' ). lo_buf->add( '.icon-copy-solid:before { content: "\f119"; }' ). lo_buf->add( '.icon-download-solid:before { content: "\f11a"; }' ). lo_buf->add( '.icon-edit-solid:before { content: "\f11b"; }' ). lo_buf->add( '.icon-exclamation-circle:before { content: "\f11c"; }' ). lo_buf->add( '.icon-exclamation-triangle:before { content: "\f11d"; }' ). lo_buf->add( '.icon-file-alt:before { content: "\f11e"; }' ). lo_buf->add( '.icon-file-code:before { content: "\f11f"; }' ). lo_buf->add( '.icon-file-image:before { content: "\f120"; }' ). lo_buf->add( '.icon-file:before { content: "\f121"; }' ). lo_buf->add( '.icon-fire-alt:before { content: "\f122"; }' ). lo_buf->add( '.icon-flow:before { content: "\f123"; }' ). lo_buf->add( '.icon-folder:before { content: "\f124"; }' ). lo_buf->add( '.icon-git-alt:before { content: "\f125"; }' ). lo_buf->add( '.icon-github:before { content: "\f126"; }' ). lo_buf->add( '.icon-heart-regular:before { content: "\f127"; }' ). lo_buf->add( '.icon-info-circle-solid:before { content: "\f128"; }' ). lo_buf->add( '.icon-language-solid:before { content: "\f129"; }' ). lo_buf->add( '.icon-lock:before { content: "\f12a"; }' ). lo_buf->add( '.icon-magnifying-glass-solid:before { content: "\f12b"; }' ). lo_buf->add( '.icon-markdown:before { content: "\f12c"; }' ). lo_buf->add( '.icon-paste-solid:before { content: "\f12d"; }' ). lo_buf->add( '.icon-plug:before { content: "\f12e"; }' ). lo_buf->add( '.icon-question-circle-solid:before { content: "\f12f"; }' ). lo_buf->add( '.icon-redo-alt-solid:before { content: "\f130"; }' ). lo_buf->add( '.icon-server-solid:before { content: "\f131"; }' ). lo_buf->add( '.icon-sliders-h:before { content: "\f132"; }' ). lo_buf->add( '.icon-snowflake:before { content: "\f133"; }' ). lo_buf->add( '.icon-star:before { content: "\f134"; }' ). lo_buf->add( '.icon-tag-solid:before { content: "\f135"; }' ). lo_buf->add( '.icon-times-solid:before { content: "\f136"; }' ). lo_buf->add( '.icon-tools-solid:before { content: "\f137"; }' ). lo_buf->add( '.icon-truck-solid:before { content: "\f138"; }' ). lo_buf->add( '.icon-upload-solid:before { content: "\f139"; }' ). lo_buf->add( '.icon-user-cog-solid:before { content: "\f13a"; }' ). lo_buf->add( '.icon-user-solid:before { content: "\f13b"; }' ). lo_buf->add( '.icon-vial-solid:before { content: "\f13c"; }' ). li_asset_man->register_asset( iv_url = 'css/ag-icons.css' iv_type = 'text/css' iv_mime_name = 'ZABAPGIT_ICON_FONT_CSS' iv_inline = lo_buf->join_w_newline_and_flush( ) ). **************************************************** * abapmerge Pragma [include-base64] - ZABAPGIT_ICON_FONT.W3MI.DATA.WOFF **************************************************** lo_buf->add( 'd09GRgABAAAAAB7AAAsAAAAANmgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABH' ). lo_buf->add( 'U1VCAAABCAAAADsAAABUIIslek9TLzIAAAFEAAAAPwAAAFZAtU4uY21hcAAA' ). lo_buf->add( 'AYQAAAFKAAAEqgUm+1RnbHlmAAAC0AAAF44AACj0lkh05mhlYWQAABpgAAAA' ). lo_buf->add( 'MAAAADYpkvEfaGhlYQAAGpAAAAAeAAAAJAmVB85obXR4AAAasAAAAGIAAAD0' ). lo_buf->add( 'eIj/62xvY2EAABsUAAAAfAAAAHwurThkbWF4cAAAG5AAAAAfAAAAIAFiARxu' ). lo_buf->add( 'YW1lAAAbsAAAASgAAAIWQeF35nBvc3QAABzYAAAB6AAAA1w9woILeJxjYGRg' ). lo_buf->add( 'YOBiMGCwY2BycfMJYeDLSSzJY5BiYGGAAJA8MpsxJzM9kYEDxgPKsYBpDiBm' ). lo_buf->add( 'g4gCACY7BUgAeJxjYGT8xTiBgZWBgXEaYxoDA4M7lP7KIMnQwsDAxMDKzIAV' ). lo_buf->add( 'BKS5pjA4fGT8aMME4uoxsTKAVDKCOADYjQlrAHic7dNrTsJAAEXhAxSUtyIg' ). lo_buf->add( 'Ioj4Qt6CCghdqAvyl6twC10Bzu11GTb55qSTttNkWiAP5IJZEEHmmww6vsJs' ). lo_buf->add( 'Jp3PUUrnIz7TayLNJ/HxGMaMxnAepWM2XBuFJxY44ZRiuK9MhSo16pxxToML' ). lo_buf->add( 'mrRoc0mHK7pc06PPDQNuGXLHPQ888sSIZ8ZMmIb15yxY8sKKNa+88c6GLTs+' ). lo_buf->add( '2HMgDgsX+D8qGrI/f2ex9sbS3coaas6060lk2r8kb/oikoKhnhjqqaEWDbVk' ). lo_buf->add( '+lKSsqFWTG+XVA21Zqh1Qz0z1HNDbRjqhaE2DbVlqG1DvTTUjqFeGWrXUK8N' ). lo_buf->add( 'tWeofUO9MdSBod4a6tBQ7wz13lAfDPXRUJ8MdWSoz4Y6NtSJoU4NdWb6u5O5' ). lo_buf->add( 'oS4MdWmoL4a6MtS1ob4a6puhvhvqxlC3hroz1A9D3RvqwVBjI/4FLdSYVwAA' ). lo_buf->add( 'eJytWnlsHNd5n2+O92ZmZ2ePmdnZm3uQM8sluaS4p0SRokRKomTJpY/Wiu3G' ). lo_buf->add( 'DKzEimUkrBKliW0ldOw4buMUqo0ELoKkAnI4BpqCQI0kQNNGlZ02RS/BRZs4' ). lo_buf->add( 'jlE1fyQo0toykiI22iz7vTezJHUlvZa7b96843vXd/y+71EwNvqCQD8tCkJJ' ). lo_buf->add( 'GBUWhVuEU8JDwmeF54S/F14VLkNMEEbafgNmoeNRj1C31WkWgTrUBIek3Dno' ). lo_buf->add( 'DoFvQsVrdfaAuweK4E532g2gFUKr7Sp1i1AAE2h3DrCfY5NqxfOVgGLrF1Js' ). lo_buf->add( 'AFLkLbvtIjTnxJDqJHCqTgJpUcdCup1UQHYEx2viEEgJX9tIdzqFLYdYz6op' ). lo_buf->add( 'pnBmXVbabXkVYqfwzQomEk7TJjFwRnjnWWi2+aOKc3eQDtammjg30NJEgtaM' ). lo_buf->add( 'd0A6ZFmuATM7pqAwVaybkmJq6VzcSlVflSTDy07thu5Y2ouLJ0lBlkCWflXP' ). lo_buf->add( 'mtlUJmNmNLiUIWJrl3dQPGQl3SjsnpoSi5NDAZFMNg6WW4VaB0eKj9hjjSR0' ). lo_buf->add( 'xt2GJcl3kbwkyYrzgFqI22kX6ali+3N0pyxrbqTX6U0bWV2SQd2Zni+8Y0W8' ). lo_buf->add( '40T5YFGWP52eSOMXylkinVTysigpWVjRUroTO7okiTukUmVYAr/hjifeU5NB' ). lo_buf->add( 'Jmc6owDFJsHlpZI4ec/L7hDBikF+PzWiQyZI782AmYT9ywfnIBY9W9eByP9p' ). lo_buf->add( 'eckXiAFjQ7VxQz383yT06ihrdzhqwtRiCakl4mIWySlK/z8URR6FKaQ4fPOE' ). lo_buf->add( 'QfeNTi4oMoB4cO/sAVnETg35HXETTj73gBgx3ytLr6ZcF9fp9j+DQ0vkO3xS' ). lo_buf->add( 'z2AXuTYjKbb7UEuUDtV9qSGJHx+vgaEKOQE/sAF/LkgCFSJCTLAEF0uHhKrg' ). lo_buf->add( 'C2PCpNAUusKMsEdYEA4KNwm/Itwm3CHcJdwjnBB+Q3gQ+7rIjdTtWk2n6oe/' ). lo_buf->add( '7g3ySvjuhk/2o9vy/vWeNmGChVw8yPiDDIylHGfBTTlvFQrNer1eLh9JpWam' ). lo_buf->add( 'pqquu7dYHC0UvKGh/p9OTRXK5aFyOVqtOrncmuumhoZ2Dw97+fzzL7/8+5/4' ). lo_buf->add( 'xGurqy9985sPpcuuW04/gz/M3Ry8wcNlo6JWIuX+a2k3nUnPptlnBnPp9DQ+' ). lo_buf->add( 'I/ibS09hOov1u7F8PpPJLCdY33Qszii572Jvrsu2WeR7/Sa8KRhCXRCs1hxM' ). lo_buf->add( 'F8Hmcr4H9UJqBqY7s+CmpvdApzUJXiUGxB6C1LS6cOrxUws8Obtk6nHdXEJl' ). lo_buf->add( 'EaH0Y9TGH+YcEBbCFgunvCNf001T/9oRVmPTxyh+bczi8BKfw3l4EU96CE9X' ). lo_buf->add( 'sMpszJZXLVcIE3D3l7zH4RzVNNpfYekN8vCwRmvsDZNz180iy6HOhUXcEtwa' ). lo_buf->add( 'qHY73hhUUPcQ3ARKUs3prtXxoPa+umQaZzUTSmBGfrOBLyZdR9228tGIZWiX' ). lo_buf->add( 'I/ELRtKAKSMtDNYmCiIgJ8eEDNJFzTYGTnOkiqTFJsUtbvLlQL+pZOKffL3/' ). lo_buf->add( 'xifjGWVafP1y3oZzdh4OPhNLnj+fjD1DS5ftfN6+vI0uXELZYDIhjNgEZ8s0' ). lo_buf->add( '4ybFarfabvE1FFB3YlLmr+0mzGsU9+R8wYJzVuH82eWChc9lqyAKhc+vra2z' ). lo_buf->add( 'DZk6axUK1tlzU+wxVbCWsbqEQ27gRwTco3nhUDiqY1MXVX1lEsjWgBWfMpHY' ). lo_buf->add( 'A2xKTDZmoO0zERmCZhcFxUadjvpbqqB5abYaSNGOds1ZzcrqnVqTKmmFNmsd' ). lo_buf->add( 'PWtps2Y3alvR3iSv+yEvm+xFrY1iq3ip2PqnaDJeKuxmpd3STxVKlZ+Wuqzp' ). lo_buf->add( '7kIpnsxZMw1exYsaMxZY2A2/jOXCPfymYAtC12eTZdPrsiRlUyCVP3yW0hHq' ). lo_buf->add( 'qKuXVQcztP8yTR36Ek3RYZWVqcOY7X9PHdCCP4aPbdGaA0YrxWghD1X+7gLF' ). lo_buf->add( '1jb9zGcwSVF6gdqPXuBZYGXAKy9s0RqBVxgti0+nCDGUQcaLuMteq3qdjpC4' ). lo_buf->add( 'doCraI1Q1p0Jtu91gsWmbChch9jrN6YVrtFy2bJMQEVLPDYnRu+Na7vBmesu' ). lo_buf->add( 'UtrY4HIhoN7JCBWkizyAvGAXYXoORraroZHpVKBd4WLvnlP39HjSn9p/+snT' ). lo_buf->add( '+3kCQq3XW+71QNgZ1vbu2XkgrNx/+kusbrl39ZjeLxqz2wmPDbm3daNxvxE1' ). lo_buf->add( 'zkYiZ43MDQb+I6oeo1n8mea6uXmuga4VtgbGSWxXlPDmlmIN9bP4CPwzyngr' ). lo_buf->add( '6MVwm4NdUaAa0GZGh2ErFKY5fPP8DibVCm2AG4CplgfC2OGxesff5z+ZLk0u' ). lo_buf->add( 'NIYyz1dnKrvGSa9WSDuHVaLrUVSQl7CVGjs8ie0+oNZz5cnJcq6ufqAyU20c' ). lo_buf->add( '0BLJWi8+PP5vrGVUH8jOI6h/8viyOea26aEO4hMSs+E4d4STgFU2OhRCkluj' ). lo_buf->add( '8pGErTUz2tO/hDpFdTdQfBUv5GlygzH/ZC/qNartjaj0ftmU76fqjWbRWmU6' ). lo_buf->add( 'cNXGdtgM2V1meg/WUI93uea7lXEPwlVUti5CUcL/2nxKQaHD5onbz44E8Wmn' ). lo_buf->add( '2+x02d/cFj9bAWSwibXJ4WuT+yZLWXDSseG86cYzQ/g+lOGPvKvYViQDY07V' ). lo_buf->add( 'ciBd7F/EKZo4y+DxcvCA1fDc0ggq8SPTs3RwlvTbYTYzqqk6gjGZ6G62rtbv' ). lo_buf->add( 'Zz1Nrb8WPNE88GeID1Bq/gHXnRbKKPVMtZvMBPPFzaKSw/Wxcxgs4f6oVarX' ). lo_buf->add( 'S1bWKiP6saJaNJqIRkUhZp6J9A709DNmPG6e0TEbORON/xhNJX4FQeF2hdlJ' ). lo_buf->add( 'X5gSltDfuRN3mKH/5jRLuY/CnYcuNzEOymmoduaADhwH19nebks6pEEDhckD' ). lo_buf->add( 'y8I0UePIE6ksbm025WXjatRUllV1WTFfMG0Tv2pYFzyKQSEs6exhQl8yaA15' ). lo_buf->add( '5VmtlmZ7mq5pz2a9GjWIqCyhmltSxFuCpnv+dqvJVrZ/Kag1A7qhTd/4ubgm' ). lo_buf->add( 'SqgfirgLAqAbJpEidBjwcBnsomwVAySmbIExVtDttOC3oq68JhlZni5o2p13' ). lo_buf->add( 'MrO3qmmrerb/oj7IWqwCNiQj2p+Pugj54XzUfT9Wv+1trHI1aKiFGSsoD7Hi' ). lo_buf->add( '67CBqHsZrYnf8ZGdfQ8RTQw4F/geZSJKqO9xiUDjR1wscpm/twc417gp7IRu' ). lo_buf->add( 'a9dNcYnw6EAM4Ed1QurokyU8SZXruYoid7uyUsnVZVXyEsivV9crHV4/JgX1' ). lo_buf->add( 'P8at3Tc5+WKmWs2IqtwelUQx4xo7ZAqGAVTeYbgZUZRG27IqXt1GIawNUXgb' ). lo_buf->add( 'kFmbJCO2bzLEp3+Gy0+gBzKOK2f+chm5LMFgTQLxloVeKXESAfJqJ1AVIQZg' ). lo_buf->add( 'MK/dgnlT719m2Hep7H75yywDCJZP6OaH9lGdrMzXeNGqbva/65bh2AlsfpYX' ). lo_buf->add( 'qeboPrpC9CtxpCtMCJ1Q+xRw9ysBBzCmQH4QA0TcDBHyGHCTr2wqGCaYh9gZ' ). lo_buf->add( 'r+HRrrGjPXQpi+4frLH0nQ2rnZwAPeTxS1HLiv7kMGu1prEelnb4qJctsaaY' ). lo_buf->add( 'TFjWRC9k32B+e3GPokJB2MV8MLSfIvH2iJ1p3ItNTmXzlJxyoslyHMEPto3N' ). lo_buf->add( 'F1vB03dK0it361HQX5HUL+4wSpFhSboTj3g4cr5//oeKVCNE7f+AQWFYsfMx' ). lo_buf->add( 'Bf3Kr7D6V3SI6ne/Itk7IthFxT7YpdR/7V0wL40qsbzdP8c6fU4lpCZt+h1v' ). lo_buf->add( 'wlsob44wgvnA+AdAgA7Mp+8GXlC7G2Db7Qb6TSuX83K5PSpVphSK6bxCtxvz' ). lo_buf->add( '06zWy33xCZlS+QlCKT/LjZ/jXi2gnJt4mj7yU8oE3AmEHdYcCol0o5HFXSrJ' ). lo_buf->add( 'JvulZJaol7VyWatfZ/ilOPMT0SWKRyLx/levMwGFr/sRPCvmb+1AXDGL75t2' ). lo_buf->add( 'lPH0dIpWA04K/L+W101s53lmZX2naSWCYEwCSlT5MsPemBiDDL0Pt/wS2/K/' ). lo_buf->add( 'ts3bzbUjMjL9OVDzrJ4lR4MHS77Rf54fKJ4QNt19pL8OJVM/0V/BqRI+X2Z7' ). lo_buf->add( 'HdytOnr/C8LbEGXvYOpnu0vKeIvL3XZZbPlu1UJ+474s9bg/h40Z/vV8ZwdT' ). lo_buf->add( 'T4O+A1qfLpfRxUlKVNwlSbtEKiWkl283cRVshiU7v3bkyHL/0jmc34dlAl1U' ). lo_buf->add( 'TOnwyTpiayrtlPDLOn6+UBBV0ZKkDj66ooRU+7ebuDErnNoRm6/1HO6Mh/2/' ). lo_buf->add( 'gXRo+Dxwbc/B2bG9SCAKL/DdQJ/y6jXTalsKl5wYaba5/PGkuwkKT21fUevI' ). lo_buf->add( 'RbacDeGSK+vSMV/WZX8KK2v5PHzuiunGj/SP8+n2L02tpSXpWE2SauusYS2/' ). lo_buf->add( 'KVNb8/slc7vuLG484iBewXRxknsNhHp+gAhD+OtJhAcZ0bS4XTQ2BBaLufrO' ). lo_buf->add( 'Q/fsvu/B+3aXc8VOZax3UzJWu3cXIXYS/iZf2tVePNeZu38Ov7nb643+X6X3' ). lo_buf->add( '93JDmakzCxGtdoxjP+4nXkZp2cOxiWAFHmwQgCRcanCZoRfstboDp4/hk0CQ' ). lo_buf->add( 'yEC0uBPsBhav4o0MjN9bTLtmn671UEFb0aezTOkua9rb8bccVKEyzlq9Gq96' ). lo_buf->add( 'dKQzgt/++Rx7jMCPWPNMr1ZiGhuTDOuC/fR1lizzWl6BSa3HaleDnq8EhELM' ). lo_buf->add( 'jTsrWCz+BtUrj42tT0IhcvHQ4OL5rhZ9eiCu7KSexIK/gLWuNhB4TPqXAf3w' ). lo_buf->add( 'IJS3wc4M8fw45wdkQ7eDCpYlBJWej6iNVNAlZZCt69MtYYavv6imtVozmo4o' ). lo_buf->add( '0/Gckikn6GRSdPJ6lCZimjL9cVV9UXO1F1SwX1TV0ZYSSUenSbKUUfKJxoNa' ). lo_buf->add( '1dGjw/QhkjOaj2MzbPKC5goqn9QbqPcJWitbWBVOCw8Kjwm/gzrFJi08VB9B' ). lo_buf->add( '1xwg5EJHo+NZFY7lEa/MojlFvMOAJ086uCHBH7Kbx2oY8PTaXrfjopLBc2YI' ). lo_buf->add( 'x00hFsI2js29BB6z7jJuReAkkRSqIZYgvmNkGqJPECx1O1j5pYgiSUOoDmTQ' ). lo_buf->add( 'xxSQRAVm96/Ov/2IqhlRI2GYiiyjSlcUiKDy14mZjSek6HAyb8YjhixqWjIa' ). lo_buf->add( 'jxb3DkXjRlJXAWRTwW3LJ0cSmnrTr1fK7/+uSGQSBSqSIRARWOFQUREREkj4' ). lo_buf->add( 'fZ8MKsuKoiKJaJdFAh+ZX1287VHETWQWUENSNaZqVJNlmeksGkFwpaYM9Cqc' ). lo_buf->add( 'zISViWlmKiVRReMfhUqplKnHdNOayNo6kc3S7QRh2KO3Le7szvefZTMhoqxI' ). lo_buf->add( 'IyCLPC4PUVDYKDIqk5A/Ab6HyLjDog+4gZuXA0FUg4lXt5NyK80dLm4eR6I2' ). lo_buf->add( 'ngKHm0wzEPrTiJHZV20uZtznjZLxvJtZbFYW0gCRifi4W5lIxNbXY4mJijse' ). lo_buf->add( 'hz8wjHSKaMstMrTTeS4Sec7ZOURayxpJpZcn41GJtKvE8c0vfMH0HVJtEyka' ). lo_buf->add( 'F67BFK2r/PxNL8ndbmyDG43A7DJ/J3VF4HQhkclUMplDVDnGbKVhsBTtPD63' ). lo_buf->add( 'I5H3sEaVTJ/VphU6z1OqHKdKYDPQnz7PI+nMgt6DULbVQcFOOQOzDolyQmkE' ). lo_buf->add( '8c4iu+JpukwGJsGtjoTTYnNG/sVyEyZF1pDfBXW6YVyv0x0E+lodLysKDCb2' ). lo_buf->add( 'MYV5EPqnRN3QxXmZxOKSdliT4jEi32p50FSN3aphqKIYzTqqrMWpFY0nZRon' ). lo_buf->add( 'hMq6ahAjTmJW5CRr0zICmLrBSYOwIYAwRfBzlsYpUW1bJZi5Y2zVUGUjbsgj' ). lo_buf->add( 'hagcN2U5ohkq8JFFRTFI3CAxO8MaqMZWDPw8PjLMx4VquxXGGqpXo+nAoYSz' ). lo_buf->add( '6dEDtx4YTQ8waP7hs/XddSgtjR4Yxe9S3j7PqjBZKtbrxYEfzfG7zcfYFjLd' ). lo_buf->add( 'QpwBkwQMA+dqH2Fq+8PdxUFw6aK/z/f33cwSmFrsfpjp+I/UwrjTX4Y1mGz5' ). lo_buf->add( 'C4/At/DM8+i1CFC+wgh7uErqO9V20+02HddvtptOU7z1599HRGmJw5j2X5ub' ). lo_buf->add( 'nZvD3+wTd2MC38pZ/ZdYLTSsXP+lDx458sGXjh59SXrg3e/GoeTQLjP/pCRM' ). lo_buf->add( 'CzPsLoGzAu4aYysaOkgzsBntcJsh5gwwJarYLpsQw5ZrZfcJU79FLVaKKnOj' ). lo_buf->add( '9ROlwCe5gO4Rd6aeME+ha0T3UVhyy+iUxxKJGHpO67oJHwx8kje/zb2oKe5r' ). lo_buf->add( 'eWQF2w7kk2Ffirsyhnl+pAVwywO8y6M3zTbTGs3g3P124GyBgBZ4qs8vFeKH' ). lo_buf->add( 'uvPdQ3HM/gwLYXWV2dbVuEZLVCvtOha5997IsV0l/hoP6q7QDbuF/Vf5G34l' ). lo_buf->add( '9JgDt5ipAbQXKGR0Ow7nMaQOY9BN/2S7FnijVsg5kihXJV2Ka2YyUdBIQszo' ). lo_buf->add( 'Sar00EFQzGzEqnSqgduwXcvcm4iVZE3KouK1qG6ZEVXRwYxYWZlpEVCJrMYN' ). lo_buf->add( 'p5SfzL0ZeBTb4plvsTsb1F1utxPgIXamCHwaKD+cl3Ebw0A4vwLmKwZhx7HK' ). lo_buf->add( 'MMWT0h/XTVp3Z0oTNzcmjjaGdro4+Rpi6V+bXAgCosPlYcqbmTatO+mJm+86' ). lo_buf->add( 'OuE4aJpqUkQqVsJQqaCFOO0S8jyLVu1AP3RBuE24W3gn53+uZJnSY3P0B9tX' ). lo_buf->add( 'HWTc/4cWcKk/zw4bzmM6G7Ds4eDxrv9FDaxYUV6HybGAq0Pe/h+WD2LfuDdV' ). lo_buf->add( '4aBwEn3O8pV3QyHnB2wW6jt/6zqnPNCEm22a17S5lk7YBi7317kkLDPJWeZZ' ). lo_buf->add( '2Jbv8xsnWN5qc5FnL16ZXYtzwQtkait77n9UzPFof2MDLqAO+AqLYnEnkoWw' ). lo_buf->add( 'fBaSYm7hJGyWddkbOo1iuzvwDzfXuxnVcIK2zJH0Bw4mdytZ0Mul15aFcr5H' ). lo_buf->add( 'dDbB7rVXre2gLbfBwbzg68hxFAFRhCwvLS2TCGYpImciSaoUVWo6KosYljpL' ). lo_buf->add( 'uxQlokTlDK6aaBnMGbK862AK0PJRImo+iWIPifxicpoYkEsd3IU2dDs5JSLL' ). lo_buf->add( 'M0ucHBJAcmhKJemzriZGKA4AqXrdYZ1pRNRc2SAmknSr4QC31G/fLZtsRtkG' ). lo_buf->add( 'O5dGhk9Wmbm9fkswHVpxcXImTnJAUXTq9RT83ylyew88zjouStw/ZefGzobw' ). lo_buf->add( 'w0qx7cbT9ybFBmJeae9T0Rho92dEdEEefRS9CzFzvwax6FN7ievCa485op3W' ). lo_buf->add( '7nvKcAhZXCTEMZ66T0vbkHrMUNUtbPFVlLuEkEXU5djbgg2MjdzN24D1ZNt6' ). lo_buf->add( 'PJlct3KfsvOr3NuzYP1TOWvdwvI2PvItVpa1NnXvCqwz225t8uYmS27yVchO' ). lo_buf->add( '/k+Oa1pKz2rHj2tZPaWx5xXvINygYvAe3oGIiqggsp3iuhWlBw2R3/ap23Q5' ). lo_buf->add( 'TweDcTA4BzwwzALTHHwz5u9QPwxhbwv7/vvpxKRzcm1+Ze5kRE2cjgzp7cjz' ). lo_buf->add( '40NWxsrZmhhVblqMHFYkOnIo5zhwq3HXzmeskbb1sPHZQEm+/3RCjZycW5lf' ). lo_buf->add( 'O+lMYvdIO1L86pAVSeYOD1NJORxZvEk2Rc3OOZ3CrdKtO3/Pao9YD5Ue3wy8' ). lo_buf->add( 'c+wiruFRsbuHncIcrgu1Gj+gdmszRjkD/D6nGaSBZlMGiygPMl0GqcTVuHnc' ). lo_buf->add( 'tMfRHeZAMN5b7q3hbwq5sz8axlXGg+fus+PHzz1gY/sp7kxjh1qvV2M/rrBW' ). lo_buf->add( 'g9hK8L24enwrFixsxoKdILwQ3rgH97ooyMpgrtxaVUPrtXUHcm0wuP+dNa/l' ). lo_buf->add( 'cZDdZyn8dmiInv7JtbHg51izrXDwicGGBvGSjyIWnOH/ufYh3M+Ojx4tskFw' ). lo_buf->add( 'UeB7DNSwawKGefglAWFedHBFwNzg4IKAYR1kGHQziiIZ2Q6P3YpfpYidGU3U' ). lo_buf->add( 'jez/xfaAX8VFVyuB44dGGj1x8V5Jziqgp2Ulg65OuUzsRFaRXR2UjCxniKi7' ). lo_buf->add( 'spId1GQUOY01T9p5KNTw1/9+daZSmTnAkn8VJZHqesLIG7KO0m3oshRJVI9U' ). lo_buf->add( 'E8Nzw8wNiBniJxwnJpFSRpZMkxYJUIrOFDVjopwpESl2/VpT4rUGDlmAfK3w' ). lo_buf->add( 'u+GAmPxAQvd8yI9mqKLKNBvVIB7H0ep2XiMK+18M7rcA4skKaoEr9ueqrWDc' ). lo_buf->add( '2oBLW8s5s33qdn54DoStcUuDYfJ2HTObd7LAeY7Fh4JrBxhA0y7TMyj4Stel' ). lo_buf->add( 'cAdjDr3/L/lejfh5cDX23v/Hp5sr8DPGPxpW1ZRaD6t09n4H1iD1/wJqjMMf' ). lo_buf->add( 'AAB4nGNgZGBgAOJ1Ukv3x/PbfGXgZmIAgYcFEQIw+v/f/3/ZpzGxArkcDGBp' ). lo_buf->add( 'AESEC/N4nGNgZGBgYgAB9qn///7/zT6NgZEBFdgCAHTqBXEAAHicVY5REcAw' ). lo_buf->add( 'CEOBn9mqlEnBxPwgYkJmYM0oo0f78Y6WQAgR0XGhi9cBm9PqLwRUP7HZ/zXR' ). lo_buf->add( 'ghWgO3Utz5hrs+LlmF2w9RbAz7yfvra/WRc9s/hel8zH555BNPTw/wA45zO6' ). lo_buf->add( 'AAAAAAAAAX4CNAJ2AroC5AMQA0wDsgPYA/4EJARKBHAEqgTqBQQFUAV+BcgG' ). lo_buf->add( 'RAZ4BvoHSgfGCAgIWAiyCO4JLgmGCgwKXAqMCsYLOAtmC64MiAzcDSYNtg3o' ). lo_buf->add( 'DiAOWA6sDuoPUg+aECgQrhGuEeQSEBJKErYTDhNeFBIUSBR6eJxjYGRgYLBl' ). lo_buf->add( 'FGCQZgABJiDmAkIGhv9gPgMAEtABgAB4nGWNS27CMBRFb/j0A1KLVKkd1qMO' ). lo_buf->add( 'qAifIQuAOQNmHYTghKAkjhyDxKwr6BK6hK6i6gq6oF7cxwRsye+8865tAD38' ). lo_buf->add( 'IMBxBbjx53E1cM3un5uke+EW+Um4jS6eha/o+8IdvGIi3MUD3vhC0Lql6aES' ). lo_buf->add( 'buAO78JN+g/hFvlTuI1HfAlf0X8Ld7DEr3AXL0E/SgdZbMp6odNdHtlTe6pL' ). lo_buf->add( 'bevMlGocjk5qrkttI6fXanVQ9T6dOJeoxJpCzUzpdJ4bVVmz1bELN85V0+Ew' ). lo_buf->add( 'ER/GpkCEFANkiGFQosYCmmaHnBN7MT3vl0xb1sz3CmOEGF2k5kyVPhnBsa6Z' ). lo_buf->add( 'XOHAs8ae2QmtQ8I+YcagIM383WM65zY0lZ9taWL6EBt/q8IUQ+7kLB/634s/' ). lo_buf->add( '3IhcMHicbVJXm9sgEPSc5SKXK76Wfumd9J5c/gtCSOIzEgrFPv/7ICE79xAe' ). lo_buf->add( 'YGbZ3dld6O31whr0/r8usYc+IgwwxAhjxJhgihnm2McBDnGEBY5xglOc4Rw3' ). lo_buf->add( 'cBO3cBt3cBf3cIH7eICHeITHeIKneIbneIGXeIXXIHiDt3iH9/iAj/iEz/iC' ). lo_buf->add( 'r/iG7/iBn/iFS/zujWhC61zYcXNKUdkDqrVaEyY0k5y4OkqoNlGipO0n6ipO' ). lo_buf->add( 'tOAZo4bHicuJUVKkA1Zwtpz5faVVRVK1rnZE8szOt0SLvLCTLXP1ohNJlSWa' ). lo_buf->add( '505SfdyZakk3W9uss7ViMyaVSwlTZSnsNJD24jBgV0tFU0Klv1QpJ4mmFSsC' ). lo_buf->add( 'DkHnLa6dlF7gj+PGhgST1t7CPlO5p/Um0P2mpTZtcOSp6GIW/IpJWlIrfEOh' ). lo_buf->add( 'zJPrJqsFrXLJx5nwDfii4hY0SpMWiZLmPGqgd9GtS5RJtR5mSqZcj/zLNLah' ). lo_buf->add( 'PwuXzAtO9W5WR6LKFLk+nH3p1ZzPGGgkFVueeYVKZBtR5SSX1JhwNy6pXjZ9' ). lo_buf->add( 'TWtq7Dagli4/bWfyr6EuteapakrpnsFwveI6kNj4jWtDithUap1JuuSRsVTH' ). lo_buf->add( 'lnZ/ZGpFyc0WKyV3WDu27HJ2bxf0nFfwg+riJy0NcCWoDLDX+wv6bwnS' ). li_asset_man->register_asset( iv_url = 'font/ag-icons.woff' iv_type = 'font/woff' iv_mime_name = 'ZABAPGIT_ICON_FONT' iv_base64 = lo_buf->join_and_flush( ) ). ri_asset_man = li_asset_man. ENDMETHOD. METHOD get_frontend_services. IF gi_fe_services IS INITIAL. IF iv_disable_gui IS INITIAL. CREATE OBJECT gi_fe_services TYPE zcl_abapgit_frontend_services. ELSE. CREATE OBJECT gi_fe_services TYPE zcl_abapgit_frontend_no_gui. ENDIF. ENDIF. ri_fe_serv = gi_fe_services. ENDMETHOD. METHOD get_gui. DATA: li_hotkey_ctl TYPE REF TO zif_abapgit_gui_hotkey_ctl, li_router TYPE REF TO zif_abapgit_gui_event_handler, li_asset_man TYPE REF TO zif_abapgit_gui_asset_manager. DATA lo_html_preprocessor TYPE REF TO zcl_abapgit_gui_html_processor. IF go_gui IS INITIAL. li_asset_man = get_asset_manager( ). CREATE OBJECT lo_html_preprocessor EXPORTING ii_asset_man = li_asset_man. lo_html_preprocessor->preserve_css( 'css/ag-icons.css' ). lo_html_preprocessor->preserve_css( 'css/common.css' ). CREATE OBJECT li_router TYPE zcl_abapgit_gui_router. CREATE OBJECT li_hotkey_ctl TYPE zcl_abapgit_gui_hotkey_ctl. CREATE OBJECT go_gui EXPORTING io_component = li_router ii_hotkey_ctl = li_hotkey_ctl ii_html_processor = lo_html_preprocessor ii_asset_man = li_asset_man. ENDIF. ro_gui = go_gui. ENDMETHOD. METHOD get_gui_services. IF gi_gui_services IS NOT BOUND. gi_gui_services ?= get_gui( ). ENDIF. ri_gui_services = gi_gui_services. ENDMETHOD. METHOD get_html_viewer. IF gi_html_viewer IS NOT BOUND. CREATE OBJECT gi_html_viewer TYPE zcl_abapgit_html_viewer_gui EXPORTING io_container = io_container iv_disable_query_table = iv_disable_query_table. ENDIF. ri_viewer = gi_html_viewer. ENDMETHOD. METHOD get_popups. IF gi_popups IS INITIAL. CREATE OBJECT gi_popups TYPE zcl_abapgit_popups. ENDIF. ri_popups = gi_popups. ENDMETHOD. ENDCLASS. CLASS kHGwlrVRrOJtQtrmwQhffrvwSNBuVh DEFINITION DEFERRED. * renamed: zcl_abapgit_popups :: lcl_object_decision_list CLASS kHGwlrVRrOJtQtrmwQhffrvwSNBuVh DEFINITION FINAL. PUBLIC SECTION. CONSTANTS c_default_column TYPE abap_componentdescr-name VALUE 'DEFAULT_COLUMN'. CONSTANTS c_fieldname_selected TYPE abap_componentdescr-name VALUE 'SELECTED'. CONSTANTS c_answer_cancel TYPE c LENGTH 1 VALUE 'A'. CONSTANTS c_fieldname_obj_type TYPE abap_componentdescr-name VALUE 'OBJ_TYPE'. CONSTANTS c_own_pfstatus TYPE sy-pfkey VALUE 'DECIDE_DIALOG'. METHODS constructor IMPORTING !it_list TYPE STANDARD TABLE !iv_title TYPE lvc_title DEFAULT space !iv_header_text TYPE csequence DEFAULT space !is_position TYPE zif_abapgit_popups=>ty_popup_position !iv_striped_pattern TYPE abap_bool DEFAULT abap_false !iv_optimize_col_width TYPE abap_bool DEFAULT abap_true !iv_selection_mode TYPE salv_de_constant DEFAULT if_salv_c_selection_mode=>multiple !iv_select_column_text TYPE csequence DEFAULT space !it_columns_to_display TYPE zif_abapgit_popups=>ty_alv_column_tt !it_preselected_rows TYPE zif_abapgit_popups=>ty_rows OPTIONAL RAISING zcx_abapgit_exception. METHODS display RAISING zcx_abapgit_exception. METHODS get_selected EXPORTING VALUE(et_list) TYPE STANDARD TABLE. PRIVATE SECTION. DATA mr_table TYPE REF TO data. DATA mo_table_descr TYPE REF TO cl_abap_tabledescr. DATA mo_alv TYPE REF TO cl_salv_table. DATA mv_cancel TYPE abap_bool. DATA ms_position TYPE zif_abapgit_popups=>ty_popup_position. " Events METHODS on_select_list_link_click FOR EVENT link_click OF cl_salv_events_table IMPORTING !row !column. METHODS on_select_list_function_click FOR EVENT added_function OF cl_salv_events_table IMPORTING !e_salv_function. METHODS on_double_click FOR EVENT double_click OF cl_salv_events_table IMPORTING !row !column. " Methods METHODS create_new_selectable_table IMPORTING it_list TYPE STANDARD TABLE. METHODS preselect IMPORTING it_preselected_rows TYPE zif_abapgit_popups=>ty_rows OPTIONAL RAISING zcx_abapgit_exception. METHODS create_alv RETURNING VALUE(ro_alv) TYPE REF TO cl_salv_table RAISING cx_salv_msg. METHODS setup_columns IMPORTING io_columns TYPE REF TO cl_salv_columns_table iv_selection_mode TYPE salv_de_constant iv_select_column_text TYPE csequence it_columns_to_display TYPE zif_abapgit_popups=>ty_alv_column_tt RAISING cx_salv_msg. METHODS setup_toolbar IMPORTING !iv_selection_mode TYPE salv_de_constant !iv_object_list TYPE abap_bool. METHODS ask_user_for_obj_category RETURNING VALUE(rv_category) TYPE string. METHODS mark_category IMPORTING iv_category TYPE string. METHODS mark_all IMPORTING iv_selected TYPE abap_bool. METHODS mark_visible IMPORTING iv_selected TYPE abap_bool. METHODS mark_selected. METHODS mark_indexed IMPORTING iv_selected TYPE abap_bool DEFAULT abap_true iv_invert TYPE abap_bool DEFAULT abap_false it_scope TYPE lvc_t_fidx. METHODS are_all_marked IMPORTING it_scope TYPE lvc_t_fidx RETURNING VALUE(rv_yes) TYPE abap_bool. ENDCLASS. CLASS kHGwlrVRrOJtQtrmwQhffrvwSNBuVh IMPLEMENTATION. METHOD display. mo_alv->display( ). IF mv_cancel = abap_true. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. ENDMETHOD. METHOD get_selected. DATA: lv_condition TYPE string, lr_exporting TYPE REF TO data, lo_data_descr TYPE REF TO cl_abap_datadescr, lo_selections TYPE REF TO cl_salv_selections, lt_selected_rows TYPE salv_t_row. FIELD-SYMBOLS: TYPE any, TYPE STANDARD TABLE, TYPE any, TYPE any, TYPE abap_bool, TYPE LINE OF salv_t_row. CLEAR et_list. " Make sure we don't accidentally return anything IF mv_cancel = abap_true. RETURN. ENDIF. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. lo_selections = mo_alv->get_selections( ). IF lo_selections->get_selection_mode( ) = if_salv_c_selection_mode=>single. lt_selected_rows = lo_selections->get_selected_rows( ). LOOP AT lt_selected_rows ASSIGNING . READ TABLE ASSIGNING INDEX . CHECK IS ASSIGNED. ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . CHECK IS ASSIGNED. = abap_true. ENDLOOP. ENDIF. lv_condition = |{ c_fieldname_selected } = ABAP_TRUE|. CREATE DATA lr_exporting LIKE LINE OF et_list. ASSIGN lr_exporting->* TO . lo_data_descr = mo_table_descr->get_table_line_type( ). LOOP AT ASSIGNING WHERE (lv_condition). CLEAR . CASE lo_data_descr->kind. WHEN cl_abap_elemdescr=>kind_elem. ASSIGN COMPONENT c_default_column OF STRUCTURE TO . ASSERT IS ASSIGNED. = . WHEN OTHERS. MOVE-CORRESPONDING TO . ENDCASE. APPEND TO et_list. ENDLOOP. ENDMETHOD. METHOD create_alv. FIELD-SYMBOLS TYPE STANDARD TABLE. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. cl_salv_table=>factory( IMPORTING r_salv_table = ro_alv CHANGING t_table = ). ENDMETHOD. METHOD constructor. DATA: lv_object_list TYPE abap_bool, lo_events TYPE REF TO cl_salv_events_table, lo_columns TYPE REF TO cl_salv_columns_table, lo_table_header TYPE REF TO cl_salv_form_text. create_new_selectable_table( it_list ). preselect( it_preselected_rows ). TRY. mo_alv = create_alv( ). mo_alv->set_screen_popup( start_column = is_position-start_column end_column = is_position-end_column start_line = is_position-start_row end_line = is_position-end_row ). ms_position = is_position. lo_events = mo_alv->get_event( ). SET HANDLER on_select_list_link_click FOR lo_events. SET HANDLER on_select_list_function_click FOR lo_events. SET HANDLER on_double_click FOR lo_events. IF iv_title CN ' _0'. mo_alv->get_display_settings( )->set_list_header( iv_title ). ENDIF. IF iv_header_text CN ' _0'. CREATE OBJECT lo_table_header EXPORTING text = iv_header_text. mo_alv->set_top_of_list( lo_table_header ). ENDIF. mo_alv->get_display_settings( )->set_striped_pattern( iv_striped_pattern ). mo_alv->get_selections( )->set_selection_mode( iv_selection_mode ). lo_columns = mo_alv->get_columns( ). lo_columns->set_optimize( iv_optimize_col_width ). TRY. lo_columns->get_column( |{ c_fieldname_obj_type }| ). lv_object_list = abap_true. CATCH cx_salv_not_found. ENDTRY. setup_columns( io_columns = lo_columns iv_selection_mode = iv_selection_mode iv_select_column_text = iv_select_column_text it_columns_to_display = it_columns_to_display ). setup_toolbar( iv_object_list = lv_object_list iv_selection_mode = iv_selection_mode ). CATCH cx_salv_msg. zcx_abapgit_exception=>raise( 'ALV error from object decision list' ). ENDTRY. ENDMETHOD. METHOD create_new_selectable_table. " create and populate a table on the fly derived from " it_data with a select column DATA: lr_struct TYPE REF TO data, lt_components TYPE cl_abap_structdescr=>component_table, lo_data_descr TYPE REF TO cl_abap_datadescr, lo_elem_descr TYPE REF TO cl_abap_elemdescr, lo_struct_descr TYPE REF TO cl_abap_structdescr, lo_struct_descr2 TYPE REF TO cl_abap_structdescr. FIELD-SYMBOLS: TYPE STANDARD TABLE, TYPE abap_componentdescr, TYPE data, TYPE any, TYPE any. mo_table_descr ?= cl_abap_tabledescr=>describe_by_data( it_list ). lo_data_descr = mo_table_descr->get_table_line_type( ). CASE lo_data_descr->kind. WHEN cl_abap_elemdescr=>kind_elem. lo_elem_descr ?= mo_table_descr->get_table_line_type( ). INSERT INITIAL LINE INTO lt_components ASSIGNING INDEX 1. -name = c_default_column. -type = lo_elem_descr. WHEN cl_abap_elemdescr=>kind_struct. lo_struct_descr ?= mo_table_descr->get_table_line_type( ). lt_components = lo_struct_descr->get_components( ). ENDCASE. IF lt_components IS INITIAL. RETURN. ENDIF. INSERT INITIAL LINE INTO lt_components ASSIGNING INDEX 1. -name = c_fieldname_selected. -type ?= cl_abap_datadescr=>describe_by_name( 'FLAG' ). lo_struct_descr2 = cl_abap_structdescr=>create( lt_components ). mo_table_descr = cl_abap_tabledescr=>create( lo_struct_descr2 ). CREATE DATA mr_table TYPE HANDLE mo_table_descr. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. CREATE DATA lr_struct TYPE HANDLE lo_struct_descr2. ASSIGN lr_struct->* TO . ASSERT sy-subrc = 0. LOOP AT it_list ASSIGNING . CLEAR . CASE lo_data_descr->kind. WHEN cl_abap_elemdescr=>kind_elem. ASSIGN COMPONENT c_default_column OF STRUCTURE TO . ASSERT IS ASSIGNED. = . WHEN OTHERS. MOVE-CORRESPONDING TO . ENDCASE. INSERT INTO TABLE . ENDLOOP. ENDMETHOD. METHOD preselect. FIELD-SYMBOLS: TYPE STANDARD TABLE, LIKE LINE OF it_preselected_rows, TYPE any, TYPE data. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. LOOP AT it_preselected_rows ASSIGNING . READ TABLE INDEX ASSIGNING . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Preselected row { } doesn't exist| ). ENDIF. ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . ASSERT sy-subrc = 0. = abap_true. ENDLOOP. ENDMETHOD. METHOD on_double_click. DATA lo_selections TYPE REF TO cl_salv_selections. lo_selections = mo_alv->get_selections( ). IF lo_selections->get_selection_mode( ) = if_salv_c_selection_mode=>single. mo_alv->close_screen( ). ENDIF. ENDMETHOD. METHOD on_select_list_function_click. " Work for functions of SAPMSVIM and OWN CASE e_salv_function. WHEN 'O.K.' OR 'OK'. mv_cancel = abap_false. mo_alv->close_screen( ). WHEN 'ABR' OR 'CANCEL'. " Canceled: clear list to overwrite nothing mv_cancel = abap_true. mo_alv->close_screen( ). WHEN 'SALL' OR 'SEL_ALL'. mark_visible( abap_true ). mo_alv->refresh( ). WHEN 'DSEL' OR 'SEL_DEL'. mark_visible( abap_false ). mo_alv->refresh( ). WHEN 'SEL_KEY'. mark_selected( ). mo_alv->refresh( ). WHEN 'SEL_CAT'. mark_category( ask_user_for_obj_category( ) ). mo_alv->refresh( ). WHEN OTHERS. mv_cancel = abap_true. mo_alv->close_screen( ). ENDCASE. ENDMETHOD. METHOD mark_all. FIELD-SYMBOLS: TYPE STANDARD TABLE, TYPE any, TYPE abap_bool. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. LOOP AT ASSIGNING . ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . ASSERT sy-subrc = 0. = iv_selected. ENDLOOP. ENDMETHOD. METHOD are_all_marked. DATA lv_index LIKE LINE OF it_scope. FIELD-SYMBOLS: TYPE STANDARD TABLE, TYPE any, TYPE abap_bool. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. LOOP AT it_scope INTO lv_index. READ TABLE ASSIGNING INDEX lv_index. CHECK sy-subrc = 0. ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . ASSERT sy-subrc = 0. IF = abap_true. rv_yes = abap_true. ELSE. rv_yes = abap_false. RETURN. ENDIF. ENDLOOP. ENDMETHOD. METHOD mark_selected. DATA lt_clear TYPE salv_t_row. DATA lt_scope TYPE lvc_t_fidx. lt_scope = mo_alv->get_selections( )->get_selected_rows( ). IF lines( lt_scope ) > 0. mark_indexed( it_scope = lt_scope iv_selected = boolc( are_all_marked( lt_scope ) = abap_false ) ). mo_alv->get_selections( )->set_selected_rows( lt_clear ). ELSE. MESSAGE 'Select rows first to mark them' TYPE 'S'. ENDIF. ENDMETHOD. METHOD mark_visible. DATA lt_filters TYPE lvc_t_filt. DATA lt_scope TYPE lvc_t_fidx. FIELD-SYMBOLS TYPE STANDARD TABLE. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. " If nothing selected, select all VISIBLE lt_filters = cl_salv_controller_metadata=>get_lvc_filter( mo_alv->get_filters( ) ). IF lines( lt_filters ) = 0. mark_all( iv_selected ). " No filters - just select all RETURN. ENDIF. CALL FUNCTION 'LVC_FILTER_APPLY' EXPORTING it_filter = lt_filters IMPORTING et_filter_index_inside = lt_scope TABLES it_data = . mark_indexed( it_scope = lt_scope iv_selected = iv_selected ). ENDMETHOD. METHOD mark_indexed. DATA lv_index LIKE LINE OF it_scope. FIELD-SYMBOLS: TYPE STANDARD TABLE, TYPE any, TYPE abap_bool. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. LOOP AT it_scope INTO lv_index. READ TABLE ASSIGNING INDEX lv_index. CHECK sy-subrc = 0. ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . ASSERT sy-subrc = 0. IF iv_invert = abap_true. = boolc( = abap_false ). ELSE. = iv_selected. ENDIF. ENDLOOP. ENDMETHOD. METHOD ask_user_for_obj_category. DATA: lv_answer TYPE c LENGTH 1, ls_position TYPE zif_abapgit_popups=>ty_popup_position, ls_selection TYPE spopli, lt_selection TYPE TABLE OF spopli. ls_selection-varoption = 'Packages'. APPEND ls_selection TO lt_selection. ls_selection-varoption = 'DDIC objects'. APPEND ls_selection TO lt_selection. ls_selection-varoption = 'Source code'. APPEND ls_selection TO lt_selection. ls_selection-varoption = 'Enhancements'. APPEND ls_selection TO lt_selection. ls_position-start_column = ms_position-start_column + 20. ls_position-start_row = ms_position-start_row + 5. CALL FUNCTION 'POPUP_TO_DECIDE_LIST' EXPORTING titel = 'Selection' textline1 = 'Which objects should be added to the selection?' start_col = ls_position-start_column start_row = ls_position-start_row cursorline = 1 IMPORTING answer = lv_answer TABLES t_spopli = lt_selection EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0 OR lv_answer = c_answer_cancel. RETURN. ENDIF. READ TABLE lt_selection INDEX lv_answer INTO ls_selection. IF sy-subrc = 0. rv_category = ls_selection-varoption. ENDIF. ENDMETHOD. METHOD mark_category. FIELD-SYMBOLS: TYPE STANDARD TABLE, TYPE tadir-object, TYPE any, TYPE abap_bool. IF iv_category IS INITIAL. RETURN. ENDIF. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. LOOP AT ASSIGNING . ASSIGN COMPONENT c_fieldname_obj_type OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . ASSERT sy-subrc = 0. CASE iv_category. WHEN 'Packages'. IF <> 'DEVC'. CONTINUE. ENDIF. WHEN 'DDIC objects'. IF zcl_abapgit_objects_activation=>is_ddic_type( ) = abap_false. CONTINUE. ENDIF. WHEN 'Source code'. IF 'CLAS,FUGR,INTF,PROG,TYPE' NS . CONTINUE. ENDIF. WHEN 'Enhancements'. IF 'ENHO,ENHS,ENHC,ENSC' NS . CONTINUE. ENDIF. WHEN OTHERS. RETURN. " Unexpected category ENDCASE. = abap_true. ENDLOOP. ENDMETHOD. METHOD on_select_list_link_click. FIELD-SYMBOLS: TYPE STANDARD TABLE, TYPE any, TYPE abap_bool. ASSIGN mr_table->* TO . ASSERT sy-subrc = 0. READ TABLE ASSIGNING INDEX row. IF sy-subrc = 0. ASSIGN COMPONENT c_fieldname_selected OF STRUCTURE TO . ASSERT sy-subrc = 0. = boolc( = abap_false ). ENDIF. mo_alv->refresh( ). ENDMETHOD. METHOD setup_columns. DATA: lt_columns TYPE salv_t_column_ref, ls_column TYPE salv_s_column_ref, lo_column TYPE REF TO cl_salv_column_list. FIELD-SYMBOLS TYPE zif_abapgit_popups=>ty_alv_column. lt_columns = io_columns->get( ). LOOP AT lt_columns INTO ls_column. lo_column ?= ls_column-r_column. IF iv_selection_mode = if_salv_c_selection_mode=>multiple AND ls_column-columnname = c_fieldname_selected. lo_column->set_cell_type( if_salv_c_cell_type=>checkbox_hotspot ). lo_column->set_output_length( 20 ). lo_column->set_short_text( |{ iv_select_column_text }| ). lo_column->set_medium_text( |{ iv_select_column_text }| ). lo_column->set_long_text( |{ iv_select_column_text }| ). CONTINUE. ENDIF. READ TABLE it_columns_to_display ASSIGNING WITH KEY name = ls_column-columnname. CASE sy-subrc. WHEN 0. IF -text CN ' _0'. lo_column->set_short_text( |{ -text }| ). lo_column->set_medium_text( |{ -text }| ). lo_column->set_long_text( |{ -text }| ). ENDIF. IF -length > 0. lo_column->set_output_length( -length ). ENDIF. IF -show_icon = abap_true. lo_column->set_icon( abap_true ). ENDIF. IF -center = abap_true. lo_column->set_alignment( if_salv_c_alignment=>centered ). ENDIF. WHEN OTHERS. lo_column->set_technical( abap_true ). " Hide column ENDCASE. ENDLOOP. ENDMETHOD. METHOD setup_toolbar. DATA: lv_report TYPE sy-repid, lv_pfstatus TYPE sy-pfkey, lo_functions TYPE REF TO cl_salv_functions_list, lt_func_list TYPE salv_t_ui_func, lv_fn TYPE string, ls_func LIKE LINE OF lt_func_list. CALL FUNCTION 'RS_CUA_STATUS_CHECK' EXPORTING program = sy-cprog objectname = c_own_pfstatus EXCEPTIONS object_not_found = 1 OTHERS = 2. IF sy-subrc = 0. mo_alv->set_screen_status( report = sy-cprog pfstatus = c_own_pfstatus ). ELSE. lv_report = 'SAPMSVIM'. IF iv_selection_mode = if_salv_c_selection_mode=>single. lv_pfstatus = '110'. ELSE. lv_pfstatus = '102'. ENDIF. mo_alv->set_screen_status( report = lv_report pfstatus = lv_pfstatus ). ENDIF. lo_functions = mo_alv->get_functions( ). lt_func_list = lo_functions->get_functions( ). LOOP AT lt_func_list INTO ls_func. lv_fn = ls_func-r_function->get_name( ). IF lv_fn = 'OK' OR lv_fn = 'CANCEL' OR lv_fn = 'O.K.' OR lv_fn = 'EABR'. ls_func-r_function->set_visible( abap_true ). ELSEIF iv_object_list = abap_true. ls_func-r_function->set_visible( abap_true ). ELSE. ls_func-r_function->set_visible( abap_false ). ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_popups IMPLEMENTATION. METHOD add_field. FIELD-SYMBOLS: LIKE LINE OF ct_fields. APPEND INITIAL LINE TO ct_fields ASSIGNING . -tabname = iv_tabname. -fieldname = iv_fieldname. -fieldtext = iv_fieldtext. -value = iv_value. -field_attr = iv_field_attr. -field_obl = iv_obligatory. ENDMETHOD. METHOD center. CONSTANTS: lc_min_size TYPE i VALUE 10, lc_min_pos TYPE i VALUE 5. " Magic math to approximate starting position of popup IF sy-scols > lc_min_size AND iv_width > 0 AND sy-scols > iv_width. rs_position-start_column = nmax( val1 = ( sy-scols - iv_width ) / 2 val2 = lc_min_pos ). ELSE. rs_position-start_column = lc_min_pos. ENDIF. IF sy-srows > lc_min_size AND iv_height > 0 AND sy-srows > iv_height. rs_position-start_row = nmax( val1 = ( sy-srows - iv_height ) / 2 - 1 val2 = lc_min_pos ). ELSE. rs_position-start_row = lc_min_pos. ENDIF. rs_position-end_column = rs_position-start_column + iv_width. rs_position-end_row = rs_position-start_row + iv_height. ENDMETHOD. METHOD commit_list_build. DATA: lv_unix_time TYPE zcl_abapgit_git_time=>ty_unixtime, lv_date TYPE d, lv_date_string TYPE c LENGTH 12, lv_time TYPE t, lv_time_string TYPE c LENGTH 10. FIELD-SYMBOLS: TYPE zif_abapgit_git_definitions=>ty_commit, TYPE ty_commit_value_tab. CLEAR: et_commits, et_value_tab. et_commits = zcl_abapgit_git_commit=>get_by_branch( iv_branch_name = iv_branch_name iv_repo_url = iv_repo_url iv_deepen_level = 99 iv_sorted = abap_false )-commits. IF et_commits IS INITIAL. zcx_abapgit_exception=>raise( |No commits are available in this branch.| ). ENDIF. SORT et_commits BY time DESCENDING. LOOP AT et_commits ASSIGNING . APPEND INITIAL LINE TO et_value_tab ASSIGNING . -commit = -sha1. -message = -message. lv_unix_time = -time. zcl_abapgit_git_time=>get_utc( EXPORTING iv_unix = lv_unix_time IMPORTING ev_time = lv_time ev_date = lv_date ). WRITE: lv_date TO lv_date_string, lv_time TO lv_time_string. -datetime = |{ lv_date_string }, | && |{ lv_time_string }|. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_popups~branch_list_popup. DATA: lo_branches TYPE REF TO zcl_abapgit_git_branch_list, lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, lv_answer TYPE c LENGTH 1, lv_default TYPE i, lv_head_suffix TYPE string, lv_head_symref TYPE string, lv_text TYPE string, lt_selection TYPE TABLE OF spopli. FIELD-SYMBOLS: LIKE LINE OF lt_selection, LIKE LINE OF lt_branches. lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). lt_branches = lo_branches->get_branches_only( ). lv_head_suffix = | ({ zif_abapgit_git_definitions=>c_head_name })|. lv_head_symref = lo_branches->get_head_symref( ). IF iv_hide_branch IS NOT INITIAL. DELETE lt_branches WHERE name = iv_hide_branch. ENDIF. IF iv_hide_head IS NOT INITIAL. DELETE lt_branches WHERE name = zif_abapgit_git_definitions=>c_head_name OR is_head = abap_true. ENDIF. IF lt_branches IS INITIAL. IF iv_hide_head IS NOT INITIAL. lv_text = 'main'. ENDIF. IF iv_hide_branch IS NOT INITIAL AND iv_hide_branch <> zif_abapgit_git_definitions=>c_git_branch-main. IF lv_text IS INITIAL. lv_text = iv_hide_branch && ' is'. ELSE. CONCATENATE lv_text 'and' iv_hide_branch 'are' INTO lv_text SEPARATED BY space. ENDIF. ELSE. lv_text = lv_text && ' is'. ENDIF. IF lv_text IS NOT INITIAL. zcx_abapgit_exception=>raise( 'No branches available to select (' && lv_text && ' hidden)' ). ELSE. zcx_abapgit_exception=>raise( 'No branches are available to select' ). ENDIF. ENDIF. LOOP AT lt_branches ASSIGNING . CHECK -name IS NOT INITIAL. " To ensure some below ifs IF -is_head = abap_true. IF -name = zif_abapgit_git_definitions=>c_head_name. " HEAD IF -name <> lv_head_symref AND lv_head_symref IS NOT INITIAL. " HEAD but other HEAD symref exists - ignore CONTINUE. ELSE. INSERT INITIAL LINE INTO lt_selection INDEX 1 ASSIGNING . -varoption = -name. ENDIF. ELSE. INSERT INITIAL LINE INTO lt_selection INDEX 1 ASSIGNING . -varoption = -display_name && lv_head_suffix. ENDIF. IF lv_default > 0. " Shift down default if set lv_default = lv_default + 1. ENDIF. ELSE. APPEND INITIAL LINE TO lt_selection ASSIGNING . -varoption = -display_name. ENDIF. IF -name = iv_default_branch. IF -is_head = abap_true. lv_default = 1. ELSE. lv_default = sy-tabix. ENDIF. ENDIF. ENDLOOP. IF iv_show_new_option = abap_true. APPEND INITIAL LINE TO lt_selection ASSIGNING . -varoption = zif_abapgit_popups=>c_new_branch_label. ENDIF. ms_position = center( iv_width = 30 iv_height = lines( lt_selection ) ). CALL FUNCTION 'POPUP_TO_DECIDE_LIST' EXPORTING titel = 'Select Branch' textline1 = 'Select a branch' start_col = ms_position-start_column start_row = ms_position-start_row cursorline = lv_default IMPORTING answer = lv_answer TABLES t_spopli = lt_selection EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error from POPUP_TO_DECIDE_LIST' ). ENDIF. IF lv_answer = c_answer_cancel. RETURN. ENDIF. READ TABLE lt_selection ASSIGNING WITH KEY selflag = abap_true. ASSERT sy-subrc = 0. IF iv_show_new_option = abap_true AND -varoption = zif_abapgit_popups=>c_new_branch_label. rs_branch-name = zif_abapgit_popups=>c_new_branch_label. ELSE. REPLACE FIRST OCCURRENCE OF lv_head_suffix IN -varoption WITH ''. READ TABLE lt_branches WITH KEY display_name = -varoption ASSIGNING . IF sy-subrc <> 0. * branch name longer than 65 characters LOOP AT lt_branches ASSIGNING WHERE display_name CS -varoption. EXIT. " current loop ENDLOOP. ENDIF. ASSERT IS ASSIGNED. rs_branch = lo_branches->find_by_name( -name ). lv_text = |Branch switched from { zcl_abapgit_git_branch_list=>get_display_name( iv_default_branch ) } to { zcl_abapgit_git_branch_list=>get_display_name( rs_branch-name ) } |. MESSAGE lv_text TYPE 'S'. ENDIF. ENDMETHOD. METHOD zif_abapgit_popups~choose_code_insp_check_variant. DATA: lt_return TYPE STANDARD TABLE OF ddshretval. FIELD-SYMBOLS: LIKE LINE OF lt_return. CALL FUNCTION 'F4IF_FIELD_VALUE_REQUEST' EXPORTING tabname = 'SCI_DYNP' fieldname = 'CHKV' TABLES return_tab = lt_return EXCEPTIONS field_not_found = 1 no_help_for_field = 2 inconsistent_help = 3 no_values_found = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. READ TABLE lt_return ASSIGNING WITH KEY retfield = 'SCI_DYNP-CHKV'. IF sy-subrc = 0. rv_check_variant = -fieldval. ENDIF. ENDMETHOD. METHOD zif_abapgit_popups~commit_list_popup. DATA: lt_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt, lt_value_tab TYPE ty_commit_value_tab_tt, lt_selected_values TYPE ty_commit_value_tab_tt, lt_columns TYPE zif_abapgit_popups=>ty_alv_column_tt. FIELD-SYMBOLS: TYPE ty_commit_value_tab, TYPE zif_abapgit_popups=>ty_alv_column. commit_list_build( EXPORTING iv_branch_name = iv_branch_name iv_repo_url = iv_repo_url IMPORTING et_value_tab = lt_value_tab et_commits = lt_commits ). APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'COMMIT'. -text = 'Hash'. -length = 8. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'MESSAGE'. -text = 'Message'. -length = 60. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'DATETIME'. -text = 'Datetime'. -length = 17. zif_abapgit_popups~popup_to_select_from_list( EXPORTING it_list = lt_value_tab iv_title = |Select a commit| iv_end_column = 100 iv_striped_pattern = abap_true iv_optimize_col_width = abap_false iv_selection_mode = if_salv_c_selection_mode=>single it_columns_to_display = lt_columns IMPORTING et_list = lt_selected_values ). IF lt_selected_values IS INITIAL. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. READ TABLE lt_selected_values ASSIGNING INDEX 1. ASSERT sy-subrc = 0. READ TABLE lt_commits INTO rs_commit WITH KEY sha1 = -commit. ASSERT sy-subrc = 0. ENDMETHOD. METHOD zif_abapgit_popups~create_branch_popup. DATA: lt_fields TYPE TABLE OF sval. DATA: lv_name TYPE spo_value. CLEAR: ev_name, ev_cancel. add_field( EXPORTING iv_tabname = 'TEXTL' iv_fieldname = 'LINE' iv_fieldtext = 'Name' iv_value = 'new-branch-name' CHANGING ct_fields = lt_fields ). TRY. _popup_3_get_values( EXPORTING iv_popup_title = |Create branch from { zcl_abapgit_git_branch_list=>get_display_name( iv_source_branch_name ) }| IMPORTING ev_value_1 = lv_name CHANGING ct_fields = lt_fields ). ev_name = zcl_abapgit_git_branch_list=>complete_heads_branch_name( zcl_abapgit_git_branch_list=>normalize_branch_name( lv_name ) ). CATCH zcx_abapgit_cancel. ev_cancel = abap_true. ENDTRY. ENDMETHOD. METHOD zif_abapgit_popups~popup_folder_logic. DATA: lt_selection TYPE TABLE OF spopli, lv_answer TYPE c LENGTH 1. FIELD-SYMBOLS: LIKE LINE OF lt_selection. APPEND INITIAL LINE TO lt_selection ASSIGNING . -selflag = abap_true. -varoption = zif_abapgit_dot_abapgit=>c_folder_logic-prefix. APPEND INITIAL LINE TO lt_selection ASSIGNING . -varoption = zif_abapgit_dot_abapgit=>c_folder_logic-full. APPEND INITIAL LINE TO lt_selection ASSIGNING . -varoption = zif_abapgit_dot_abapgit=>c_folder_logic-mixed. CALL FUNCTION 'POPUP_TO_DECIDE_LIST' EXPORTING titel = 'Folder logic' textline1 = 'Select folder logic' start_col = ms_position-start_column start_row = ms_position-start_row IMPORTING answer = lv_answer TABLES t_spopli = lt_selection EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error from POPUP_TO_DECIDE_LIST' ). ENDIF. IF lv_answer = c_answer_cancel. zcx_abapgit_cancel=>raise( |Canceled| ). ENDIF. READ TABLE lt_selection ASSIGNING WITH KEY selflag = abap_true. ASSERT sy-subrc = 0. rv_folder_logic = -varoption. ENDMETHOD. METHOD zif_abapgit_popups~popup_search_help. DATA lt_ret TYPE TABLE OF ddshretval. DATA ls_ret LIKE LINE OF lt_ret. DATA lv_tabname TYPE dfies-tabname. DATA lv_fieldname TYPE dfies-fieldname. SPLIT iv_tab_field AT '-' INTO lv_tabname lv_fieldname. lv_tabname = to_upper( lv_tabname ). lv_fieldname = to_upper( lv_fieldname ). CALL FUNCTION 'F4IF_FIELD_VALUE_REQUEST' EXPORTING tabname = lv_tabname fieldname = lv_fieldname TABLES return_tab = lt_ret EXCEPTIONS OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |F4IF_FIELD_VALUE_REQUEST error [{ iv_tab_field }]| ). ENDIF. IF lines( lt_ret ) > 0. READ TABLE lt_ret WITH KEY fieldname = lv_fieldname INTO ls_ret. IF sy-subrc = 0. rv_value = ls_ret-fieldval. ELSE. READ TABLE lt_ret INDEX 1 INTO ls_ret. ASSERT sy-subrc = 0. rv_value = ls_ret-fieldval. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_popups~popup_select_tr_requests. DATA ls_r_trkorr TYPE LINE OF zif_abapgit_definitions=>ty_trrngtrkor_tt. DATA lr_request TYPE REF TO trwbo_request_header. DATA lt_request TYPE trwbo_request_headers. ms_position = center( iv_width = 120 iv_height = 10 ). CALL FUNCTION 'TRINT_SELECT_REQUESTS' EXPORTING iv_username_pattern = iv_username_pattern is_selection = is_selection iv_complete_projects = abap_false is_popup = ms_position iv_via_selscreen = 'X' iv_title = iv_title IMPORTING et_requests = lt_request EXCEPTIONS action_aborted_by_user = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Selection canceled' ). ENDIF. IF lt_request IS INITIAL. zcx_abapgit_exception=>raise( 'No Request Found' ). ENDIF. IF lines( lt_request ) > 10000. zcx_abapgit_exception=>raise( 'Too many requests selected (max 10000)' ). ENDIF. LOOP AT lt_request REFERENCE INTO lr_request. ls_r_trkorr-sign = 'I'. ls_r_trkorr-option = 'EQ'. ls_r_trkorr-low = lr_request->trkorr. INSERT ls_r_trkorr INTO TABLE rt_r_trkorr. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_popups~popup_select_wb_tc_tr_and_tsk. DATA ls_selection TYPE trwbo_selection. DATA lv_title TYPE trwbo_title. ls_selection-trkorrpattern = space. ls_selection-connect_req_task_conditions = 'X'. ls_selection-reqfunctions = 'KTRXS'. ls_selection-reqstatus = 'RNODL'. ls_selection-taskstatus = 'RNODL'. CONDENSE ls_selection-reqfunctions NO-GAPS. ls_selection-taskfunctions = 'QRSX'. CONCATENATE sy-sysid '*' INTO ls_selection-trkorrpattern. lv_title = 'Select Transports / Tasks'. rt_r_trkorr = zif_abapgit_popups~popup_select_tr_requests( is_selection = ls_selection iv_title = lv_title iv_username_pattern = '*' ). ENDMETHOD. METHOD zif_abapgit_popups~popup_to_confirm. ms_position = center( iv_width = 65 iv_height = 5 ). CALL FUNCTION 'POPUP_TO_CONFIRM' EXPORTING titlebar = iv_titlebar text_question = iv_text_question text_button_1 = iv_text_button_1 icon_button_1 = iv_icon_button_1 text_button_2 = iv_text_button_2 icon_button_2 = iv_icon_button_2 default_button = iv_default_button display_cancel_button = iv_display_cancel_button popup_type = iv_popup_type start_column = ms_position-start_column start_row = ms_position-start_row IMPORTING answer = rv_answer EXCEPTIONS text_not_found = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from POPUP_TO_CONFIRM' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_popups~popup_to_create_package. DATA ls_data TYPE scompkdtln. MOVE-CORRESPONDING is_package_data TO ls_data. IF zcl_abapgit_factory=>get_function_module( )->function_exists( 'PB_POPUP_PACKAGE_CREATE' ) = abap_false. * looks like the function module used does not exist on all * versions since 702, so show an error zcx_abapgit_exception=>raise( 'Your system does not support automatic creation of packages.' && 'Please, create the package manually.' ). ENDIF. CALL FUNCTION 'PB_POPUP_PACKAGE_CREATE' CHANGING p_object_data = ls_data EXCEPTIONS action_cancelled = 1. ev_create = boolc( sy-subrc = 0 ). MOVE-CORRESPONDING ls_data TO es_package_data. ENDMETHOD. METHOD zif_abapgit_popups~popup_to_create_transp_branch. DATA: lt_fields TYPE TABLE OF sval, lv_transports_as_text TYPE string, lv_desc_as_text TYPE string. DATA: lv_branch_name TYPE spo_value. DATA: lv_commit_text TYPE spo_value. CLEAR: rs_transport_branch-branch_name, rs_transport_branch-commit_text. lv_transports_as_text = iv_trkorr. lv_desc_as_text = zcl_abapgit_factory=>get_cts_api( )->read_description( iv_trkorr ). add_field( EXPORTING iv_tabname = 'TEXTL' iv_fieldname = 'LINE' iv_fieldtext = 'Branch name' iv_value = lv_transports_as_text CHANGING ct_fields = lt_fields ). add_field( EXPORTING iv_tabname = 'ABAPTXT255' iv_fieldname = 'LINE' iv_fieldtext = 'Commit text' iv_value = lv_desc_as_text CHANGING ct_fields = lt_fields ). _popup_3_get_values( EXPORTING iv_popup_title = 'Transport to new Branch' IMPORTING ev_value_1 = lv_branch_name ev_value_2 = lv_commit_text CHANGING ct_fields = lt_fields ). rs_transport_branch-branch_name = lv_branch_name. rs_transport_branch-commit_text = lv_commit_text. ENDMETHOD. METHOD zif_abapgit_popups~popup_to_select_from_list. DATA lo_popup TYPE REF TO kHGwlrVRrOJtQtrmwQhffrvwSNBuVh. CLEAR et_list. ms_position = center( iv_width = iv_end_column - iv_start_column iv_height = iv_end_line - iv_start_line ). CREATE OBJECT lo_popup EXPORTING it_list = it_list iv_title = iv_title iv_header_text = iv_header_text is_position = ms_position iv_striped_pattern = iv_striped_pattern iv_optimize_col_width = iv_optimize_col_width iv_selection_mode = iv_selection_mode iv_select_column_text = iv_select_column_text it_columns_to_display = it_columns_to_display it_preselected_rows = it_preselected_rows. lo_popup->display( ). lo_popup->get_selected( IMPORTING et_list = et_list ). ENDMETHOD. METHOD zif_abapgit_popups~popup_to_select_labels. DATA: lt_all_labels TYPE zif_abapgit_repo_srv=>ty_labels, ls_label LIKE LINE OF lt_all_labels, lt_current_labels TYPE string_table, lt_selected_labels LIKE lt_all_labels, lt_columns_to_display TYPE zif_abapgit_popups=>ty_alv_column_tt, lt_preselected_rows TYPE zif_abapgit_popups=>ty_rows, ls_columns_to_display LIKE LINE OF lt_columns_to_display, lv_save_tabix TYPE i, li_popup TYPE REF TO zif_abapgit_popups. FIELD-SYMBOLS: TYPE zif_abapgit_repo_srv=>ty_label, TYPE LINE OF string_table. lt_current_labels = zcl_abapgit_repo_labels=>split( iv_labels ). lt_all_labels = zcl_abapgit_repo_srv=>get_instance( )->get_label_list( ). " Add labels which are not saved yet LOOP AT lt_current_labels ASSIGNING . READ TABLE lt_all_labels TRANSPORTING NO FIELDS WITH KEY key_label COMPONENTS label = . IF sy-subrc <> 0. ls_label-label = . INSERT ls_label INTO TABLE lt_all_labels. ENDIF. ENDLOOP. IF lines( lt_all_labels ) = 0. zcx_abapgit_exception=>raise( |No labels maintained yet| ). ENDIF. SORT lt_all_labels. DELETE ADJACENT DUPLICATES FROM lt_all_labels. " Preselect current labels LOOP AT lt_all_labels ASSIGNING . lv_save_tabix = sy-tabix. READ TABLE lt_current_labels TRANSPORTING NO FIELDS WITH KEY table_line = -label. IF sy-subrc = 0. INSERT lv_save_tabix INTO TABLE lt_preselected_rows. ENDIF. ENDLOOP. ls_columns_to_display-name = 'LABEL'. ls_columns_to_display-text = 'Label'. INSERT ls_columns_to_display INTO TABLE lt_columns_to_display. li_popup = zcl_abapgit_ui_factory=>get_popups( ). li_popup->popup_to_select_from_list( EXPORTING iv_header_text = 'Select labels' iv_select_column_text = 'Add label' it_list = lt_all_labels iv_selection_mode = if_salv_c_selection_mode=>multiple it_columns_to_display = lt_columns_to_display it_preselected_rows = lt_preselected_rows iv_start_column = 15 iv_end_column = 55 IMPORTING et_list = lt_selected_labels ). LOOP AT lt_selected_labels ASSIGNING . IF rv_labels IS NOT INITIAL. rv_labels = rv_labels && ','. ENDIF. rv_labels = rv_labels && -label. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_popups~popup_to_select_transport. CALL FUNCTION 'TR_F4_REQUESTS' IMPORTING ev_selected_request = rv_trkorr. ENDMETHOD. METHOD zif_abapgit_popups~popup_transport_request. DATA: lt_e071 TYPE STANDARD TABLE OF e071, lt_e071k TYPE STANDARD TABLE OF e071k, lv_order TYPE trkorr, ls_default TYPE zif_abapgit_default_transport=>ty_get. DATA lv_category TYPE e070-korrdev. " If default transport is set and its type matches, then use it as default for the popup ls_default = zcl_abapgit_factory=>get_default_transport( )->get( ). IF ( ls_default-trfunction = is_transport_type-request OR ls_default-trfunction IS INITIAL ) AND iv_use_default_transport = abap_true. lv_order = ls_default-ordernum. ENDIF. " Differentiate between customizing and WB requests IF is_transport_type-request = zif_abapgit_cts_api=>c_transport_type-cust_request. lv_category = zif_abapgit_cts_api=>c_transport_category-customizing. ELSE. lv_category = zif_abapgit_cts_api=>c_transport_category-workbench. ENDIF. CALL FUNCTION 'TRINT_ORDER_CHOICE' EXPORTING wi_order_type = is_transport_type-request wi_task_type = is_transport_type-task wi_category = lv_category wi_order = lv_order IMPORTING we_order = rv_transport TABLES wt_e071 = lt_e071 wt_e071k = lt_e071k EXCEPTIONS no_correction_selected = 1 display_mode = 2 object_append_error = 3 recursive_call = 4 wrong_order_type = 5 OTHERS = 6. IF sy-subrc = 1. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ELSEIF sy-subrc > 1. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_popups~tag_list_popup. DATA: lo_branches TYPE REF TO zcl_abapgit_git_branch_list, lt_tags TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, ls_branch TYPE zif_abapgit_git_definitions=>ty_git_branch, lv_answer TYPE c LENGTH 1, lv_default TYPE i, lv_tag TYPE string, lt_selection TYPE TABLE OF spopli. FIELD-SYMBOLS: LIKE LINE OF lt_selection, LIKE LINE OF lt_tags. lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). lt_tags = lo_branches->get_tags_only( ). LOOP AT lt_tags ASSIGNING WHERE name NP '*' && zif_abapgit_git_definitions=>c_git_branch-peel. APPEND INITIAL LINE TO lt_selection ASSIGNING . -varoption = zcl_abapgit_git_tag=>remove_tag_prefix( -name ). ENDLOOP. IF lt_selection IS INITIAL. zcx_abapgit_exception=>raise( 'No tags are available to select' ). ENDIF. ms_position = center( iv_width = 30 iv_height = lines( lt_selection ) ). CALL FUNCTION 'POPUP_TO_DECIDE_LIST' EXPORTING titel = 'Select Tag' textline1 = 'Select a tag' start_col = ms_position-start_column start_row = ms_position-start_row cursorline = lv_default IMPORTING answer = lv_answer TABLES t_spopli = lt_selection EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error from POPUP_TO_DECIDE_LIST' ). ENDIF. IF lv_answer = c_answer_cancel. RETURN. ENDIF. READ TABLE lt_selection ASSIGNING WITH KEY selflag = abap_true. ASSERT sy-subrc = 0. lv_tag = zcl_abapgit_git_tag=>add_tag_prefix( -varoption ). READ TABLE lt_tags WITH KEY name_key COMPONENTS name = lv_tag ASSIGNING . IF sy-subrc <> 0. " tag name longer than 65 characters LOOP AT lt_tags ASSIGNING WHERE name CS lv_tag. EXIT. ENDLOOP. ENDIF. ASSERT IS ASSIGNED. ls_branch = lo_branches->find_by_name( -name ). MOVE-CORRESPONDING ls_branch TO rs_tag. ENDMETHOD. METHOD _popup_3_get_values. DATA lv_answer TYPE c LENGTH 1. FIELD-SYMBOLS: TYPE sval. ms_position = center( iv_width = 120 iv_height = lines( ct_fields ) ). CALL FUNCTION 'POPUP_GET_VALUES' EXPORTING no_value_check = iv_no_value_check popup_title = iv_popup_title start_column = ms_position-start_column start_row = ms_position-start_row IMPORTING returncode = lv_answer TABLES fields = ct_fields EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error from POPUP_GET_VALUES' ). ENDIF. IF lv_answer = c_answer_cancel. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. IF ev_value_1 IS SUPPLIED. READ TABLE ct_fields INDEX 1 ASSIGNING . ASSERT sy-subrc = 0. ev_value_1 = -value. ENDIF. IF ev_value_2 IS SUPPLIED. READ TABLE ct_fields INDEX 2 ASSIGNING . ASSERT sy-subrc = 0. ev_value_2 = -value. ENDIF. IF ev_value_3 IS SUPPLIED. READ TABLE ct_fields INDEX 3 ASSIGNING . ASSERT sy-subrc = 0. ev_value_3 = -value. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_password_dialog IMPLEMENTATION. METHOD popup. DATA: lx_error TYPE REF TO cx_sy_dyn_call_illegal_form. IF zcl_abapgit_ui_factory=>get_frontend_services( )->gui_is_available( ) = abap_true. TRY. PERFORM password_popup IN PROGRAM (sy-cprog) USING iv_repo_url CHANGING cv_user cv_pass. CATCH cx_sy_dyn_call_illegal_form INTO lx_error. " abapGit was called via API and either wrong or no username/password " was supplied. It's not possible to call abapGit password popup in " this case. " See https://docs.abapgit.org/development/api.html#online-repository " on how to provide username/password zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ELSE. "Extract user credentials from the environment... "Class ZCL_ABAPGIT_DEFAULT_AUTH_INFO is part of https://github.com/abapGit/ADT_Backend. "It stores the credentials of a private repository as long as the session exists. "Usually this class should belong to abapGit core and a refactoring is recommended. "As a temporary solution - and to avoid a DYNPRO_SEND_IN_BACKGROUND dump - a generic "call of the getter methods for username and password is implemented by PR#2635. TRY. CALL METHOD ('ZCL_ABAPGIT_DEFAULT_AUTH_INFO')=>('GET_USER') RECEIVING rv_user = cv_user. CATCH cx_root. RETURN. ENDTRY. TRY. CALL METHOD ('ZCL_ABAPGIT_DEFAULT_AUTH_INFO')=>('GET_PASSWORD') RECEIVING rv_password = cv_pass. CATCH cx_root. "check if old version with typo in method name exists TRY. CALL METHOD ('ZCL_ABAPGIT_DEFAULT_AUTH_INFO')=>('GET_PASSOWORD') RECEIVING rv_password = cv_pass. CATCH cx_root. RETURN. ENDTRY. ENDTRY. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_frontend_services IMPLEMENTATION. METHOD get_path_from_fullname. DATA lv_len TYPE i. FIND FIRST OCCURRENCE OF REGEX '^/(.*/)?' IN iv_fullname MATCH LENGTH lv_len. IF sy-subrc = 0. rv_path = iv_fullname(lv_len). ELSE. FIND FIRST OCCURRENCE OF REGEX '^(.*\\)?' IN iv_fullname MATCH LENGTH lv_len. IF sy-subrc = 0. rv_path = iv_fullname(lv_len). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_frontend_services~clipboard_export. DATA lv_rc TYPE i. " Note: do not use a string table for 'it_data'! TRY. CALL METHOD cl_gui_frontend_services=>('CLIPBOARD_EXPORT') EXPORTING no_auth_check = iv_no_auth_check " >= 740 IMPORTING data = it_data CHANGING rc = lv_rc EXCEPTIONS cntl_error = 1 error_no_gui = 2 not_supported_by_gui = 3 no_authority = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CATCH cx_sy_dyn_call_param_missing. cl_gui_frontend_services=>clipboard_export( IMPORTING data = it_data CHANGING rc = lv_rc EXCEPTIONS cntl_error = 1 error_no_gui = 2 not_supported_by_gui = 3 no_authority = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDTRY. ENDMETHOD. METHOD zif_abapgit_frontend_services~directory_browse. IF iv_initial_folder IS NOT INITIAL. gv_initial_folder = iv_initial_folder. ENDIF. cl_gui_frontend_services=>directory_browse( EXPORTING window_title = iv_window_title initial_folder = gv_initial_folder CHANGING selected_folder = cv_selected_folder EXCEPTIONS cntl_error = 1 error_no_gui = 2 not_supported_by_gui = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. gv_initial_folder = cv_selected_folder. ENDMETHOD. METHOD zif_abapgit_frontend_services~directory_create. cl_gui_frontend_services=>directory_create( EXPORTING directory = iv_directory CHANGING rc = cv_rc EXCEPTIONS directory_create_failed = 1 cntl_error = 2 error_no_gui = 3 directory_access_denied = 4 directory_already_exists = 5 path_not_found = 6 unknown_error = 7 not_supported_by_gui = 8 wrong_parameter = 9 OTHERS = 10 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_frontend_services~directory_exist. cl_gui_frontend_services=>directory_exist( EXPORTING directory = iv_directory RECEIVING result = rv_exists EXCEPTIONS cntl_error = 1 error_no_gui = 2 wrong_parameter = 3 not_supported_by_gui = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_frontend_services~execute. cl_gui_frontend_services=>execute( EXPORTING document = iv_document application = iv_application parameter = iv_parameter default_directory = iv_default_directory maximized = iv_maximized minimized = iv_minimized synchronous = iv_synchronous operation = iv_operation EXCEPTIONS cntl_error = 1 error_no_gui = 2 bad_parameter = 3 file_not_found = 4 path_not_found = 5 file_extension_unknown = 6 error_execute_failed = 7 synchronous_failed = 8 not_supported_by_gui = 9 OTHERS = 10 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_frontend_services~file_download. TYPES ty_hex TYPE x LENGTH 200. DATA lt_rawdata TYPE STANDARD TABLE OF ty_hex WITH DEFAULT KEY. zcl_abapgit_convert=>xstring_to_bintab( EXPORTING iv_xstr = iv_xstr IMPORTING et_bintab = lt_rawdata ). cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = xstrlen( iv_xstr ) filename = iv_path filetype = 'BIN' CHANGING data_tab = lt_rawdata EXCEPTIONS file_write_error = 1 no_batch = 2 gui_refuse_filetransfer = 3 invalid_type = 4 no_authority = 5 unknown_error = 6 header_not_allowed = 7 separator_not_allowed = 8 filesize_not_allowed = 9 header_too_long = 10 dp_error_create = 11 dp_error_send = 12 dp_error_write = 13 unknown_dp_error = 14 access_denied = 15 dp_out_of_memory = 16 disk_full = 17 dp_timeout = 18 file_not_found = 19 dataprovider_exception = 20 control_flush_error = 21 not_supported_by_gui = 22 error_no_gui = 23 OTHERS = 24 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_frontend_services~file_upload. TYPES: ty_hex TYPE x LENGTH 255. DATA: lt_data TYPE TABLE OF ty_hex WITH DEFAULT KEY, lv_length TYPE i. cl_gui_frontend_services=>gui_upload( EXPORTING filename = iv_path filetype = 'BIN' IMPORTING filelength = lv_length CHANGING data_tab = lt_data EXCEPTIONS file_open_error = 1 file_read_error = 2 no_batch = 3 gui_refuse_filetransfer = 4 invalid_type = 5 no_authority = 6 unknown_error = 7 bad_data_format = 8 header_not_allowed = 9 separator_not_allowed = 10 header_too_long = 11 unknown_dp_error = 12 access_denied = 13 dp_out_of_memory = 14 disk_full = 15 dp_timeout = 16 not_supported_by_gui = 17 error_no_gui = 18 OTHERS = 19 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CONCATENATE LINES OF lt_data INTO rv_xstr IN BYTE MODE. rv_xstr = rv_xstr(lv_length). ENDMETHOD. METHOD zif_abapgit_frontend_services~get_file_separator. cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = cv_file_separator EXCEPTIONS not_supported_by_gui = 1 error_no_gui = 2 cntl_error = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_frontend_services~get_gui_version. DATA: lt_version_table TYPE filetable, lv_rc TYPE i, ls_version LIKE LINE OF lt_version_table. cl_gui_frontend_services=>get_gui_version( CHANGING version_table = lt_version_table rc = lv_rc EXCEPTIONS get_gui_version_failed = 1 cant_write_version_table = 2 gui_no_version = 3 cntl_error = 4 error_no_gui = 5 not_supported_by_gui = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. READ TABLE lt_version_table INTO ls_version INDEX 1. " gui release ev_gui_release = ls_version-filename. READ TABLE lt_version_table INTO ls_version INDEX 2. " gui sp ev_gui_sp = ls_version-filename. READ TABLE lt_version_table INTO ls_version INDEX 3. " gui patch ev_gui_patch = ls_version-filename. ev_gui_version_string = |{ ev_gui_release }.{ condense( ev_gui_sp ) }.{ condense( ev_gui_patch ) }|. ENDMETHOD. METHOD zif_abapgit_frontend_services~get_system_directory. cl_gui_frontend_services=>get_system_directory( CHANGING system_directory = cv_system_directory EXCEPTIONS cntl_error = 1 error_no_gui = 2 not_supported_by_gui = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_frontend_services~gui_is_available. CALL FUNCTION 'GUI_IS_AVAILABLE' IMPORTING return = rv_gui_is_available. ENDMETHOD. METHOD zif_abapgit_frontend_services~is_sapgui_for_java. CALL FUNCTION 'GUI_HAS_JAVABEANS' IMPORTING return = rv_result. ENDMETHOD. METHOD zif_abapgit_frontend_services~is_sapgui_for_windows. CALL FUNCTION 'GUI_HAS_ACTIVEX' IMPORTING return = rv_result. ENDMETHOD. METHOD zif_abapgit_frontend_services~is_webgui. CALL FUNCTION 'GUI_IS_ITS' IMPORTING return = rv_is_webgui. ENDMETHOD. METHOD zif_abapgit_frontend_services~open_ie_devtools. DATA: lv_system_directory TYPE string, lv_exe_full_path TYPE string. IF zif_abapgit_frontend_services~is_sapgui_for_windows( ) = abap_false. zcx_abapgit_exception=>raise( |IE DevTools not supported on frontend OS| ). ENDIF. zif_abapgit_frontend_services~get_system_directory( CHANGING cv_system_directory = lv_system_directory ). cl_gui_cfw=>flush( ). lv_exe_full_path = lv_system_directory && `\F12\IEChooser.exe`. zif_abapgit_frontend_services~execute( iv_application = lv_exe_full_path ). ENDMETHOD. METHOD zif_abapgit_frontend_services~show_file_open_dialog. DATA: lt_file_table TYPE filetable, ls_file_table LIKE LINE OF lt_file_table, lv_filter TYPE string, lv_action TYPE i, lv_rc TYPE i. IF iv_extension = 'zip'. lv_filter = 'ZIP Files (*.zip)|*.zip|' && cl_gui_frontend_services=>filetype_all. ENDIF. cl_gui_frontend_services=>file_open_dialog( EXPORTING window_title = iv_title default_filename = iv_default_filename file_filter = lv_filter initial_directory = gv_initial_folder CHANGING file_table = lt_file_table rc = lv_rc user_action = lv_action EXCEPTIONS file_open_dialog_failed = 1 cntl_error = 2 error_no_gui = 3 not_supported_by_gui = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF lv_action = cl_gui_frontend_services=>action_cancel. zcx_abapgit_exception=>raise( 'Cancelled' ). ENDIF. READ TABLE lt_file_table INDEX 1 INTO ls_file_table. ASSERT sy-subrc = 0. rv_path = ls_file_table-filename. gv_initial_folder = get_path_from_fullname( rv_path ). ENDMETHOD. METHOD zif_abapgit_frontend_services~show_file_save_dialog. DATA: lv_action TYPE i, lv_filter TYPE string, lv_filename TYPE string, lv_path TYPE string. IF iv_extension = 'zip'. lv_filter = 'ZIP Files (*.zip)|*.zip|' && cl_gui_frontend_services=>filetype_all. ENDIF. cl_gui_frontend_services=>file_save_dialog( EXPORTING window_title = iv_title default_extension = iv_extension default_file_name = iv_default_filename file_filter = lv_filter initial_directory = gv_initial_folder CHANGING filename = lv_filename path = lv_path fullpath = rv_path user_action = lv_action EXCEPTIONS cntl_error = 1 error_no_gui = 2 not_supported_by_gui = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF lv_action = cl_gui_frontend_services=>action_cancel. zcx_abapgit_exception=>raise( 'Cancelled' ). ENDIF. gv_initial_folder = lv_path. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_frontend_no_gui IMPLEMENTATION. METHOD zif_abapgit_frontend_services~clipboard_export. ENDMETHOD. METHOD zif_abapgit_frontend_services~directory_browse. ENDMETHOD. METHOD zif_abapgit_frontend_services~directory_create. ENDMETHOD. METHOD zif_abapgit_frontend_services~directory_exist. ENDMETHOD. METHOD zif_abapgit_frontend_services~execute. ENDMETHOD. METHOD zif_abapgit_frontend_services~file_download. ENDMETHOD. METHOD zif_abapgit_frontend_services~file_upload. ENDMETHOD. METHOD zif_abapgit_frontend_services~get_file_separator. ENDMETHOD. METHOD zif_abapgit_frontend_services~get_gui_version. ENDMETHOD. METHOD zif_abapgit_frontend_services~get_system_directory. ENDMETHOD. METHOD zif_abapgit_frontend_services~gui_is_available. rv_gui_is_available = abap_false. ENDMETHOD. METHOD zif_abapgit_frontend_services~is_sapgui_for_java. rv_result = abap_false. ENDMETHOD. METHOD zif_abapgit_frontend_services~is_sapgui_for_windows. rv_result = abap_false. ENDMETHOD. METHOD zif_abapgit_frontend_services~is_webgui. rv_is_webgui = abap_false. ENDMETHOD. METHOD zif_abapgit_frontend_services~open_ie_devtools. ENDMETHOD. METHOD zif_abapgit_frontend_services~show_file_open_dialog. ENDMETHOD. METHOD zif_abapgit_frontend_services~show_file_save_dialog. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_services_repo IMPLEMENTATION. METHOD activate_objects. DATA: lo_repo TYPE REF TO zcl_abapgit_repo, lo_browser TYPE REF TO zcl_abapgit_repo_content_list, lt_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt, lv_count TYPE i, lv_message TYPE string. FIELD-SYMBOLS LIKE LINE OF lt_repo_items. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). CREATE OBJECT lo_browser EXPORTING io_repo = lo_repo. lt_repo_items = lo_browser->list( '/' ). ri_log = lo_repo->create_new_log( 'Activation Log' ). " Add all inactive objects to activation queue zcl_abapgit_objects_activation=>clear( ). LOOP AT lt_repo_items ASSIGNING WHERE inactive = abap_true. zcl_abapgit_objects_activation=>add( iv_type = -obj_type iv_name = -obj_name ). lv_count = lv_count + 1. ENDLOOP. IF lv_count = 0. MESSAGE 'No inactive objects found' TYPE 'S'. RETURN. ENDIF. " Activate DDIC + non-DDIC zcl_abapgit_objects_activation=>activate( iv_ddic = abap_true ii_log = ri_log ). zcl_abapgit_objects_activation=>activate( iv_ddic = abap_false ii_log = ri_log ). IF ri_log->get_status( ) <> zif_abapgit_log=>c_status-error. lv_message = |Successfully activated { lv_count } objects|. MESSAGE lv_message TYPE 'S'. ENDIF. lo_repo->refresh( iv_drop_log = abap_false ). ENDMETHOD. METHOD check_for_restart. CONSTANTS: lc_abapgit_prog TYPE progname VALUE `ZABAPGIT`. DATA lo_repo_online TYPE REF TO zcl_abapgit_repo_online. IF io_repo->is_offline( ) = abap_true. RETURN. ENDIF. lo_repo_online ?= io_repo. " If abapGit was used to update itself, then restart to avoid LOAD_PROGRAM_&_MISMATCH dumps " because abapGit code was changed at runtime IF zcl_abapgit_ui_factory=>get_frontend_services( )->gui_is_available( ) = abap_true AND zcl_abapgit_url=>is_abapgit_repo( lo_repo_online->get_url( ) ) = abap_true AND sy-batch = abap_false AND sy-cprog = lc_abapgit_prog. IF zcl_abapgit_persist_factory=>get_settings( )->read( )->get_show_default_repo( ) = abap_false. MESSAGE 'abapGit was updated and will restart itself' TYPE 'I'. ENDIF. SUBMIT (sy-cprog). ENDIF. ENDMETHOD. METHOD check_package. DATA: li_repo TYPE REF TO zif_abapgit_repo, li_repo_srv TYPE REF TO zif_abapgit_repo_srv, lv_reason TYPE string. " make sure package is not already in use for a different repository " 702: chaining calls with exp&imp parameters causes syntax error li_repo_srv = zcl_abapgit_repo_srv=>get_instance( ). li_repo_srv->get_repo_from_package( EXPORTING iv_package = is_repo_params-package iv_ign_subpkg = is_repo_params-ignore_subpackages IMPORTING ei_repo = li_repo ev_reason = lv_reason ). IF li_repo IS BOUND. zcx_abapgit_exception=>raise( lv_reason ). ENDIF. ENDMETHOD. METHOD check_package_exists. IF zcl_abapgit_factory=>get_sap_package( iv_package )->exists( ) = abap_false. " Check if any package is included in remote READ TABLE it_remote TRANSPORTING NO FIELDS WITH KEY file COMPONENTS filename = zcl_abapgit_filename_logic=>c_package_file. IF sy-subrc <> 0. " If not, give error zcx_abapgit_exception=>raise( iv_text = |Package { iv_package } does not exist and there's no package included in the repository| iv_longtext = 'Either select an existing package, create a new one, or add a package to the repository' ). ENDIF. ENDIF. ENDMETHOD. METHOD create_package. DATA ls_package_data TYPE zif_abapgit_sap_package=>ty_create. DATA lv_create TYPE abap_bool. DATA li_popup TYPE REF TO zif_abapgit_popups. ls_package_data-devclass = condense( to_upper( iv_prefill_package ) ). raise_error_if_package_exists( ls_package_data-devclass ). li_popup = zcl_abapgit_ui_factory=>get_popups( ). li_popup->popup_to_create_package( EXPORTING is_package_data = ls_package_data IMPORTING es_package_data = ls_package_data ev_create = lv_create ). IF lv_create = abap_true. zcl_abapgit_factory=>get_sap_package( ls_package_data-devclass )->create( ls_package_data ). rv_package = ls_package_data-devclass. COMMIT WORK AND WAIT. ENDIF. ENDMETHOD. METHOD delete_unnecessary_objects. DATA: ls_checks TYPE zif_abapgit_definitions=>ty_delete_checks, ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. FIELD-SYMBOLS LIKE LINE OF is_checks-overwrite. " get confirmed deletions LOOP AT is_checks-overwrite ASSIGNING WHERE ( action = zif_abapgit_objects=>c_deserialize_action-delete OR action = zif_abapgit_objects=>c_deserialize_action-delete_add ) AND decision = zif_abapgit_definitions=>c_yes. ls_tadir-pgmid = 'R3TR'. ls_tadir-object = -obj_type. ls_tadir-obj_name = -obj_name. ls_tadir-devclass = -devclass. INSERT ls_tadir INTO TABLE lt_tadir. ENDLOOP. " todo, check if object type supports deletion of parts to avoid deleting complete object " delete objects IF lines( lt_tadir ) > 0. ls_checks-transport = is_checks-transport. zcl_abapgit_objects=>delete( it_tadir = lt_tadir is_checks = ls_checks ii_log = ii_log ). io_repo->refresh( iv_drop_log = abap_false ). ENDIF. ENDMETHOD. METHOD gui_deserialize. DATA ls_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks. " find troublesome objects ls_checks = io_repo->deserialize_checks( ). IF ls_checks-overwrite IS INITIAL. zcx_abapgit_exception=>raise( 'There is nothing to pull. The local state completely matches the remote repository.' ). ENDIF. " let the user decide what to do TRY. popup_decisions( EXPORTING io_repo = io_repo CHANGING cs_checks = ls_checks ). CATCH zcx_abapgit_cancel. RETURN. ENDTRY. real_deserialize( io_repo = io_repo is_checks = ls_checks ). ENDMETHOD. METHOD new_offline. DATA lx_error TYPE REF TO zcx_abapgit_exception. check_package( is_repo_params ). " create new repo and add to favorites ro_repo ?= zcl_abapgit_repo_srv=>get_instance( )->new_offline( iv_name = is_repo_params-name iv_package = is_repo_params-package iv_folder_logic = is_repo_params-folder_logic iv_labels = is_repo_params-labels iv_ign_subpkg = is_repo_params-ignore_subpackages iv_main_lang_only = is_repo_params-main_lang_only iv_abap_lang_vers = is_repo_params-abap_lang_vers ). TRY. check_package_exists( iv_package = is_repo_params-package it_remote = ro_repo->get_files_remote( ) ). CATCH zcx_abapgit_exception INTO lx_error. zcl_abapgit_repo_srv=>get_instance( )->delete( ro_repo ). COMMIT WORK. RAISE EXCEPTION lx_error. ENDTRY. " Make sure there're no leftovers from previous repos ro_repo->zif_abapgit_repo~checksums( )->rebuild( ). toggle_favorite( ro_repo->get_key( ) ). " Set default repo for user zcl_abapgit_persistence_user=>get_instance( )->set_repo_show( ro_repo->get_key( ) ). COMMIT WORK AND WAIT. ENDMETHOD. METHOD new_online. DATA lx_error TYPE REF TO zcx_abapgit_exception. check_package( is_repo_params ). ro_repo ?= zcl_abapgit_repo_srv=>get_instance( )->new_online( iv_url = is_repo_params-url iv_branch_name = is_repo_params-branch_name iv_name = is_repo_params-name iv_package = is_repo_params-package iv_display_name = is_repo_params-display_name iv_folder_logic = is_repo_params-folder_logic iv_labels = is_repo_params-labels iv_ign_subpkg = is_repo_params-ignore_subpackages iv_main_lang_only = is_repo_params-main_lang_only iv_abap_lang_vers = is_repo_params-abap_lang_vers ). TRY. check_package_exists( iv_package = is_repo_params-package it_remote = ro_repo->get_files_remote( ) ). CATCH zcx_abapgit_exception INTO lx_error. zcl_abapgit_repo_srv=>get_instance( )->delete( ro_repo ). COMMIT WORK. RAISE EXCEPTION lx_error. ENDTRY. " Make sure there're no leftovers from previous repos ro_repo->zif_abapgit_repo~checksums( )->rebuild( ). toggle_favorite( ro_repo->get_key( ) ). " Set default repo for user zcl_abapgit_persistence_user=>get_instance( )->set_repo_show( ro_repo->get_key( ) ). COMMIT WORK AND WAIT. ENDMETHOD. METHOD popup_decisions. DATA: lt_decision TYPE zif_abapgit_definitions=>ty_overwrite_tt, lt_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt, lt_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies. FIELD-SYMBOLS: LIKE LINE OF cs_checks-overwrite, LIKE LINE OF lt_decision. lt_decision = cs_checks-overwrite. " If there's a new namespace, it has to be pulled before all other objects READ TABLE lt_decision ASSIGNING WITH KEY obj_type = 'NSPC'. IF sy-subrc = 0 AND -action = zif_abapgit_objects=>c_deserialize_action-add. -decision = zif_abapgit_definitions=>c_yes. ELSE. " Set all new objects to YES LOOP AT lt_decision ASSIGNING WHERE action = zif_abapgit_objects=>c_deserialize_action-add. -decision = zif_abapgit_definitions=>c_yes. ENDLOOP. ENDIF. " Ask user what to do IF cs_checks-requirements-met = zif_abapgit_definitions=>c_no. lt_requirements = io_repo->get_dot_abapgit( )->get_data( )-requirements. zcl_abapgit_repo_requirements=>requirements_popup( lt_requirements ). cs_checks-requirements-decision = zif_abapgit_definitions=>c_yes. ENDIF. IF cs_checks-dependencies-met = zif_abapgit_definitions=>c_no. lt_dependencies = io_repo->get_dot_apack( )->get_manifest_descriptor( )-dependencies. zcl_abapgit_apack_helper=>dependencies_popup( lt_dependencies ). cs_checks-dependencies-decision = zif_abapgit_definitions=>c_yes. ENDIF. popup_objects_overwrite( CHANGING ct_overwrite = lt_decision ). popup_package_overwrite( CHANGING ct_overwrite = cs_checks-warning_package ). IF cs_checks-transport-required = abap_true AND cs_checks-transport-transport IS INITIAL. cs_checks-transport-transport = zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( cs_checks-transport-type ). ENDIF. " Update decisions LOOP AT cs_checks-overwrite ASSIGNING . READ TABLE lt_decision ASSIGNING WITH KEY object_type_and_name COMPONENTS obj_type = -obj_type obj_name = -obj_name. ASSERT sy-subrc = 0. -decision = -decision. ENDLOOP. ENDMETHOD. METHOD popup_objects_overwrite. DATA: lt_columns TYPE zif_abapgit_popups=>ty_alv_column_tt, lt_selected LIKE ct_overwrite, li_popups TYPE REF TO zif_abapgit_popups. DATA lt_preselected_rows TYPE zif_abapgit_popups=>ty_rows. FIELD-SYMBOLS: LIKE LINE OF ct_overwrite, TYPE zif_abapgit_popups=>ty_alv_column. IF lines( ct_overwrite ) = 0. RETURN. ENDIF. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'OBJ_TYPE'. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'OBJ_NAME'. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'DEVCLASS'. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'STATE'. -text = 'State'. -length = 3. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'ICON'. -text = 'Action'. -show_icon = abap_true. -length = 5. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'TEXT'. -text = 'Description'. LOOP AT ct_overwrite ASSIGNING 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_overwrite iv_header_text = |The following objects are different between local and remote repository.| && | Select the objects which should be brought in line with the remote version.| iv_select_column_text = 'Change?' it_columns_to_display = lt_columns it_preselected_rows = lt_preselected_rows IMPORTING et_list = lt_selected ). LOOP AT ct_overwrite ASSIGNING . READ TABLE lt_selected WITH TABLE KEY object_type_and_name COMPONENTS obj_type = -obj_type obj_name = -obj_name TRANSPORTING NO FIELDS. IF sy-subrc = 0. -decision = zif_abapgit_definitions=>c_yes. ELSE. -decision = zif_abapgit_definitions=>c_no. ENDIF. ENDLOOP. ENDMETHOD. METHOD popup_package_overwrite. DATA: lt_columns TYPE zif_abapgit_popups=>ty_alv_column_tt, lt_selected LIKE ct_overwrite, li_popups TYPE REF TO zif_abapgit_popups. FIELD-SYMBOLS: LIKE LINE OF ct_overwrite, TYPE zif_abapgit_popups=>ty_alv_column. IF lines( ct_overwrite ) = 0. RETURN. ENDIF. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'OBJ_TYPE'. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'OBJ_NAME'. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'DEVCLASS'. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'STATE'. -text = 'State'. -length = 3. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'ICON'. -text = 'Action'. -show_icon = abap_true. -length = 5. APPEND INITIAL LINE TO lt_columns ASSIGNING . -name = 'TEXT'. -text = 'Description'. li_popups = zcl_abapgit_ui_factory=>get_popups( ). li_popups->popup_to_select_from_list( EXPORTING it_list = ct_overwrite iv_header_text = |The following objects have been created in other packages.| && | Select the objects which should be overwritten.| iv_select_column_text = |Overwrite?| it_columns_to_display = lt_columns IMPORTING et_list = lt_selected ). LOOP AT ct_overwrite ASSIGNING . READ TABLE lt_selected WITH TABLE KEY object_type_and_name COMPONENTS obj_type = -obj_type obj_name = -obj_name TRANSPORTING NO FIELDS. IF sy-subrc = 0. -decision = zif_abapgit_definitions=>c_yes. ELSE. -decision = zif_abapgit_definitions=>c_no. ENDIF. ENDLOOP. ENDMETHOD. METHOD purge. DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, lv_answer TYPE c LENGTH 1, lo_repo TYPE REF TO zcl_abapgit_repo, lv_package TYPE devclass, lv_title TYPE c LENGTH 20, lv_question TYPE c LENGTH 150, ls_checks TYPE zif_abapgit_definitions=>ty_delete_checks, lv_repo_name TYPE string, lv_message TYPE string. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). lv_repo_name = lo_repo->get_name( ). lv_package = lo_repo->get_package( ). lt_tadir = lo_repo->get_tadir_objects( ). IF lines( lt_tadir ) > 0. lv_question = |This will DELETE all objects in package { lv_package } including subpackages ({ lines( lt_tadir ) } objects) from the system|. IF iv_keep_repo = abap_true. lv_title = 'Remove Objects'. lv_question = lv_question && ', but keep the reference to the repository'. ELSE. lv_title = 'Uninstall'. lv_question = lv_question && ' and remove the reference to the repository'. ENDIF. lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = lv_title iv_text_question = lv_question iv_text_button_1 = 'Delete' iv_icon_button_1 = 'ICON_DELETE' iv_text_button_2 = 'Cancel' iv_icon_button_2 = 'ICON_CANCEL' iv_default_button = '2' iv_popup_type = 'ICON_MESSAGE_WARNING' iv_display_cancel_button = abap_false ). IF lv_answer = '2'. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. ENDIF. ls_checks = lo_repo->delete_checks( ). IF ls_checks-transport-required = abap_true. ls_checks-transport-transport = zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( ls_checks-transport-type ). ENDIF. ri_log = zcl_abapgit_repo_srv=>get_instance( )->purge( ii_repo = lo_repo is_checks = ls_checks iv_keep_repo = iv_keep_repo ). COMMIT WORK. IF ri_log IS BOUND AND ri_log->get_status( ) = zif_abapgit_log=>c_status-error. zcl_abapgit_log_viewer=>show_log( ri_log ). RETURN. ENDIF. lv_message = |Repository { lv_repo_name } successfully uninstalled from Package { lv_package }. |. MESSAGE lv_message TYPE 'S'. ENDMETHOD. METHOD raise_error_if_package_exists. IF iv_devclass IS INITIAL. RETURN. ENDIF. IF zcl_abapgit_factory=>get_sap_package( iv_devclass )->exists( ) = abap_true. zcx_abapgit_exception=>raise( |Package { iv_devclass } already exists| ). ENDIF. ENDMETHOD. METHOD real_deserialize. DATA li_log TYPE REF TO zif_abapgit_log. DATA lv_msg TYPE string. li_log = io_repo->create_new_log( 'Pull Log' ). " pass decisions to delete delete_unnecessary_objects( io_repo = io_repo is_checks = is_checks ii_log = li_log ). " pass decisions to deserialize io_repo->deserialize( is_checks = is_checks ii_log = li_log ). IF li_log->get_status( ) = zif_abapgit_log=>c_status-ok. lv_msg = |Repository { io_repo->get_name( ) } successfully pulled for package { io_repo->get_package( ) }|. MESSAGE lv_msg TYPE 'S'. ENDIF. check_for_restart( io_repo ). ENDMETHOD. METHOD refresh. zcl_abapgit_repo_srv=>get_instance( )->get( iv_key )->refresh( ). ENDMETHOD. METHOD refresh_local_checksums. DATA: lv_answer TYPE c, lv_question TYPE string, lo_repo TYPE REF TO zcl_abapgit_repo. IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-update_local_checksum ) = abap_false. zcx_abapgit_exception=>raise( 'Not authorized' ). ENDIF. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). lv_question = 'This will rebuild and overwrite local repo checksums.'. IF lo_repo->is_offline( ) = abap_false. lv_question = lv_question && ' The logic: if local and remote file differs then:' && ' if remote branch is ahead then assume changes are remote,' && ' else (branches are equal) assume changes are local.' && ' This will lead to incorrect state for files changed on both sides.' && ' Please make sure you don''t have ones like that.'. ENDIF. lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = 'Warning' iv_text_question = lv_question iv_text_button_1 = 'OK' iv_icon_button_1 = 'ICON_DELETE' 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'. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. lo_repo->zif_abapgit_repo~checksums( )->rebuild( ). COMMIT WORK AND WAIT. ENDMETHOD. METHOD remove. DATA: lv_answer TYPE c LENGTH 1, li_repo TYPE REF TO zif_abapgit_repo, lv_package TYPE devclass, lv_question TYPE c LENGTH 200, lv_repo_name TYPE string, lv_message TYPE string. li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). lv_repo_name = li_repo->get_name( ). lv_package = li_repo->get_package( ). lv_question = |This will remove the repository reference to the package { lv_package }. All objects will safely remain in the system.|. lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = 'Remove Repository' iv_text_question = lv_question iv_text_button_1 = 'Remove' iv_icon_button_1 = 'ICON_WF_UNLINK' 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'. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. zcl_abapgit_repo_srv=>get_instance( )->delete( li_repo ). COMMIT WORK. lv_message = |Reference to repository { lv_repo_name } successfully removed from Package { lv_package }. |. MESSAGE lv_message TYPE 'S'. ENDMETHOD. METHOD toggle_favorite. zcl_abapgit_persistence_user=>get_instance( )->toggle_favorite( iv_key ). ENDMETHOD. METHOD transport_to_branch. DATA: lo_repository TYPE REF TO zcl_abapgit_repo_online, lo_transport_to_branch TYPE REF TO zcl_abapgit_transport_2_branch, lt_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt, lv_trkorr TYPE trkorr, ls_transport_to_branch TYPE zif_abapgit_definitions=>ty_transport_to_branch. IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-transport_to_branch ) = abap_false. zcx_abapgit_exception=>raise( 'Not authorized' ). ENDIF. lo_repository ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_repository_key ). lv_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_transport( ). " Also include deleted objects that are included in transport lt_transport_objects = zcl_abapgit_transport=>to_tadir( iv_trkorr = lv_trkorr iv_deleted_objects = abap_true ). IF lt_transport_objects IS INITIAL. zcx_abapgit_exception=>raise( 'Canceled or List of objects is empty ' ). ENDIF. ls_transport_to_branch = zcl_abapgit_ui_factory=>get_popups( )->popup_to_create_transp_branch( lv_trkorr ). CREATE OBJECT lo_transport_to_branch. lo_transport_to_branch->create( io_repository = lo_repository is_transport_to_branch = ls_transport_to_branch it_transport_objects = lt_transport_objects ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_services_git IMPLEMENTATION. METHOD commit. DATA: ls_comment TYPE zif_abapgit_git_definitions=>ty_comment, li_user TYPE REF TO zif_abapgit_persist_user. li_user = zcl_abapgit_persistence_user=>get_instance( ). li_user->set_repo_git_user_name( iv_url = io_repo->get_url( ) iv_username = is_commit-committer_name ). li_user->set_repo_git_user_email( iv_url = io_repo->get_url( ) iv_email = is_commit-committer_email ). IF is_commit-committer_name IS INITIAL. zcx_abapgit_exception=>raise( 'Commit: Committer name empty' ). ELSEIF is_commit-committer_email IS INITIAL. zcx_abapgit_exception=>raise( 'Commit: Committer email empty' ). ELSEIF is_commit-author_email IS NOT INITIAL AND is_commit-author_name IS INITIAL. zcx_abapgit_exception=>raise( 'Commit: Author name empty' ). " Opposite should be OK ? ELSEIF is_commit-comment IS INITIAL. zcx_abapgit_exception=>raise( 'Commit: empty comment' ). ENDIF. ls_comment-committer-name = is_commit-committer_name. ls_comment-committer-email = is_commit-committer_email. ls_comment-author-name = is_commit-author_name. ls_comment-author-email = is_commit-author_email. ls_comment-comment = is_commit-comment. IF NOT is_commit-body IS INITIAL. CONCATENATE ls_comment-comment '' is_commit-body INTO ls_comment-comment SEPARATED BY cl_abap_char_utilities=>newline. ENDIF. zcl_abapgit_exit=>get_instance( )->validate_before_push( is_comment = ls_comment io_stage = io_stage io_repo = io_repo ). io_repo->push( is_comment = ls_comment io_stage = io_stage ). COMMIT WORK. ENDMETHOD. METHOD create_branch. DATA: lv_name TYPE string, lv_cancel TYPE abap_bool, lo_repo TYPE REF TO zcl_abapgit_repo_online, lv_msg TYPE string, li_popups TYPE REF TO zif_abapgit_popups, lv_source_branch_name TYPE string. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). lv_source_branch_name = lo_repo->get_selected_branch( ). li_popups = zcl_abapgit_ui_factory=>get_popups( ). li_popups->create_branch_popup( EXPORTING iv_source_branch_name = lv_source_branch_name IMPORTING ev_name = lv_name ev_cancel = lv_cancel ). IF lv_cancel = abap_true. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. lo_repo->create_branch( lv_name ). lv_msg = |Branch switched from { zcl_abapgit_git_branch_list=>get_display_name( lv_source_branch_name ) } to new branch { zcl_abapgit_git_branch_list=>get_display_name( lv_name ) }|. MESSAGE lv_msg TYPE 'S'. ENDMETHOD. METHOD delete_branch. DATA: lo_repo TYPE REF TO zcl_abapgit_repo_online, ls_branch TYPE zif_abapgit_git_definitions=>ty_git_branch, lv_msg TYPE string, li_popups TYPE REF TO zif_abapgit_popups. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). li_popups = zcl_abapgit_ui_factory=>get_popups( ). ls_branch = li_popups->branch_list_popup( iv_url = lo_repo->get_url( ) iv_hide_branch = lo_repo->get_selected_branch( ) iv_hide_head = abap_true ). IF ls_branch IS INITIAL. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. zcl_abapgit_git_porcelain=>delete_branch( iv_url = lo_repo->get_url( ) is_branch = ls_branch ). lv_msg = |Branch { ls_branch-display_name } deleted|. MESSAGE lv_msg TYPE 'S'. ENDMETHOD. METHOD delete_tag. DATA: lo_repo TYPE REF TO zcl_abapgit_repo_online, ls_tag TYPE zif_abapgit_git_definitions=>ty_git_tag, lv_text TYPE string. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). ls_tag = zcl_abapgit_ui_factory=>get_popups( )->tag_list_popup( lo_repo->get_url( ) ). IF ls_tag IS INITIAL. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. zcl_abapgit_git_porcelain=>delete_tag( iv_url = lo_repo->get_url( ) is_tag = ls_tag ). lv_text = |Tag { ls_tag-display_name } deleted|. MESSAGE lv_text TYPE 'S'. ENDMETHOD. METHOD pull. DATA: lo_repo TYPE REF TO zcl_abapgit_repo. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). lo_repo->refresh( ). zcl_abapgit_services_repo=>gui_deserialize( lo_repo ). ENDMETHOD. METHOD switch_branch. DATA: lo_repo TYPE REF TO zcl_abapgit_repo_online, ls_branch TYPE zif_abapgit_git_definitions=>ty_git_branch. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). ls_branch = zcl_abapgit_ui_factory=>get_popups( )->branch_list_popup( iv_url = lo_repo->get_url( ) iv_default_branch = lo_repo->get_selected_branch( ) iv_show_new_option = abap_true ). IF ls_branch IS INITIAL. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. IF ls_branch-name = zif_abapgit_popups=>c_new_branch_label. create_branch( iv_key ). RETURN. ENDIF. IF lo_repo->get_selected_commit( ) IS NOT INITIAL. lo_repo->select_commit( space ). ENDIF. lo_repo->select_branch( ls_branch-name ). COMMIT WORK AND WAIT. ENDMETHOD. METHOD switch_tag. DATA: lo_repo TYPE REF TO zcl_abapgit_repo_online, ls_tag TYPE zif_abapgit_git_definitions=>ty_git_tag, lv_text TYPE string. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). ls_tag = zcl_abapgit_ui_factory=>get_popups( )->tag_list_popup( lo_repo->get_url( ) ). IF ls_tag IS INITIAL. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. lo_repo->select_branch( zcl_abapgit_git_tag=>remove_peel( ls_tag-name ) ). COMMIT WORK AND WAIT. lv_text = |Tag switched to { ls_tag-display_name } |. MESSAGE lv_text TYPE 'S'. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_services_abapgit IMPLEMENTATION. METHOD get_abapgit_tcode. CONSTANTS lc_report_tcode_hex TYPE x VALUE '80'. DATA lt_tcodes TYPE STANDARD TABLE OF tcode. TRY. SELECT tcode FROM ('TSTC') INTO TABLE lt_tcodes WHERE pgmna = sy-cprog AND cinfo = lc_report_tcode_hex ORDER BY tcode. CATCH cx_sy_dynamic_osql_error. * ABAP Cloud/Steampunk compatibility RETURN. ENDTRY. IF lines( lt_tcodes ) > 0. READ TABLE lt_tcodes INDEX 1 INTO rv_tcode. ENDIF. ENDMETHOD. METHOD open_abapgit_changelog. open_url_in_browser( |{ c_abapgit_repo }{ c_changelog_path }| ). ENDMETHOD. METHOD open_abapgit_homepage. open_url_in_browser( |{ c_abapgit_homepage }/{ iv_page }| ). ENDMETHOD. METHOD open_abapgit_wikipage. open_url_in_browser( |{ c_abapgit_wikipage }/{ iv_page }| ). ENDMETHOD. METHOD open_dotabap_homepage. open_url_in_browser( c_dotabap_homepage ). ENDMETHOD. METHOD open_url_in_browser. DATA lx_error TYPE REF TO zcx_abapgit_exception. TRY. zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = iv_url ). CATCH zcx_abapgit_exception INTO lx_error. zcx_abapgit_exception=>raise( iv_text = 'Opening page in external browser failed.' ix_previous = lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_ROUTER IMPLEMENTATION. METHOD abapgit_services_actions. IF ii_event->mv_action = zif_abapgit_definitions=>c_action-abapgit_home. rs_handled-page = zcl_abapgit_gui_page_repo_over=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. ENDIF. ENDMETHOD. METHOD call_browser. zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = |{ iv_url }| ). ENDMETHOD. METHOD call_transaction. DATA lv_msg TYPE c LENGTH 200. CALL FUNCTION 'ABAP4_CALL_TRANSACTION' DESTINATION 'NONE' STARTING NEW TASK 'ABAPGIT' EXPORTING tcode = iv_tcode EXCEPTIONS communication_failure = 1 MESSAGE lv_msg system_failure = 2 MESSAGE lv_msg OTHERS = 3. IF sy-subrc <> 0. lv_msg = |Error starting transaction { iv_tcode }: { lv_msg }|. MESSAGE lv_msg TYPE 'I'. ELSE. lv_msg = |Transaction { iv_tcode } opened in a new window|. MESSAGE lv_msg TYPE 'S'. ENDIF. ENDMETHOD. METHOD db_actions. DATA ls_db_key TYPE zif_abapgit_persistence=>ty_content. DATA lo_query TYPE REF TO zcl_abapgit_string_map. lo_query = ii_event->query( ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-db_edit. lo_query->to_abap( CHANGING cs_container = ls_db_key ). rs_handled-page = zcl_abapgit_gui_page_db_entry=>create( is_key = ls_db_key iv_edit_mode = abap_true ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-db_display. lo_query->to_abap( CHANGING cs_container = ls_db_key ). rs_handled-page = zcl_abapgit_gui_page_db_entry=>create( ls_db_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. ENDCASE. ENDMETHOD. METHOD file_download. DATA: lv_path TYPE string, lv_default TYPE string, li_fe_serv TYPE REF TO zif_abapgit_frontend_services, lv_package TYPE devclass. lv_package = iv_package. TRANSLATE lv_package USING '/#'. CONCATENATE lv_package '_' sy-datlo '_' sy-timlo '.zip' INTO lv_default. li_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). lv_path = li_fe_serv->show_file_save_dialog( iv_title = 'Export ZIP' iv_extension = 'zip' iv_default_filename = lv_default ). li_fe_serv->file_download( iv_path = lv_path iv_xstr = iv_xstr ). ENDMETHOD. METHOD general_page_routing. DATA: lv_key TYPE zif_abapgit_persistence=>ty_repo-key, lv_last_repo_key TYPE zif_abapgit_persistence=>ty_repo-key, lo_obj_filter_trans TYPE REF TO zcl_abapgit_object_filter_tran, lo_repo TYPE REF TO zcl_abapgit_repo, lt_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt. lv_key = ii_event->query( )->get( 'KEY' ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-go_home. " Go Home lv_last_repo_key = zcl_abapgit_persistence_user=>get_instance( )->get_repo_show( ). IF lv_last_repo_key IS NOT INITIAL. rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( lv_last_repo_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. ELSE. rs_handled-page = main_page( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. ENDIF. WHEN zif_abapgit_definitions=>c_action-go_back. " Go Back rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. WHEN zif_abapgit_definitions=>c_action-go_db. " Go DB util page rs_handled-page = zcl_abapgit_gui_page_db=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-go_debuginfo. " Go debug info rs_handled-page = zcl_abapgit_gui_page_debuginfo=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-go_settings. " Go global settings rs_handled-page = zcl_abapgit_gui_page_sett_glob=>create( ). rs_handled-state = get_state_settings( ii_event ). WHEN zif_abapgit_definitions=>c_action-go_settings_personal. " Go personal settings rs_handled-page = zcl_abapgit_gui_page_sett_pers=>create( ). rs_handled-state = get_state_settings( ii_event ). WHEN zif_abapgit_definitions=>c_action-go_background_run. " Go background run page rs_handled-page = zcl_abapgit_gui_page_run_bckg=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-go_repo_diff " Go Diff page OR zif_abapgit_definitions=>c_action-go_file_diff. rs_handled-page = get_page_diff( ii_event ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. WHEN zif_abapgit_definitions=>c_action-go_patch. " Go Patch page rs_handled-page = get_page_patch( ii_event ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. WHEN zif_abapgit_definitions=>c_action-go_stage. " Go Staging page rs_handled-page = get_page_stage( ii_event ). rs_handled-state = get_state_diff( ii_event ). WHEN zif_abapgit_definitions=>c_action-go_stage_transport. " Go Staging page by Transport lt_r_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_select_wb_tc_tr_and_tsk( ). lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). CREATE OBJECT lo_obj_filter_trans. lo_obj_filter_trans->set_filter_values( iv_package = lo_repo->get_package( ) it_r_trkorr = lt_r_trkorr ). rs_handled-page = get_page_stage( ii_event = ii_event ii_obj_filter = lo_obj_filter_trans ). rs_handled-state = get_state_diff( ii_event ). WHEN zif_abapgit_definitions=>c_action-go_tutorial. " Go to tutorial rs_handled-page = zcl_abapgit_gui_page_tutorial=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-documentation. " abapGit docs zcl_abapgit_services_abapgit=>open_abapgit_wikipage( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-go_explore. " dotabap zcl_abapgit_services_abapgit=>open_dotabap_homepage( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-changelog. " abapGit full changelog zcl_abapgit_services_abapgit=>open_abapgit_changelog( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-homepage. " abapGit homepage zcl_abapgit_services_abapgit=>open_abapgit_homepage( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-sponsor. " abapGit sponsor us zcl_abapgit_services_abapgit=>open_abapgit_homepage( 'sponsor.html' ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-show_hotkeys. " show hotkeys zcl_abapgit_ui_factory=>get_gui_services( )->get_hotkeys_ctl( )->set_visible( abap_true ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD get_page_diff. DATA: ls_file TYPE zif_abapgit_git_definitions=>ty_file, ls_object TYPE zif_abapgit_definitions=>ty_item, lv_key TYPE zif_abapgit_persistence=>ty_repo-key. lv_key = ii_event->query( )->get( 'KEY' ). ls_file-path = ii_event->query( )->get( 'PATH' ). ls_file-filename = ii_event->query( )->get( 'FILENAME' ). " unescape ? ls_object-obj_type = ii_event->query( )->get( 'OBJ_TYPE' ). ls_object-obj_name = ii_event->query( )->get( 'OBJ_NAME' ). " unescape ? ri_page = zcl_abapgit_gui_page_diff=>create( iv_key = lv_key is_file = ls_file is_object = ls_object ). ENDMETHOD. METHOD get_page_patch. DATA: ls_file TYPE zif_abapgit_git_definitions=>ty_file, ls_object TYPE zif_abapgit_definitions=>ty_item, lv_key TYPE zif_abapgit_persistence=>ty_repo-key. lv_key = ii_event->query( )->get( 'KEY' ). ls_file-path = ii_event->query( )->get( 'PATH' ). ls_file-filename = ii_event->query( )->get( 'FILENAME' ). " unescape ? ls_object-obj_type = ii_event->query( )->get( 'OBJ_TYPE' ). ls_object-obj_name = ii_event->query( )->get( 'OBJ_NAME' ). " unescape ? ri_page = zcl_abapgit_gui_page_patch=>create( iv_key = lv_key is_file = ls_file is_object = ls_object ). ENDMETHOD. METHOD get_page_stage. DATA: lo_repo TYPE REF TO zcl_abapgit_repo_online, lv_key TYPE zif_abapgit_persistence=>ty_repo-key, lv_seed TYPE string, lv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result, lx_error TYPE REF TO cx_sy_move_cast_error. lv_key = ii_event->query( )->get( 'KEY' ). lv_seed = ii_event->query( )->get( 'SEED' ). lv_sci_result = zif_abapgit_definitions=>c_sci_result-no_run. TRY. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). CATCH cx_sy_move_cast_error INTO lx_error. zcx_abapgit_exception=>raise( `Staging is only possible for online repositories.` ). ENDTRY. IF lo_repo->get_selected_branch( ) CP zif_abapgit_git_definitions=>c_git_branch-tags. zcx_abapgit_exception=>raise( |You are working on a tag, must be on branch| ). ELSEIF lo_repo->get_selected_commit( ) IS NOT INITIAL. zcx_abapgit_exception=>raise( |You are working on a commit, must be on branch| ). ENDIF. IF lo_repo->get_local_settings( )-code_inspector_check_variant IS NOT INITIAL. TRY. ri_page = zcl_abapgit_gui_page_code_insp=>create( io_repo = lo_repo iv_raise_when_no_results = abap_true ). CATCH zcx_abapgit_exception. lv_sci_result = zif_abapgit_definitions=>c_sci_result-passed. ENDTRY. ENDIF. IF ri_page IS INITIAL. ri_page = zcl_abapgit_gui_page_stage=>create( io_repo = lo_repo iv_seed = lv_seed iv_sci_result = lv_sci_result ii_obj_filter = ii_obj_filter ). ENDIF. ENDMETHOD. METHOD get_state_diff. " Bookmark current page before jumping to diff page IF ii_event->mv_current_page_name CP 'ZCL_ABAPGIT_GUI_PAGE_DIFF'. rv_state = zcl_abapgit_gui=>c_event_state-new_page. ELSE. rv_state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. ENDIF. ENDMETHOD. METHOD get_state_settings. " Bookmark current page before jumping to any settings page IF ii_event->mv_current_page_name CP 'ZCL_ABAPGIT_GUI_PAGE_SETT_*'. rv_state = zcl_abapgit_gui=>c_event_state-new_page_replacing. ELSE. rv_state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. ENDIF. ENDMETHOD. METHOD git_services. DATA lv_key TYPE zif_abapgit_persistence=>ty_repo-key. DATA li_repo TYPE REF TO zif_abapgit_repo. lv_key = ii_event->query( )->get( 'KEY' ). IF lv_key IS NOT INITIAL. li_repo = zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). ENDIF. CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-git_pull. " GIT Pull zcl_abapgit_services_git=>pull( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-git_branch_create. " GIT Create new branch zcl_abapgit_services_git=>create_branch( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-git_branch_delete. " GIT Delete remote branch zcl_abapgit_services_git=>delete_branch( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-git_branch_switch. " GIT Switch branch zcl_abapgit_services_git=>switch_branch( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-git_branch_merge. " GIT Merge branch rs_handled-page = zcl_abapgit_gui_page_merge_sel=>create( li_repo ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-git_tag_create. " GIT Tag create rs_handled-page = zcl_abapgit_gui_page_tags=>create( li_repo ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-git_tag_delete. " GIT Tag delete zcl_abapgit_services_git=>delete_tag( lv_key ). zcl_abapgit_services_repo=>refresh( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-git_tag_switch. " GIT Switch Tag zcl_abapgit_services_git=>switch_tag( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD jump_display_transport. DATA: lv_adt_link TYPE string, lv_adt_jump_enabled TYPE abap_bool. lv_adt_jump_enabled = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_adt_jump_enabled( ). IF lv_adt_jump_enabled = abap_true. TRY. lv_adt_link = zcl_abapgit_adt_link=>link_transport( iv_transport ). zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = lv_adt_link ). CATCH zcx_abapgit_exception. " Fallback if ADT link execution failed or was cancelled CALL FUNCTION 'TR_DISPLAY_REQUEST' EXPORTING i_trkorr = iv_transport. ENDTRY. ELSE. CALL FUNCTION 'TR_DISPLAY_REQUEST' EXPORTING i_trkorr = iv_transport. ENDIF. ENDMETHOD. METHOD jump_display_user. " todo, user display in ADT CALL FUNCTION 'BAPI_USER_DISPLAY' EXPORTING username = iv_username. ENDMETHOD. METHOD jump_object. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, ls_sub_item TYPE zif_abapgit_definitions=>ty_item, lx_error TYPE REF TO zcx_abapgit_exception, lv_line_number TYPE i, lv_new_window TYPE abap_bool, li_html_viewer TYPE REF TO zif_abapgit_html_viewer. ls_item-obj_type = cl_http_utility=>unescape_url( |{ iv_obj_type }| ). ls_item-obj_name = cl_http_utility=>unescape_url( |{ iv_obj_name }| ). ls_sub_item-obj_type = cl_http_utility=>unescape_url( |{ iv_sub_type }| ). ls_sub_item-obj_name = cl_http_utility=>unescape_url( |{ iv_sub_name }| ). IF iv_line CO '0123456789'. lv_line_number = iv_line. ENDIF. lv_new_window = boolc( iv_new_window IS NOT INITIAL ). TRY. li_html_viewer = zcl_abapgit_ui_factory=>get_html_viewer( ). " Hide HTML Viewer in dummy screen0 for direct CALL SCREEN to work li_html_viewer->set_visiblity( abap_false ). IF ls_item-obj_type = zif_abapgit_data_config=>c_data_type-tabu. zcl_abapgit_data_utils=>jump( ls_item ). ELSEIF lv_line_number IS INITIAL OR ls_sub_item IS INITIAL. zcl_abapgit_objects=>jump( is_item = ls_item iv_filename = iv_filename iv_new_window = lv_new_window ). ELSE. zcl_abapgit_objects=>jump( is_item = ls_item is_sub_item = ls_sub_item iv_filename = iv_filename iv_line_number = lv_line_number iv_new_window = lv_new_window ). ENDIF. li_html_viewer->set_visiblity( abap_true ). CATCH zcx_abapgit_exception INTO lx_error. li_html_viewer->set_visiblity( abap_true ). RAISE EXCEPTION lx_error. ENDTRY. ENDMETHOD. METHOD main_page. DATA lt_repo_all_list TYPE zif_abapgit_repo_srv=>ty_repo_list. " if there are no favorites, check if there are any repositories at all " if not, go to tutorial where the user can create the first repository lt_repo_all_list = zcl_abapgit_repo_srv=>get_instance( )->list( ). IF lt_repo_all_list IS NOT INITIAL. ri_page = zcl_abapgit_gui_page_repo_over=>create( ). ELSE. ri_page = zcl_abapgit_gui_page_tutorial=>create( ). ENDIF. ENDMETHOD. METHOD other_utilities. TYPES ty_char600 TYPE c LENGTH 600. DATA lv_clip_content TYPE string. DATA lt_clipboard TYPE STANDARD TABLE OF ty_char600. CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-ie_devtools. zcl_abapgit_ui_factory=>get_frontend_services( )->open_ie_devtools( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-clipboard. lv_clip_content = ii_event->query( )->get( 'CLIPBOARD' ). APPEND lv_clip_content TO lt_clipboard. zcl_abapgit_ui_factory=>get_frontend_services( )->clipboard_export( lt_clipboard ). MESSAGE 'Successfully exported URL to Clipboard.' TYPE 'S'. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-yank_to_clipboard. lv_clip_content = ii_event->form_data( )->get( 'CLIPBOARD' ). APPEND lv_clip_content TO lt_clipboard. zcl_abapgit_ui_factory=>get_frontend_services( )->clipboard_export( lt_clipboard ). MESSAGE 'Successfully exported to Clipboard.' TYPE 'S'. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDCASE. ENDMETHOD. METHOD repository_services. DATA: lv_key TYPE zif_abapgit_persistence=>ty_repo-key, lo_repo TYPE REF TO zcl_abapgit_repo, li_log TYPE REF TO zif_abapgit_log. lv_key = ii_event->query( )->get( 'KEY' ). IF lv_key IS NOT INITIAL. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). ENDIF. CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-repo_newoffline. " New offline repo rs_handled-page = zcl_abapgit_gui_page_addofflin=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-repo_add_all_obj_to_trans_req. " Add objects to transport zcl_abapgit_transport=>add_all_objects_to_trans_req( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-repo_refresh. " Repo refresh zcl_abapgit_services_repo=>refresh( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-repo_syntax_check. " Syntax check rs_handled-page = zcl_abapgit_gui_page_syntax=>create( lo_repo ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-repo_code_inspector. " Code inspector rs_handled-page = zcl_abapgit_gui_page_code_insp=>create( lo_repo ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-repo_purge. " Purge all objects and repo (uninstall) zcl_abapgit_services_repo=>purge( lv_key ). rs_handled-page = zcl_abapgit_gui_page_repo_over=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. WHEN zif_abapgit_definitions=>c_action-repo_delete_objects. " Purge all objects (uninstall) zcl_abapgit_services_repo=>purge( iv_key = lv_key iv_keep_repo = abap_true ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-repo_remove. " Repo remove zcl_abapgit_services_repo=>remove( lv_key ). rs_handled-page = zcl_abapgit_gui_page_repo_over=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. WHEN zif_abapgit_definitions=>c_action-repo_activate_objects. " Repo activate objects zcl_abapgit_services_repo=>activate_objects( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-repo_newonline. " New online repo rs_handled-page = zcl_abapgit_gui_page_addonline=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-flow. " Flow page rs_handled-page = zcl_abapgit_gui_page_flow=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-repo_refresh_checksums. " Rebuild local checksums zcl_abapgit_services_repo=>refresh_local_checksums( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-repo_toggle_fav. " Toggle repo as favorite zcl_abapgit_services_repo=>toggle_favorite( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-repo_transport_to_branch. " Transport to branch zcl_abapgit_services_repo=>transport_to_branch( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-repo_settings. " Repo settings rs_handled-page = zcl_abapgit_gui_page_sett_repo=>create( lo_repo ). rs_handled-state = get_state_settings( ii_event ). WHEN zif_abapgit_definitions=>c_action-repo_local_settings. " Local repo settings rs_handled-page = zcl_abapgit_gui_page_sett_locl=>create( lo_repo ). rs_handled-state = get_state_settings( ii_event ). WHEN zif_abapgit_definitions=>c_action-repo_remote_settings. " Remote repo settings rs_handled-page = zcl_abapgit_gui_page_sett_remo=>create( lo_repo ). rs_handled-state = get_state_settings( ii_event ). WHEN zif_abapgit_definitions=>c_action-repo_background. " Repo background mode rs_handled-page = zcl_abapgit_gui_page_sett_bckg=>create( lo_repo ). rs_handled-state = get_state_settings( ii_event ). WHEN zif_abapgit_definitions=>c_action-repo_infos. " Repo infos rs_handled-page = zcl_abapgit_gui_page_sett_info=>create( lo_repo ). rs_handled-state = get_state_settings( ii_event ). WHEN zif_abapgit_definitions=>c_action-repo_log. " Repo log li_log = lo_repo->get_log( ). zcl_abapgit_log_viewer=>show_log( li_log ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDCASE. ENDMETHOD. METHOD sap_gui_actions. CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-jump. " Open object editor jump_object( iv_obj_type = ii_event->query( )->get( 'TYPE' ) iv_obj_name = ii_event->query( )->get( 'NAME' ) iv_filename = ii_event->query( )->get( 'FILE' ) iv_sub_type = ii_event->query( )->get( 'SUBTYPE' ) iv_sub_name = ii_event->query( )->get( 'SUBNAME' ) iv_line = ii_event->query( )->get( 'LINE' ) iv_new_window = ii_event->query( )->get( 'NEW_WINDOW' ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-jump_transaction. call_transaction( |{ ii_event->query( )->get( 'TRANSACTION' ) }| ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-jump_transport. jump_display_transport( |{ ii_event->query( )->get( 'TRANSPORT' ) }| ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-jump_user. jump_display_user( |{ ii_event->query( )->get( 'USER' ) }| ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-url. call_browser( ii_event->query( )->get( 'URL' ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. IF rs_handled-state IS INITIAL. rs_handled = general_page_routing( ii_event ). ENDIF. IF rs_handled-state IS INITIAL. rs_handled = repository_services( ii_event ). ENDIF. IF rs_handled-state IS INITIAL. rs_handled = git_services( ii_event ). ENDIF. IF rs_handled-state IS INITIAL. rs_handled = zip_services( ii_event ). ENDIF. IF rs_handled-state IS INITIAL. rs_handled = db_actions( ii_event ). ENDIF. IF rs_handled-state IS INITIAL. rs_handled = abapgit_services_actions( ii_event ). ENDIF. IF rs_handled-state IS INITIAL. rs_handled = sap_gui_actions( ii_event ). ENDIF. IF rs_handled-state IS INITIAL. rs_handled = other_utilities( ii_event ). ENDIF. IF rs_handled-state IS INITIAL. rs_handled-state = zcl_abapgit_gui=>c_event_state-not_handled. ENDIF. ENDMETHOD. METHOD zip_services. DATA: lv_key TYPE zif_abapgit_persistence=>ty_repo-key, lo_repo TYPE REF TO zcl_abapgit_repo, lv_path TYPE string, lv_dest TYPE rfcdest, lv_msg TYPE c LENGTH 200, lv_xstr TYPE xstring, lv_package TYPE zif_abapgit_persistence=>ty_repo-package, lv_folder_logic TYPE string, lv_main_lang_only TYPE zif_abapgit_persistence=>ty_local_settings-main_language_only, lo_obj_filter_trans TYPE REF TO zcl_abapgit_object_filter_tran, lt_r_trkorr TYPE zif_abapgit_definitions=>ty_trrngtrkor_tt. CONSTANTS: BEGIN OF lc_page, main_view TYPE string VALUE 'ZCL_ABAPGIT_GUI_PAGE_MAIN', repo_view TYPE string VALUE 'ZCL_ABAPGIT_GUI_PAGE_REPO_VIEW', END OF lc_page. lv_key = ii_event->query( )->get( 'KEY' ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-zip_import " Import repo from ZIP OR zif_abapgit_definitions=>c_action-rfc_compare. " Compare repo via RFC lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). IF ii_event->mv_action = zif_abapgit_definitions=>c_action-zip_import. lv_path = zcl_abapgit_ui_factory=>get_frontend_services( )->show_file_open_dialog( iv_title = 'Import ZIP' iv_extension = 'zip' iv_default_filename = '*.zip' ). lv_xstr = zcl_abapgit_ui_factory=>get_frontend_services( )->file_upload( lv_path ). ELSE. lv_dest = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'RFCDES-RFCDEST' ). IF lv_dest IS INITIAL. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. RETURN. ENDIF. lv_package = lo_repo->get_package( ). lv_folder_logic = lo_repo->get_dot_abapgit( )->get_folder_logic( ). lv_main_lang_only = lo_repo->get_local_settings( )-main_language_only. CALL FUNCTION 'Z_ABAPGIT_SERIALIZE_PACKAGE' DESTINATION lv_dest EXPORTING iv_package = lv_package iv_folder_logic = lv_folder_logic iv_main_lang_only = lv_main_lang_only IMPORTING ev_xstring = lv_xstr EXCEPTIONS system_failure = 1 MESSAGE lv_msg communication_failure = 2 MESSAGE lv_msg OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |RFC import error: { lv_msg }| ). ENDIF. ENDIF. lo_repo->set_files_remote( zcl_abapgit_zip=>load( lv_xstr ) ). zcl_abapgit_services_repo=>refresh( lv_key ). CASE ii_event->mv_current_page_name. WHEN lc_page-repo_view. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN lc_page-main_view. rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( lo_repo->get_key( ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN OTHERS. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDCASE. WHEN zif_abapgit_definitions=>c_action-zip_export. " Export repo as ZIP lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). lv_xstr = zcl_abapgit_zip=>encode_files( lo_repo->get_files_local( ) ). file_download( iv_package = lo_repo->get_package( ) iv_xstr = lv_xstr ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-zip_export_transport. " Export repo as ZIP lt_r_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_select_wb_tc_tr_and_tsk( ). lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). lo_repo->refresh( ). CREATE OBJECT lo_obj_filter_trans. lo_obj_filter_trans->set_filter_values( iv_package = lo_repo->get_package( ) it_r_trkorr = lt_r_trkorr ). lv_xstr = zcl_abapgit_zip=>encode_files( lo_repo->get_files_local_filtered( lo_obj_filter_trans ) ). lo_repo->refresh( ). file_download( iv_package = lo_repo->get_package( ) iv_xstr = lv_xstr ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-zip_package. " Export package as ZIP rs_handled-page = zcl_abapgit_gui_page_ex_pckage=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-zip_transport. " Export transports as ZIP zcl_abapgit_transport_mass=>run( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-zip_object. " Export object as ZIP rs_handled-page = zcl_abapgit_gui_page_ex_object=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-where_used. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). rs_handled-page = zcl_abapgit_gui_page_whereused=>create( ii_repo = lo_repo ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. ENDCASE. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_progress IMPLEMENTATION. METHOD calc_pct. DATA: lv_f TYPE f. lv_f = ( iv_current / mv_total ) * 100. rv_pct = lv_f. IF rv_pct = 100. rv_pct = 99. ELSEIF rv_pct = 0. rv_pct = 1. ENDIF. ENDMETHOD. METHOD get_instance. * max one progress indicator at a time is supported IF gi_progress IS INITIAL. CREATE OBJECT gi_progress TYPE zcl_abapgit_progress. ENDIF. gi_progress->set_total( iv_total ). ri_progress = gi_progress. ENDMETHOD. METHOD set_instance. gi_progress = ii_progress. ENDMETHOD. METHOD zif_abapgit_progress~off. " Clear the status bar CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'. ENDMETHOD. METHOD zif_abapgit_progress~set_total. mv_total = iv_total. CLEAR mv_cv_time_next. CLEAR mv_cv_datum_next. ENDMETHOD. METHOD zif_abapgit_progress~show. DATA: lv_pct TYPE i, lv_time TYPE t. CONSTANTS: lc_wait_secs TYPE i VALUE 2. GET TIME. lv_time = sy-uzeit. IF mv_cv_time_next IS INITIAL AND mv_cv_datum_next IS INITIAL. mv_cv_time_next = lv_time. mv_cv_datum_next = sy-datum. ENDIF. "We only do a progress indication if enough time has passed IF lv_time >= mv_cv_time_next AND sy-datum = mv_cv_datum_next OR sy-datum > mv_cv_datum_next. lv_pct = calc_pct( iv_current ). CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR' EXPORTING percentage = lv_pct text = iv_text. mv_cv_time_next = lv_time + lc_wait_secs. ENDIF. IF sy-datum > mv_cv_datum_next. mv_cv_datum_next = sy-datum. ENDIF. IF mv_cv_time_next < lv_time. mv_cv_datum_next = sy-datum + 1. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_popup_tag_list IMPLEMENTATION. METHOD create. CREATE OBJECT ri_popup TYPE zcl_abapgit_popup_tag_list EXPORTING iv_url = iv_url. ENDMETHOD. METHOD constructor. mv_repo_url = iv_url. ENDMETHOD. METHOD zif_abapgit_html_popup~create_picklist. CREATE OBJECT ro_picklist EXPORTING iv_title = 'Choose Tag' it_list = fetch_tag_list( ) ii_item_renderer = me. ENDMETHOD. METHOD fetch_tag_list. DATA lo_branches TYPE REF TO zcl_abapgit_git_branch_list. lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( mv_repo_url ). rt_tags = lo_branches->get_tags_only( ). DELETE rt_tags WHERE name CP '*' && zif_abapgit_git_definitions=>c_git_branch-peel. IF lines( rt_tags ) = 0. zcx_abapgit_exception=>raise( 'No tags are available to select' ). ENDIF. SORT rt_tags BY display_name ASCENDING. ENDMETHOD. METHOD zif_abapgit_gui_render_item~render. FIELD-SYMBOLS TYPE zif_abapgit_git_definitions=>ty_git_branch. ASSIGN iv_item TO . ASSERT sy-subrc = 0. ri_html = zcl_abapgit_html=>create( |{ -display_name }| ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_popup_pull_request IMPLEMENTATION. METHOD constructor. mv_repo_url = iv_url. ENDMETHOD. METHOD create. CREATE OBJECT ri_popup TYPE zcl_abapgit_popup_pull_request EXPORTING iv_url = iv_url. ENDMETHOD. METHOD fetch_pull_request_list. rt_pulls = zcl_abapgit_pr_enumerator=>new( mv_repo_url )->get_pulls( ). SORT rt_pulls DESCENDING BY number. IF lines( rt_pulls ) = 0. zcx_abapgit_exception=>raise( 'No pull requests found' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_render_item~render. FIELD-SYMBOLS TYPE zif_abapgit_pr_enum_provider=>ty_pull_request. ASSIGN iv_item TO . ASSERT sy-subrc = 0. ri_html = zcl_abapgit_html=>create( |{ -number } - { -title } @{ -user }| ). ENDMETHOD. METHOD zif_abapgit_html_popup~create_picklist. CREATE OBJECT ro_picklist EXPORTING iv_title = 'Choose Pull Request' it_list = fetch_pull_request_list( ) ii_item_renderer = me. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_POPUP_CODE_INSP IMPLEMENTATION. METHOD create. CREATE OBJECT ri_popup TYPE zcl_abapgit_popup_code_insp. ENDMETHOD. METHOD fetch_list. rt_list = zcl_abapgit_factory=>get_code_inspector( '$TMP' )->list_global_variants( ). ENDMETHOD. METHOD zif_abapgit_gui_render_item~render. FIELD-SYMBOLS TYPE LINE OF zif_abapgit_code_inspector=>ty_variants. ASSIGN iv_item TO . ASSERT sy-subrc = 0. ri_html = zcl_abapgit_html=>create( |{ -name } - { -description }| ). ENDMETHOD. METHOD zif_abapgit_html_popup~create_picklist. CREATE OBJECT ro_picklist EXPORTING iv_title = 'Choose Variant' it_list = fetch_list( ) ii_item_renderer = me. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_popup_branch_list IMPLEMENTATION. METHOD create. CREATE OBJECT ri_popup TYPE zcl_abapgit_popup_branch_list EXPORTING iv_url = iv_url iv_default_branch = iv_default_branch iv_show_new_option = iv_show_new_option. ENDMETHOD. METHOD constructor. mv_repo_url = iv_url. mv_default_branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && iv_default_branch. mv_show_new_option = iv_show_new_option. ENDMETHOD. METHOD zif_abapgit_html_popup~create_picklist. CREATE OBJECT ro_picklist EXPORTING iv_title = 'Choose Branch' it_list = fetch_branch_list( ) ii_item_renderer = me. ENDMETHOD. METHOD fetch_branch_list. DATA lo_branches TYPE REF TO zcl_abapgit_git_branch_list. DATA lv_head_symref TYPE string. FIELD-SYMBOLS LIKE LINE OF rt_branches. lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( mv_repo_url ). rt_branches = lo_branches->get_branches_only( ). lv_head_symref = lo_branches->get_head_symref( ). IF rt_branches IS INITIAL. zcx_abapgit_exception=>raise( 'No branches are available to select' ). ENDIF. " Clean up branches: HEAD duplicates, empty names LOOP AT rt_branches ASSIGNING . IF -name IS INITIAL. DELETE rt_branches INDEX sy-tabix. ELSEIF -is_head = abap_true AND lv_head_symref IS NOT INITIAL AND -name <> lv_head_symref. DELETE rt_branches INDEX sy-tabix. ENDIF. ENDLOOP. SORT rt_branches BY is_head DESCENDING display_name ASCENDING. IF mv_show_new_option = abap_true. APPEND INITIAL LINE TO rt_branches ASSIGNING . -name = zif_abapgit_popups=>c_new_branch_label. -display_name = zif_abapgit_popups=>c_new_branch_label. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_render_item~render. DATA lv_head_marker TYPE string. FIELD-SYMBOLS TYPE zif_abapgit_git_definitions=>ty_git_branch. ASSIGN iv_item TO . ASSERT sy-subrc = 0. " TODO render mv_default_branch properly, needs respecting support from the picklist components IF -is_head = abap_true. lv_head_marker = | ({ zif_abapgit_git_definitions=>c_head_name })|. ENDIF. ri_html = zcl_abapgit_html=>create( |{ -display_name }{ lv_head_marker }| ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_tutorial IMPLEMENTATION. METHOD build_main_menu. CREATE OBJECT ro_menu EXPORTING iv_id = 'toolbar-main'. ro_menu->add( iv_txt = zcl_abapgit_gui_buttons=>repo_list( ) iv_act = zif_abapgit_definitions=>c_action-abapgit_home )->add( iv_txt = zcl_abapgit_gui_buttons=>new_online( ) iv_act = zif_abapgit_definitions=>c_action-repo_newonline )->add( iv_txt = zcl_abapgit_gui_buttons=>new_offline( ) iv_act = zif_abapgit_definitions=>c_action-repo_newoffline )->add( iv_txt = zcl_abapgit_gui_buttons=>help( ) io_sub = zcl_abapgit_gui_menus=>help( ) ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_tutorial. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Tutorial' io_page_menu = build_main_menu( ) ii_child_component = lo_component ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( '

Tutorial

' ). ri_html->add( '
' ). ri_html->add( '

Online repositories

' ). ri_html->add( '

    ' ). ri_html->add( `
  • To clone a remote repository (e.g. from github) click ` ). ri_html->add_a( iv_txt = zcl_abapgit_gui_buttons=>new_online( ) iv_act = zif_abapgit_definitions=>c_action-repo_newonline ). ri_html->add( ' from the top menu. This will link a remote repository with a package on your system.
  • ' ). ri_html->add( '
  • Use the pull button to retrieve and activate the remote objects.
  • ' ). ri_html->add( '
  • If the remote repository is updated,' ). ri_html->add( ' you will see the changes and can pull to apply the updates.
  • ' ). ri_html->add( '

' ). ri_html->add( '

Offline repositories

' ). ri_html->add( '

    ' ). ri_html->add( `
  • To add a package as an offline repository, click ` ). ri_html->add_a( iv_txt = zcl_abapgit_gui_buttons=>new_offline( ) iv_act = zif_abapgit_definitions=>c_action-repo_newoffline ). ri_html->add( ' from the top menu.' ). ri_html->add( '
  • abapGit will start tracking changes for the package ' ). ri_html->add( 'without linking it to an online git repository.
  • ' ). ri_html->add( '
  • You can link the package later or just export the package content as a ZIP file.
  • ' ). ri_html->add( '

' ). ri_html->add( '

' ). ri_html->add( '

Repository list and favorites

' ). ri_html->add( '

    ' ). ri_html->add( |
  • To favorite a repository, use the { ri_html->icon( 'star/darkgrey' ) } icon in the repository list.
  • | ). ri_html->add( |
  • To go to a repository, click on the repository name.
  • | ). ri_html->add( |
  • To go back to your favorites, use the| ). ri_html->add_a( iv_txt = zcl_abapgit_gui_buttons=>repo_list( ) iv_act = zif_abapgit_definitions=>c_action-abapgit_home ). ri_html->add( |
  • | ). ri_html->add( `
  • ` ). ri_html->add_a( iv_txt = 'Explore' iv_act = zif_abapgit_definitions=>c_action-go_explore ). ri_html->add( ' to find projects using abapGit
  • ' ). ri_html->add( '

' ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_tags IMPLEMENTATION. METHOD choose_commit. DATA li_popups TYPE REF TO zif_abapgit_popups. li_popups = zcl_abapgit_ui_factory=>get_popups( ). rv_commit = li_popups->commit_list_popup( iv_repo_url = mo_repo->get_url( ) iv_branch_name = mo_repo->get_selected_branch( ) )-sha1. ENDMETHOD. METHOD constructor. super->constructor( ). CREATE OBJECT mo_form_data. CREATE OBJECT mo_validation_log. mo_repo ?= ii_repo. " Get settings from DB mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). mo_form = get_form_schema( ). initialize_form_data( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_tags. CREATE OBJECT lo_component EXPORTING ii_repo = ii_repo. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Create Tag' ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. CONSTANTS lc_commitmsg_comment_min_len TYPE i VALUE 1. CONSTANTS lc_commitmsg_comment_max_len TYPE i VALUE 255. IF io_form_data IS BOUND AND io_form_data->is_empty( ) = abap_false. ms_tag-type = io_form_data->get( c_id-tag_type ). ENDIF. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'create-tag-form' iv_help_page = 'https://docs.abapgit.org/' ). " todo, add docs ro_form->start_group( iv_name = c_id-tag_group iv_label = 'New Tag' )->radio( iv_label = 'Type' iv_name = c_id-tag_type iv_action = c_event-change_type )->option( iv_label = 'Lightweight' iv_value = zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag )->option( iv_label = 'Annotated' iv_value = zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag )->text( iv_name = c_id-name iv_label = 'Tag Name' iv_required = abap_true )->text( iv_name = c_id-sha1 iv_label = 'Commit' iv_min = 40 iv_max = 40 iv_condense = abap_true iv_required = abap_true iv_side_action = c_event-choose_commit ). IF ms_tag-type = zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. ro_form->start_group( iv_name = c_id-anno_group iv_label = 'Annotation' )->text( iv_name = c_id-message iv_label = 'Comment' iv_min = lc_commitmsg_comment_min_len iv_max = lc_commitmsg_comment_max_len iv_placeholder = |Add a mandatory comment with max { lc_commitmsg_comment_max_len } characters| )->textarea( iv_name = c_id-body iv_label = 'Body' iv_rows = 6 iv_cols = mo_settings->get_commitmsg_body_size( ) iv_placeholder = 'Add an optional description...' )->text( iv_name = c_id-tagger_name iv_label = 'Tagger Name' )->text( iv_name = c_id-tagger_email iv_label = 'Tagger Email' ). ELSE. ro_form->hidden( c_id-message )->hidden( c_id-body )->hidden( c_id-tagger_name )->hidden( c_id-tagger_email ). ENDIF. ro_form->command( iv_label = 'Create' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-create )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD get_tagger_email. DATA li_user TYPE REF TO zif_abapgit_persist_user. li_user = zcl_abapgit_persistence_user=>get_instance( ). rv_email = li_user->get_repo_git_user_email( mo_repo->get_url( ) ). IF rv_email IS INITIAL. rv_email = li_user->get_default_git_user_email( ). ENDIF. IF rv_email IS INITIAL. " get default from user record rv_email = zcl_abapgit_user_record=>get_instance( sy-uname )->get_email( ). ENDIF. ENDMETHOD. METHOD get_tagger_name. DATA li_user TYPE REF TO zif_abapgit_persist_user. li_user = zcl_abapgit_persistence_user=>get_instance( ). rv_user = li_user->get_repo_git_user_name( mo_repo->get_url( ) ). IF rv_user IS INITIAL. rv_user = li_user->get_default_git_user_name( ). ENDIF. IF rv_user IS INITIAL. " get default from user record rv_user = zcl_abapgit_user_record=>get_instance( sy-uname )->get_name( ). ENDIF. ENDMETHOD. METHOD initialize_form_data. ms_tag-type = zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. mo_form_data->set( iv_key = c_id-tag_type iv_val = ms_tag-type ). ms_tag-tagger_name = get_tagger_name( ). ms_tag-tagger_email = get_tagger_email( ). mo_form_data->set( iv_key = c_id-tagger_name iv_val = ms_tag-tagger_name ). mo_form_data->set( iv_key = c_id-tagger_email iv_val = ms_tag-tagger_email ). ENDMETHOD. METHOD validate_form. DATA: lt_tags TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, lv_new_tag_name TYPE string. ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-tagger_email ) ) = abap_false. ro_validation_log->set( iv_key = c_id-tagger_email iv_val = |Invalid email address| ). ENDIF. lv_new_tag_name = io_form_data->get( c_id-name ). IF lv_new_tag_name IS NOT INITIAL. " Check if tag already exists lt_tags = zcl_abapgit_git_factory=>get_git_transport( )->branches( mo_repo->get_url( ) )->get_tags_only( ). READ TABLE lt_tags TRANSPORTING NO FIELDS WITH TABLE KEY name_key COMPONENTS name = zcl_abapgit_git_tag=>add_tag_prefix( lv_new_tag_name ). IF sy-subrc = 0. ro_validation_log->set( iv_key = c_id-name iv_val = |Tag already exists| ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA: lx_error TYPE REF TO zcx_abapgit_exception, lv_commit TYPE zif_abapgit_git_definitions=>ty_sha1, lv_text TYPE string. mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). CASE ii_event->mv_action. WHEN c_event-choose_commit. lv_commit = choose_commit( ). IF lv_commit IS INITIAL. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ELSE. mo_form_data->set( iv_key = c_id-sha1 iv_val = lv_commit ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. WHEN c_event-change_type. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. mo_validation_log->clear( ). WHEN c_event-create. " Validate form entries before creating tag mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. mo_form_data->strict( abap_false ). mo_form_data->to_abap( CHANGING cs_container = ms_tag ). REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN ms_tag-body WITH cl_abap_char_utilities=>newline. ms_tag-name = zcl_abapgit_git_tag=>add_tag_prefix( ms_tag-name ). ASSERT ms_tag-name CP zif_abapgit_git_definitions=>c_git_branch-tags. TRY. zcl_abapgit_git_porcelain=>create_tag( iv_url = mo_repo->get_url( ) is_tag = ms_tag ). CATCH zcx_abapgit_exception INTO lx_error. zcx_abapgit_exception=>raise( |Cannot create tag { ms_tag-name }: { lx_error->get_text( ) }| ). ENDTRY. lv_text = |Tag { zcl_abapgit_git_tag=>remove_tag_prefix( ms_tag-name ) } created|. MESSAGE lv_text TYPE 'S'. rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. ENDCASE. " If staying on form, initialize it with current settings IF rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. mo_form = get_form_schema( mo_form_data ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( `
` ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false iv_interactive_branch = abap_false ) ). ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( `
` ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_STAGE IMPLEMENTATION. METHOD check_selected. DATA: ls_file TYPE zif_abapgit_git_definitions=>ty_file, lv_pattern TYPE string, lv_msg TYPE string. FIELD-SYMBOLS: LIKE LINE OF io_files->mt_entries, LIKE LINE OF io_files->mt_entries. " Check all added files if the exist in different paths (packages) without being removed LOOP AT io_files->mt_entries ASSIGNING WHERE v = zif_abapgit_definitions=>c_method-add. zcl_abapgit_path=>split_file_location( EXPORTING iv_fullpath = to_lower( -k ) IMPORTING ev_path = ls_file-path ev_filename = ls_file-filename ). " Skip packages since they all have identical filenames IF ls_file-filename <> 'package.devc.xml'. lv_pattern = '*/' && to_upper( ls_file-filename ). REPLACE ALL OCCURRENCES OF '#' IN lv_pattern WITH '##'. " for CP LOOP AT io_files->mt_entries ASSIGNING WHERE k CP lv_pattern AND k <> -k AND v <> zif_abapgit_definitions=>c_method-rm. lv_msg = |In order to add { to_lower( -k ) }, | && |you have to remove { to_lower( -k ) }|. zcx_abapgit_exception=>raise( lv_msg ). ENDLOOP. ENDIF. ENDLOOP. ENDMETHOD. METHOD constructor. DATA lv_ts TYPE timestamp. super->constructor( ). " force refresh on stage, to make sure the latest local and remote files are used IF ii_force_refresh = abap_true. io_repo->refresh( ). ENDIF. mo_repo = io_repo. mv_seed = iv_seed. mv_sci_result = iv_sci_result. mi_obj_filter = ii_obj_filter. IF mv_seed IS INITIAL. " Generate based on time unless obtained from diff page GET TIME STAMP FIELD lv_ts. mv_seed = |stage{ lv_ts }|. ENDIF. init_files( ). ENDMETHOD. METHOD count_default_files_to_commit. FIELD-SYMBOLS LIKE LINE OF ms_files-status. FIELD-SYMBOLS LIKE LINE OF ms_files-remote. rv_count = lines( ms_files-local ). LOOP AT ms_files-remote ASSIGNING . READ TABLE ms_files-status ASSIGNING WITH TABLE KEY path = -path filename = -filename. ASSERT sy-subrc = 0. IF -lstate = zif_abapgit_definitions=>c_state-deleted AND -rstate = zif_abapgit_definitions=>c_state-unchanged. rv_count = rv_count + 1. ENDIF. ENDLOOP. ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_stage. CREATE OBJECT lo_component EXPORTING io_repo = io_repo iv_seed = iv_seed iv_sci_result = iv_sci_result ii_force_refresh = ii_force_refresh ii_obj_filter = ii_obj_filter. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Stage' ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD find_changed_by. DATA: ls_local LIKE LINE OF it_files-local, ls_remote LIKE LINE OF it_files-remote, ls_changed_by LIKE LINE OF rt_changed_by, lt_changed_by_remote LIKE rt_changed_by, ls_item TYPE zif_abapgit_definitions=>ty_item, lv_transport LIKE LINE OF it_transports, lv_user TYPE uname. FIELD-SYMBOLS LIKE LINE OF lt_changed_by_remote. LOOP AT it_files-local INTO ls_local WHERE NOT item IS INITIAL. ls_changed_by-item = ls_local-item. ls_changed_by-filename = ls_local-file-filename. ls_changed_by-name = zcl_abapgit_objects=>changed_by( is_item = ls_local-item iv_filename = ls_local-file-filename ). INSERT ls_changed_by INTO TABLE rt_changed_by. ENDLOOP. LOOP AT it_files-remote INTO ls_remote WHERE filename IS NOT INITIAL. TRY. zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = ls_remote-filename iv_path = ls_remote-path io_dot = mo_repo->get_dot_abapgit( ) IMPORTING es_item = ls_item ). ls_changed_by-item = ls_item. INSERT ls_changed_by INTO TABLE lt_changed_by_remote. CATCH zcx_abapgit_exception. ENDTRY. ENDLOOP. LOOP AT lt_changed_by_remote ASSIGNING . " deleted files might still be in a transport CLEAR lv_transport. READ TABLE it_transports WITH KEY obj_type = -item-obj_type obj_name = -item-obj_name INTO lv_transport. IF sy-subrc = 0. lv_user = zcl_abapgit_factory=>get_cts_api( )->read_user( lv_transport-trkorr ). IF lv_user IS NOT INITIAL. -name = lv_user. ENDIF. ENDIF. IF -name IS INITIAL. -name = zcl_abapgit_objects_super=>c_user_unknown. ENDIF. ENDLOOP. INSERT LINES OF lt_changed_by_remote INTO TABLE rt_changed_by. ENDMETHOD. METHOD find_transports. DATA li_cts_api TYPE REF TO zif_abapgit_cts_api. DATA lt_items TYPE zif_abapgit_definitions=>ty_items_tt. DATA ls_item TYPE zif_abapgit_definitions=>ty_item. DATA lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. FIELD-SYMBOLS LIKE LINE OF it_files-local. FIELD-SYMBOLS LIKE LINE OF it_files-remote. li_cts_api = zcl_abapgit_factory=>get_cts_api( ). TRY. LOOP AT it_files-local ASSIGNING WHERE item IS NOT INITIAL. IF li_cts_api->is_chrec_possible_for_package( -item-devclass ) = abap_false. RETURN. " Assume all other objects are also in packages without change recording ENDIF. APPEND -item TO lt_items. ENDLOOP. lo_dot = mo_repo->get_dot_abapgit( ). LOOP AT it_files-remote ASSIGNING WHERE filename IS NOT INITIAL. zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = -filename iv_path = -path io_dot = lo_dot IMPORTING es_item = ls_item ). IF ls_item IS INITIAL. CONTINUE. ENDIF. APPEND ls_item TO lt_items. ENDLOOP. SORT lt_items BY obj_type obj_name. DELETE ADJACENT DUPLICATES FROM lt_items COMPARING obj_type obj_name. rt_transports = li_cts_api->get_transports_for_list( lt_items ). CATCH zcx_abapgit_exception. ENDTRY. ENDMETHOD. METHOD get_page_patch. DATA: lv_key TYPE zif_abapgit_persistence=>ty_repo-key, lt_files TYPE zif_abapgit_definitions=>ty_stage_tt. lv_key = mo_repo->get_key( ). lt_files = io_stage->get_all( ). DELETE lt_files WHERE method <> zif_abapgit_definitions=>c_method-add AND method <> zif_abapgit_definitions=>c_method-rm. ri_page = zcl_abapgit_gui_page_patch=>create( iv_key = lv_key it_files = lt_files ). ENDMETHOD. METHOD init_files. ms_files = zcl_abapgit_factory=>get_stage_logic( )->get( io_repo = mo_repo ii_obj_filter = mi_obj_filter ). IF lines( ms_files-local ) = 0 AND lines( ms_files-remote ) = 0. mo_repo->refresh( ). zcx_abapgit_exception=>raise( 'There are no changes that could be staged' ). ENDIF. ENDMETHOD. METHOD render_actions. DATA: lv_local_count TYPE i, lv_add_all_txt TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. lv_local_count = count_default_files_to_commit( ). IF lv_local_count > 0. lv_add_all_txt = |Add All and Commit ({ lv_local_count })|. " Otherwise empty, but the element (id) is preserved for JS ENDIF. ri_html->add( '' ). " Action buttons ri_html->add( '' ). " Filter bar ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '
' ). ri_html->add_a( iv_act = 'errorStub(event)' " Will be reinit by JS iv_typ = zif_abapgit_html=>c_action_type-onclick iv_id = 'commitSelectedButton' iv_style = 'display: none' iv_txt = 'Commit Selected ()' iv_opt = zif_abapgit_html=>c_html_opt-strong ). ri_html->add_a( iv_act = 'errorStub(event)' " Will be reinit by JS iv_typ = zif_abapgit_html=>c_action_type-onclick iv_id = 'commitFilteredButton' iv_style = 'display: none' iv_txt = 'Add Filtered and Commit ()' ). ri_html->add_a( iv_act = |{ c_action-stage_all }| iv_id = 'commitAllButton' iv_txt = lv_add_all_txt ). ri_html->add( '' ). ri_html->add( '| ). zcl_abapgit_gui_chunk_lib=>render_sci_result( ii_html = ri_html iv_sci_result = mv_sci_result ). ri_html->add( '
' ). ENDMETHOD. METHOD render_deferred_hidden_events. DATA ls_event TYPE zcl_abapgit_gui_chunk_lib=>ty_event_signature. ls_event-method = 'post'. ls_event-name = 'stage_commit'. ri_html = zcl_abapgit_gui_chunk_lib=>render_event_as_form( ls_event ). ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). ENDMETHOD. METHOD render_file. DATA: lv_param TYPE string, lv_filename TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. lv_filename = is_file-path && is_file-filename. " make sure whitespace is preserved in the DOM REPLACE ALL OCCURRENCES OF ` ` IN lv_filename WITH ' '. ri_html->add( || ). ri_html->add( '' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = is_status-lstate iv_rstate = is_status-rstate ) ). ri_html->add( '' ). CASE iv_context. WHEN 'local'. lv_param = zcl_abapgit_html_action_utils=>file_encode( iv_key = mo_repo->get_key( ) ig_file = is_file ). lv_filename = ri_html->a( iv_txt = lv_filename iv_act = |{ zif_abapgit_definitions=>c_action-go_file_diff }?{ lv_param }| ). ri_html->add( |{ is_item-obj_type }| ). ri_html->add( |{ lv_filename }| ). WHEN 'remote'. ri_html->add( |{ is_item-obj_type }| ). ri_html->add( |{ lv_filename }| ). ENDCASE. ri_html->add( '' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name( iv_changed_by ) ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_transport( iv_transport ) ). ri_html->add( '' ). ri_html->add( '?' ). ri_html->add( '' ). " Command added in JS ri_html->add( '' ). ENDMETHOD. METHOD render_list. DATA: lt_changed_by TYPE ty_changed_by_tt, ls_changed_by LIKE LINE OF lt_changed_by, lt_transports TYPE zif_abapgit_cts_api=>ty_transport_list, ls_transport LIKE LINE OF lt_transports, ls_item_remote TYPE zif_abapgit_definitions=>ty_item. FIELD-SYMBOLS: LIKE LINE OF ms_files-remote, LIKE LINE OF ms_files-status, LIKE LINE OF ms_files-local. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). lt_transports = find_transports( ms_files ). lt_changed_by = find_changed_by( it_files = ms_files it_transports = lt_transports ). " Local changes LOOP AT ms_files-local ASSIGNING . AT FIRST. ri_html->add( '' ). ri_html->add( '' ). " Diff state ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). " Status ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ENDAT. READ TABLE lt_changed_by INTO ls_changed_by WITH TABLE KEY item = -item filename = -file-filename. IF sy-subrc <> 0. READ TABLE lt_changed_by INTO ls_changed_by WITH KEY item = -item. ENDIF. READ TABLE lt_transports INTO ls_transport WITH KEY obj_type = -item-obj_type obj_name = -item-obj_name. "#EC CI_SUBRC READ TABLE ms_files-status ASSIGNING WITH TABLE KEY path = -file-path filename = -file-filename. ASSERT sy-subrc = 0. ri_html->add( render_file( iv_context = 'local' is_file = -file is_item = -item is_status = iv_changed_by = ls_changed_by-name iv_transport = ls_transport-trkorr ) ). CLEAR ls_transport. AT LAST. ri_html->add( '' ). ENDAT. ENDLOOP. " Remote changes LOOP AT ms_files-remote ASSIGNING . AT FIRST. ri_html->add( '' ). ri_html->add( '' ). " Diff state ri_html->add( '' ). " Type ri_html->add( '' ). ri_html->add( '' ). " Transport ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ENDAT. READ TABLE ms_files-status ASSIGNING WITH TABLE KEY path = -path filename = -filename. ASSERT sy-subrc = 0. TRY. zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = -filename iv_path = -path io_dot = mo_repo->get_dot_abapgit( ) IMPORTING es_item = ls_item_remote ). READ TABLE lt_transports INTO ls_transport WITH KEY obj_type = ls_item_remote-obj_type obj_name = ls_item_remote-obj_name. READ TABLE lt_changed_by INTO ls_changed_by WITH TABLE KEY item = ls_item_remote filename = -filename. IF sy-subrc <> 0. READ TABLE lt_changed_by INTO ls_changed_by WITH KEY item = ls_item_remote. ENDIF. CATCH zcx_abapgit_exception. CLEAR ls_transport. ENDTRY. ri_html->add( render_file( iv_context = 'remote' is_status = is_file = is_item = ls_item_remote iv_changed_by = ls_changed_by-name iv_transport = ls_transport-trkorr ) ). AT LAST. ri_html->add( '' ). ENDAT. ENDLOOP. ri_html->add( '
TypeFileChanged byTransport' ). ri_html->add( 'addreset↓' ). ri_html->add( '
Files to remove or non-code' ). ri_html->add( 'ignoreremovereset↓' ). ri_html->add( '
' ). ENDMETHOD. METHOD render_main_language_warning. DATA lv_main_language TYPE spras. CREATE OBJECT ri_html TYPE zcl_abapgit_html. lv_main_language = mo_repo->get_dot_abapgit( )->get_main_language( ). IF lv_main_language <> sy-langu. ri_html->add( zcl_abapgit_gui_chunk_lib=>render_warning_banner( |Caution: Main language of the repo is '{ lv_main_language }', | && |but you're logged on in '{ sy-langu }'| ) ). ENDIF. ENDMETHOD. METHOD render_scripts. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). ri_html->add( 'var gStageParams = {' ). ri_html->add( | seed: "{ mv_seed }",| ). " Unique page id ri_html->add( | user: "{ to_lower( sy-uname ) }",| ). ri_html->add( ' formAction: "stage_commit",' ). ri_html->add( | patchAction: "{ zif_abapgit_definitions=>c_action-go_patch }",| ). ri_html->add( ' focusFilterKey: "f",' ). ri_html->add( ' ids: {' ). ri_html->add( ' stageTab: "stageTab",' ). ri_html->add( ' commitAllBtn: "commitAllButton",' ). ri_html->add( ' commitSelectedBtn: "commitSelectedButton",' ). ri_html->add( ' commitFilteredBtn: "commitFilteredButton",' ). ri_html->add( ' patchBtn: "patchBtn",' ). ri_html->add( ' objectSearch: "objectSearch",' ). ri_html->add( ' }' ). ri_html->add( '}' ). ri_html->add( 'var gHelper = new StageHelper(gStageParams);' ). ENDMETHOD. METHOD stage_all. FIELD-SYMBOLS LIKE LINE OF ms_files-local. FIELD-SYMBOLS LIKE LINE OF ms_files-remote. FIELD-SYMBOLS LIKE LINE OF ms_files-status. CREATE OBJECT ro_stage. LOOP AT ms_files-local ASSIGNING . READ TABLE ms_files-status ASSIGNING WITH TABLE KEY path = -file-path filename = -file-filename. ASSERT sy-subrc = 0. ro_stage->add( iv_path = -file-path iv_filename = -file-filename is_status = iv_data = -file-data ). ENDLOOP. LOOP AT ms_files-remote ASSIGNING . READ TABLE ms_files-status ASSIGNING WITH TABLE KEY path = -path filename = -filename. ASSERT sy-subrc = 0. IF -lstate = zif_abapgit_definitions=>c_state-deleted AND -rstate = zif_abapgit_definitions=>c_state-unchanged. ro_stage->rm( iv_path = -path iv_filename = -filename is_status = ). ENDIF. ENDLOOP. ENDMETHOD. METHOD stage_selected. DATA ls_file TYPE zif_abapgit_git_definitions=>ty_file. DATA lo_files TYPE REF TO zcl_abapgit_string_map. FIELD-SYMBOLS: LIKE LINE OF ms_files-local, LIKE LINE OF ms_files-status, LIKE LINE OF lo_files->mt_entries. lo_files = ii_event->form_data( ). IF lo_files->size( ) = 0. zcx_abapgit_exception=>raise( 'process_stage_list: empty list' ). ENDIF. check_selected( lo_files ). CREATE OBJECT ro_stage. LOOP AT lo_files->mt_entries ASSIGNING "Ignore Files that we don't want to stage, so any errors don't stop the staging process WHERE v <> zif_abapgit_definitions=>c_method-skip. zcl_abapgit_path=>split_file_location( EXPORTING iv_fullpath = to_lower( -k ) " filename is lower cased IMPORTING ev_path = ls_file-path ev_filename = ls_file-filename ). READ TABLE ms_files-status ASSIGNING WITH TABLE KEY path = ls_file-path filename = ls_file-filename. IF sy-subrc <> 0. * see https://github.com/abapGit/abapGit/issues/3073 zcx_abapgit_exception=>raise( |Unable to stage { ls_file-filename }. If the filename contains spaces, this is a known issue.| && | Consider ignoring or staging the file at a later time.| ). ENDIF. CASE -v. WHEN zif_abapgit_definitions=>c_method-add. READ TABLE ms_files-local ASSIGNING WITH KEY file-path = ls_file-path file-filename = ls_file-filename. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |process_stage_list: unknown file { ls_file-path }{ ls_file-filename }| ). ENDIF. ro_stage->add( iv_path = -file-path iv_filename = -file-filename is_status = iv_data = -file-data ). WHEN zif_abapgit_definitions=>c_method-ignore. ro_stage->ignore( iv_path = ls_file-path iv_filename = ls_file-filename ). WHEN zif_abapgit_definitions=>c_method-rm. ro_stage->rm( iv_path = ls_file-path is_status = iv_filename = ls_file-filename ). WHEN zif_abapgit_definitions=>c_method-skip. " Do nothing WHEN OTHERS. zcx_abapgit_exception=>raise( |process_stage_list: unknown method { -v }| ). ENDCASE. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA: lo_stage TYPE REF TO zcl_abapgit_stage. CASE ii_event->mv_action. WHEN c_action-stage_all. lo_stage = stage_all( ). rs_handled-page = zcl_abapgit_gui_page_commit=>create( io_repo = mo_repo io_stage = lo_stage iv_sci_result = mv_sci_result ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN c_action-stage_commit. lo_stage = stage_selected( ii_event ). rs_handled-page = zcl_abapgit_gui_page_commit=>create( io_repo = mo_repo io_stage = lo_stage iv_sci_result = mv_sci_result ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN c_action-stage_filter. mv_filter_value = ii_event->form_data( )->get( 'filterValue' ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-go_patch. " Go Patch page lo_stage = stage_selected( ii_event ). rs_handled-page = get_page_patch( lo_stage ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN c_action-stage_refresh. mo_repo->refresh( abap_true ). init_files( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-git_branch_switch. zcl_abapgit_services_git=>switch_branch( |{ ii_event->query( )->get( 'KEY' ) }| ). mo_repo->refresh( abap_true ). init_files( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA ls_hotkey_action LIKE LINE OF rt_hotkey_actions. ls_hotkey_action-ui_component = 'Stage'. ls_hotkey_action-description = |Patch|. ls_hotkey_action-action = 'submitPatch'. " JS function in StageHelper ls_hotkey_action-hotkey = |p|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Diff|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_repo_diff. ls_hotkey_action-hotkey = |d|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Refresh|. ls_hotkey_action-action = c_action-stage_refresh. ls_hotkey_action-hotkey = |r|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. " registered/handled in js ls_hotkey_action-description = |Focus filter|. ls_hotkey_action-action = `#`. ls_hotkey_action-hotkey = |f|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar EXPORTING iv_id = 'toolbar-main'. IF lines( ms_files-local ) > 0 OR lines( ms_files-remote ) > 0. ro_toolbar->add( iv_txt = 'Refresh' iv_act = |{ c_action-stage_refresh }| iv_opt = zif_abapgit_html=>c_html_opt-strong )->add( iv_txt = |Diff| iv_act = |{ zif_abapgit_definitions=>c_action-go_repo_diff }?key={ mo_repo->get_key( ) }| )->add( iv_txt = |Patch| iv_typ = zif_abapgit_html=>c_action_type-onclick iv_id = |patchBtn| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_interactive_branch = abap_true ) ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_js_error_banner( ) ). ri_html->add( render_main_language_warning( ) ). ri_html->add( '
' ). ri_html->add( render_actions( ) ). ri_html->add( render_list( ) ). ri_html->add( '
' ). ri_html->add( '
' ). gui_services( )->get_html_parts( )->add_part( iv_collection = zcl_abapgit_gui_component=>c_html_parts-hidden_forms ii_part = render_deferred_hidden_events( ) ). register_deferred_script( render_scripts( ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_run_bckg IMPLEMENTATION. METHOD constructor. super->constructor( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_run_bckg. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Background Run' io_page_menu = zcl_abapgit_gui_menus=>back( ) ii_child_component = lo_component ). ENDMETHOD. METHOD run. DATA: lx_error TYPE REF TO zcx_abapgit_exception, lv_text TYPE string, lv_line TYPE i VALUE 1. TRY. zcl_abapgit_background=>run( ). DO. READ LINE lv_line LINE VALUE INTO lv_text. IF sy-subrc <> 0. EXIT. ENDIF. APPEND lv_text TO mt_text. lv_line = lv_line + 1. ENDDO. CATCH zcx_abapgit_exception INTO lx_error. APPEND lx_error->get_text( ) TO mt_text. ENDTRY. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA: lv_text LIKE LINE OF mt_text. register_handlers( ). run( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). LOOP AT mt_text INTO lv_text. ri_html->add( '
' && lv_text && '

' ). ENDLOOP. ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_REPO_VIEW IMPLEMENTATION. METHOD apply_order_by. DATA: lt_sort TYPE abap_sortorder_tab, ls_sort LIKE LINE OF lt_sort, lt_non_code_and_metadata_items LIKE ct_repo_items, lt_code_items LIKE ct_repo_items, lt_diff_items LIKE ct_repo_items. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_repo_item. IF mv_order_by IS INITIAL. RETURN. ENDIF. " we want to preserve non-code and metadata files at the top, " so we isolate them and sort only the code artifacts LOOP AT ct_repo_items ASSIGNING . IF -obj_type IS INITIAL AND -is_dir = abap_false. INSERT INTO TABLE lt_non_code_and_metadata_items. ELSE. INSERT INTO TABLE lt_code_items. ENDIF. ENDLOOP. IF mv_diff_first = abap_true. " fix diffs on the top, right after non-code and metadata LOOP AT lt_code_items ASSIGNING WHERE changes > 0. INSERT INTO TABLE lt_diff_items. ENDLOOP. DELETE lt_code_items WHERE changes > 0. ENDIF. CLEAR: ct_repo_items. ls_sort-descending = mv_order_descending. ls_sort-astext = abap_true. ls_sort-name = mv_order_by. INSERT ls_sort INTO TABLE lt_sort. " Combine state fields for order of 'Status' column IF mv_order_by = 'LSTATE'. ls_sort-name = 'RSTATE'. INSERT ls_sort INTO TABLE lt_sort. ENDIF. " Use object name as secondary sort criteria IF mv_order_by <> 'OBJ_NAME'. ls_sort-name = 'OBJ_NAME'. INSERT ls_sort INTO TABLE lt_sort. ENDIF. SORT lt_code_items STABLE BY (lt_sort). SORT lt_diff_items STABLE BY (lt_sort). INSERT LINES OF lt_non_code_and_metadata_items INTO TABLE ct_repo_items. INSERT LINES OF lt_diff_items INTO TABLE ct_repo_items. INSERT LINES OF lt_code_items INTO TABLE ct_repo_items. " Files are listed under the object names so we always sort them by name LOOP AT ct_repo_items ASSIGNING . order_files( CHANGING ct_files = -files ). ENDLOOP. ENDMETHOD. METHOD build_advanced_dropdown. CREATE OBJECT ro_advanced_dropdown. ro_advanced_dropdown->add( iv_txt = 'Activate Objects' iv_act = |{ zif_abapgit_definitions=>c_action-repo_activate_objects }?key={ mv_key }| ). IF mo_repo->is_offline( ) = abap_false. " Online ? ro_advanced_dropdown->add( iv_txt = 'Transport to Branch' iv_act = |{ zif_abapgit_definitions=>c_action-repo_transport_to_branch }?key={ mv_key }| iv_opt = get_crossout( zif_abapgit_auth=>c_authorization-transport_to_branch ) ). ENDIF. IF mv_are_changes_recorded_in_tr = abap_true. ro_advanced_dropdown->add( iv_txt = 'Add All Objects to Transport' iv_act = |{ zif_abapgit_definitions=>c_action-repo_add_all_obj_to_trans_req }?key={ mv_key }| ). ENDIF. IF mo_repo->is_offline( ) = abap_true. ro_advanced_dropdown->add( iv_txt = 'Export by Transport' iv_act = |{ zif_abapgit_definitions=>c_action-zip_export_transport }?key={ mv_key }| ). ELSE. ro_advanced_dropdown->add( iv_txt = 'Stage by Transport' iv_act = |{ zif_abapgit_definitions=>c_action-go_stage_transport }?key={ mv_key }| ). ENDIF. ro_advanced_dropdown->add( iv_txt = 'Quality Assurance' iv_typ = zif_abapgit_html=>c_action_type-separator ). ro_advanced_dropdown->add( iv_txt = 'Syntax Check' iv_act = |{ zif_abapgit_definitions=>c_action-repo_syntax_check }?key={ mv_key }| ). ro_advanced_dropdown->add( iv_txt = 'Unit Test' iv_act = |{ c_actions-go_unit }| ). ro_advanced_dropdown->add( iv_txt = 'Run Code Inspector' iv_act = |{ zif_abapgit_definitions=>c_action-repo_code_inspector }?key={ mv_key }| ). ro_advanced_dropdown->add( iv_txt = 'Where Used' iv_act = |{ zif_abapgit_definitions=>c_action-where_used }?key={ mv_key }| ). ro_advanced_dropdown->add( iv_txt = 'Very Advanced' iv_typ = zif_abapgit_html=>c_action_type-separator ). ro_advanced_dropdown->add( iv_txt = 'Update Local Checksums' iv_act = |{ zif_abapgit_definitions=>c_action-repo_refresh_checksums }?key={ mv_key }| iv_opt = get_crossout( zif_abapgit_auth=>c_authorization-update_local_checksum ) ). ro_advanced_dropdown->add( iv_txt = 'Data Config' iv_act = |{ c_actions-go_data }?key={ mv_key }| ). IF is_repo_lang_logon_lang( ) = abap_false AND zcl_abapgit_services_abapgit=>get_abapgit_tcode( ) IS NOT INITIAL. ro_advanced_dropdown->add( iv_txt = 'Open in Main Language' iv_act = |{ zif_abapgit_definitions=>c_action-repo_open_in_master_lang }?key={ mv_key }| ). ENDIF. ro_advanced_dropdown->add( iv_txt = 'Danger' iv_typ = zif_abapgit_html=>c_action_type-separator ). ro_advanced_dropdown->add( iv_txt = 'Remove Repository' iv_title = `Remove abapGit's records of the repository (the system's ` && `development objects will remain unaffected)` iv_act = |{ zif_abapgit_definitions=>c_action-repo_remove }?key={ mv_key }| ). ro_advanced_dropdown->add( iv_txt = 'Remove Objects' iv_title = `Delete all development objects belonging to this package ` && `(and subpackages) from the system, but keep repository in abapGit` iv_act = |{ zif_abapgit_definitions=>c_action-repo_delete_objects }?key={ mv_key }| ). ro_advanced_dropdown->add( iv_txt = 'Uninstall' iv_title = `Delete all development objects belonging to this package ` && `(and subpackages) from the system, and remove the repository from abapGit` iv_act = |{ zif_abapgit_definitions=>c_action-repo_purge }?key={ mv_key }| iv_opt = get_crossout( iv_authorization = zif_abapgit_auth=>c_authorization-uninstall iv_protected = abap_true ) ). ENDMETHOD. METHOD build_branch_dropdown. CREATE OBJECT ro_branch_dropdown. IF mo_repo->is_offline( ) = abap_true. RETURN. ENDIF. ro_branch_dropdown->add( iv_txt = 'Switch' iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_switch }?key={ mv_key }| ). ro_branch_dropdown->add( iv_txt = 'Create' iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_create }?key={ mv_key }| ). ro_branch_dropdown->add( iv_txt = 'Delete' iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_delete }?key={ mv_key }| ). ro_branch_dropdown->add( iv_txt = 'Merge' iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_merge }?key={ mv_key }| ). ENDMETHOD. METHOD build_dir_jump_link. DATA lv_path TYPE string. DATA lv_encode TYPE string. DATA li_html TYPE REF TO zif_abapgit_html. CREATE OBJECT li_html TYPE zcl_abapgit_html. lv_path = iv_path. REPLACE FIRST OCCURRENCE OF mv_cur_dir IN lv_path WITH ''. lv_encode = zcl_abapgit_html_action_utils=>dir_encode( lv_path ). " remove leading and trailing / for display IF lv_path <> '/'. IF lv_path(1) = '/'. lv_path = lv_path+1. ENDIF. IF substring( val = reverse( lv_path ) len = 1 ) = '/'. lv_path = substring( val = lv_path len = strlen( lv_path ) - 1 ). ENDIF. ENDIF. rv_html = li_html->a( iv_txt = lv_path iv_act = |{ c_actions-change_dir }?{ lv_encode }| ). ENDMETHOD. METHOD build_inactive_object_code. IF is_item-inactive = abap_true. rv_inactive_html_code = zcl_abapgit_html=>icon( iv_name = 'bolt/orange' iv_hint = 'Object or object part is inactive' iv_class = 'inactive' ). ENDIF. ENDMETHOD. METHOD build_main_toolbar. DATA: li_log TYPE REF TO zif_abapgit_log. CREATE OBJECT ro_toolbar EXPORTING iv_id = 'toolbar-repo'. IF mo_repo->is_offline( ) = abap_false. " online repo IF mo_repo_aggregated_state->is_unchanged( ) = abap_false. " Any changes ro_toolbar->add( iv_txt = 'Pull' iv_act = |{ zif_abapgit_definitions=>c_action-git_pull }?key={ mv_key }| iv_opt = get_crossout( iv_protected = abap_true iv_strong = abap_true ) ). ro_toolbar->add( iv_txt = 'Stage' iv_act = |{ zif_abapgit_definitions=>c_action-go_stage }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). ro_toolbar->add( iv_txt = 'Patch' iv_act = |{ zif_abapgit_definitions=>c_action-go_patch }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). ro_toolbar->add( iv_txt = 'Diff' iv_act = |{ zif_abapgit_definitions=>c_action-go_repo_diff }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). ENDIF. li_log = mo_repo->get_log( ). IF li_log IS BOUND AND li_log->count( ) > 0. ro_toolbar->add( iv_txt = 'Log' iv_act = |{ zif_abapgit_definitions=>c_action-repo_log }?key={ mv_key }| ). ENDIF. ro_toolbar->add( iv_txt = 'Branch' io_sub = build_branch_dropdown( ) ). ro_toolbar->add( iv_txt = 'Tag' io_sub = build_tag_dropdown( ) ). ELSE. " offline repo IF mo_repo->has_remote_source( ) = abap_true AND mo_repo_aggregated_state->is_unchanged( ) = abap_false. ro_toolbar->add( iv_txt = 'Pull zip' iv_act = |{ zif_abapgit_definitions=>c_action-git_pull }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). ro_toolbar->add( iv_txt = 'Diff' iv_act = |{ zif_abapgit_definitions=>c_action-go_repo_diff }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). ENDIF. ro_toolbar->add( iv_txt = 'Import zip' iv_act = |{ zif_abapgit_definitions=>c_action-zip_import }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). IF mo_repo->get_local_settings( )-write_protected = abap_true. ro_toolbar->add( iv_txt = 'Compare rfc' iv_act = |{ zif_abapgit_definitions=>c_action-rfc_compare }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). ENDIF. ro_toolbar->add( iv_txt = 'Export zip' iv_act = |{ zif_abapgit_definitions=>c_action-zip_export }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). li_log = mo_repo->get_log( ). IF li_log IS BOUND AND li_log->count( ) > 0. ro_toolbar->add( iv_txt = 'Log' iv_act = |{ zif_abapgit_definitions=>c_action-repo_log }?key={ mv_key }| ). ENDIF. ENDIF. ro_toolbar->add( iv_txt = 'Advanced' io_sub = build_advanced_dropdown( ) ). ro_toolbar->add( iv_txt = 'View' io_sub = build_view_dropdown( ) ). ro_toolbar->add( iv_txt = 'Refresh' iv_act = |{ zif_abapgit_definitions=>c_action-repo_refresh }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). ro_toolbar->add( iv_txt = 'Repo Settings' iv_act = |{ zif_abapgit_definitions=>c_action-repo_settings }?key={ mv_key }| iv_opt = zif_abapgit_html=>c_html_opt-strong iv_title = `Repository Settings` ). ENDMETHOD. METHOD build_origlang_code. IF is_item-origlang IS NOT INITIAL AND is_item-origlang <> mo_repo->get_dot_abapgit( )->get_main_language( ). rv_html_code = zcl_abapgit_html=>icon( iv_name = 'language-solid/grey' iv_hint = |Original language: { is_item-origlang }| iv_class = 'cursor-pointer' ). ENDIF. ENDMETHOD. METHOD build_srcsystem_code. IF is_item-srcsystem IS NOT INITIAL AND is_item-srcsystem <> sy-sysid. rv_srcsystem_html_code = zcl_abapgit_html=>icon( iv_name = 'server-solid/grey' iv_hint = |Original system: { is_item-srcsystem }| iv_class = 'cursor-pointer' ). ENDIF. ENDMETHOD. METHOD build_tag_dropdown. CREATE OBJECT ro_tag_dropdown. IF mo_repo->is_offline( ) = abap_true. RETURN. ENDIF. ro_tag_dropdown->add( iv_txt = 'Switch' iv_act = |{ zif_abapgit_definitions=>c_action-git_tag_switch }?key={ mv_key }| ). ro_tag_dropdown->add( iv_txt = 'Create' iv_act = |{ zif_abapgit_definitions=>c_action-git_tag_create }?key={ mv_key }| ). ro_tag_dropdown->add( iv_txt = 'Delete' iv_act = |{ zif_abapgit_definitions=>c_action-git_tag_delete }?key={ mv_key }| ). ENDMETHOD. METHOD build_view_dropdown. CREATE OBJECT ro_toolbar. ro_toolbar->add( iv_txt = 'Changes First' iv_chk = mv_diff_first iv_act = c_actions-toggle_diff_first ). ro_toolbar->add( iv_txt = 'Changes Only' iv_chk = mv_changes_only iv_act = c_actions-toggle_changes ). ro_toolbar->add( iv_txt = 'File Paths' iv_chk = boolc( NOT mv_hide_files = abap_true ) iv_act = c_actions-toggle_hide_files ). ro_toolbar->add( iv_txt = 'Folders' iv_chk = mv_show_folders iv_act = c_actions-toggle_folders ). ENDMETHOD. METHOD check_branch. DATA lo_repo TYPE REF TO zif_abapgit_repo_online. IF mo_repo->is_offline( ) = abap_false. lo_repo ?= mo_repo. lo_repo->check_for_valid_branch( ). ENDIF. ENDMETHOD. METHOD check_connection. DATA lo_repo TYPE REF TO zif_abapgit_repo_online. mv_connection_error = abap_true. IF mo_repo->is_offline( ) = abap_false. lo_repo ?= mo_repo. zcl_abapgit_http=>check_connection( lo_repo->get_url( ) ). ENDIF. mv_connection_error = abap_false. ENDMETHOD. METHOD constructor. DATA: lo_settings TYPE REF TO zcl_abapgit_settings, lx_error TYPE REF TO zcx_abapgit_exception, lo_persistence_user TYPE REF TO zif_abapgit_persist_user. super->constructor( ). TRY. lo_persistence_user = zcl_abapgit_persistence_user=>get_instance( ). mv_key = iv_key. mo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). mv_cur_dir = '/'. " Root mv_hide_files = lo_persistence_user->get_hide_files( ). mv_changes_only = lo_persistence_user->get_changes_only( ). mv_order_by = lo_persistence_user->get_order_by( ). mv_order_descending = lo_persistence_user->get_order_descending( ). mv_diff_first = lo_persistence_user->get_diff_first( ). mv_show_folders = lo_persistence_user->get_show_folders( ). " Read global settings to get max # of objects to be listed lo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). mv_max_lines = lo_settings->get_max_lines( ). mv_max_setting = mv_max_lines. CATCH zcx_abapgit_exception INTO lx_error. " Reset 'last shown repo' so next start will go to repo overview " and allow troubleshooting of issue zcl_abapgit_persistence_user=>get_instance( )->set_repo_show( || ). RAISE EXCEPTION lx_error. ENDTRY. ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_repo_view. CREATE OBJECT lo_component EXPORTING iv_key = iv_key. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Repository' ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD get_crossout. IF iv_strong = abap_true. rv_crossout = zif_abapgit_html=>c_html_opt-strong. ENDIF. IF iv_protected = abap_true AND mo_repo->get_local_settings( )-write_protected = abap_true. rv_crossout = zif_abapgit_html=>c_html_opt-crossout. ENDIF. IF iv_authorization IS NOT INITIAL AND zcl_abapgit_auth=>is_allowed( iv_authorization ) = abap_false. rv_crossout = zif_abapgit_html=>c_html_opt-crossout. ENDIF. ENDMETHOD. METHOD get_item_class. DATA lt_class TYPE TABLE OF string. IF iv_is_object_row = abap_true. APPEND 'object_row' TO lt_class. ELSE. APPEND 'file_row' TO lt_class. ENDIF. IF is_item-is_dir = abap_true. APPEND 'folder' TO lt_class. ELSEIF is_item-changes > 0. APPEND 'modified' TO lt_class. ELSEIF is_item-obj_name IS INITIAL. APPEND 'unsupported' TO lt_class. ENDIF. IF lines( lt_class ) > 0. rv_html = | class="{ concat_lines_of( table = lt_class sep = ` ` ) }"|. ENDIF. ENDMETHOD. METHOD is_repo_lang_logon_lang. rv_repo_lang_is_logon_lang = boolc( mo_repo->get_dot_abapgit( )->get_main_language( ) = sy-langu ). ENDMETHOD. METHOD open_in_main_language. DATA: lv_main_language TYPE spras, ls_item TYPE zif_abapgit_definitions=>ty_item, lv_tcode TYPE tcode. lv_main_language = mo_repo->get_dot_abapgit( )->get_main_language( ). lv_tcode = zcl_abapgit_services_abapgit=>get_abapgit_tcode( ). ASSERT lv_tcode IS NOT INITIAL. IF lv_main_language = sy-langu. zcx_abapgit_exception=>raise( |Repo already opened in main language| ). ENDIF. ls_item-obj_name = lv_tcode. ls_item-obj_type = |TRAN|. IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. zcx_abapgit_exception=>raise( |Please install the abapGit repository| ). ENDIF. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_abapgit( iv_language = lv_main_language iv_key = mo_repo->get_key( ) ). ENDMETHOD. METHOD order_files. DATA: lt_sort TYPE abap_sortorder_tab, ls_sort LIKE LINE OF lt_sort. IF lines( ct_files ) = 0. RETURN. ENDIF. ls_sort-descending = mv_order_descending. ls_sort-astext = abap_true. ls_sort-name = 'PATH'. INSERT ls_sort INTO TABLE lt_sort. ls_sort-descending = mv_order_descending. ls_sort-astext = abap_true. ls_sort-name = 'FILENAME'. INSERT ls_sort INTO TABLE lt_sort. SORT ct_files STABLE BY (lt_sort). ENDMETHOD. METHOD render_file_command. DATA: lv_difflink TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). IF is_file-is_changed = abap_true. lv_difflink = zcl_abapgit_html_action_utils=>file_encode( iv_key = mo_repo->get_key( ) ig_file = is_file ). ri_html->add_a( iv_txt = 'diff' iv_act = |{ zif_abapgit_definitions=>c_action-go_file_diff }?{ lv_difflink }| ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = is_file-lstate iv_rstate = is_file-rstate ) ). ELSE. ri_html->add( ' ' ). ENDIF. ri_html->add( '
' ). ENDMETHOD. METHOD render_head_line. DATA: lo_toolbar TYPE REF TO zcl_abapgit_html_toolbar, ls_settings TYPE zif_abapgit_definitions=>ty_s_user_settings, lo_label_colors TYPE REF TO zcl_abapgit_string_map, lt_labels TYPE string_table. CREATE OBJECT ri_html TYPE zcl_abapgit_html. lo_toolbar = build_main_toolbar( ). ri_html->add( '
' ). ri_html->add( '' ). IF mv_show_folders = abap_true. ri_html->add( '' ). ENDIF. lt_labels = zcl_abapgit_repo_labels=>split( mo_repo->ms_data-local_settings-labels ). IF lines( lt_labels ) > 0. ls_settings = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_user_settings( ). lo_label_colors = zcl_abapgit_repo_labels=>split_colors_into_map( ls_settings-label_colors ). ri_html->td( iv_content = zcl_abapgit_gui_chunk_lib=>render_label_list( it_labels = lt_labels io_label_colors = lo_label_colors ) iv_class = 'labels' ). ENDIF. ri_html->add( '' ). ri_html->add( '
' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_path( mv_cur_dir ) ). ri_html->add( '' ). ri_html->add( lo_toolbar->render( iv_right = abap_true ) ). ri_html->add( '
' ). ri_html->add( '
' ). ENDMETHOD. METHOD render_item. DATA: lv_link TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( || ). IF is_item-obj_name IS INITIAL AND is_item-is_dir = abap_false. ri_html->add( || && '' && 'non-code and meta files' && '' ). ELSE. ri_html->add( |{ zcl_abapgit_gui_chunk_lib=>get_item_icon( is_item ) }| ). IF is_item-is_dir = abap_true. " Subdir lv_link = build_dir_jump_link( is_item-path ). ri_html->add( |{ lv_link }| ). ELSE. lv_link = zcl_abapgit_gui_chunk_lib=>get_item_link( is_item ). ri_html->add( |{ is_item-obj_type }| ). ri_html->add( |{ lv_link } { build_inactive_object_code( is_item ) } { build_srcsystem_code( is_item ) } { build_origlang_code( is_item ) }| ). ENDIF. ENDIF. " Changed by ri_html->add( '' ). ri_html->add( render_item_changed_by( is_item ) ). ri_html->add( '' ). IF iv_render_transports = abap_true. ri_html->add( render_item_transport( is_item ) ). ENDIF. " Command ri_html->add( '' ). IF mo_repo->has_remote_source( ) = abap_true. ri_html->add( render_item_command( is_item ) ). ENDIF. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( render_item_files( is_item ) ). ENDMETHOD. METHOD render_item_changed_by. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF is_item-changes = 0 OR is_item-changed_by IS INITIAL. ri_html->add( ' ' ). ELSE. ri_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name( is_item-changed_by ) ). ENDIF. ENDMETHOD. METHOD render_item_command. DATA lv_difflink TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF is_item-is_dir = abap_true. " Directory ri_html->add( '
' ). ri_html->add( |{ is_item-changes } changes| ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = is_item-lstate iv_rstate = is_item-rstate ) ). ri_html->add( '
' ). ELSEIF is_item-changes > 0. IF mv_hide_files = abap_true AND is_item-obj_name IS NOT INITIAL. lv_difflink = zcl_abapgit_html_action_utils=>obj_encode( iv_key = mo_repo->get_key( ) ig_object = is_item ). ri_html->add( '
' ). ri_html->add_a( iv_txt = |diff ({ is_item-changes })| iv_act = |{ zif_abapgit_definitions=>c_action-go_file_diff }?{ lv_difflink }| ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = is_item-lstate iv_rstate = is_item-rstate ) ). ri_html->add( '
' ). ENDIF. ENDIF. ENDMETHOD. METHOD render_item_files. DATA: ls_file LIKE LINE OF is_item-files. DATA li_exit TYPE REF TO zif_abapgit_exit. DATA lv_filename TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF mv_hide_files = abap_true AND is_item-obj_type IS NOT INITIAL. RETURN. ENDIF. li_exit = zcl_abapgit_exit=>get_instance( ). LOOP AT is_item-files INTO ls_file. ri_html->add( || ). ri_html->add( || ). ri_html->add( || ). ri_html->add( || ). IF mv_show_folders = abap_true. lv_filename = ls_file-filename. ELSE. lv_filename = ls_file-path && ls_file-filename. ENDIF. lv_filename = li_exit->adjust_display_filename( is_repo_meta = mo_repo->ms_data iv_filename = lv_filename ). ri_html->add( |
{ lv_filename }
| ). ri_html->add( || ). " Changed by (not applicable to file) ri_html->add( '' ). ri_html->add( '' ). " Transport (not applicable to file) IF mv_are_changes_recorded_in_tr = abap_true. ri_html->add( `` ). ENDIF. " Command ri_html->add( '' ). IF mo_repo->has_remote_source( ) = abap_true. ri_html->add( render_file_command( ls_file ) ). ENDIF. ri_html->add( '' ). ri_html->add( '' ). ENDLOOP. ENDMETHOD. METHOD render_item_transport. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_transport( is_item-transport ) ). ri_html->add( '' ). ENDMETHOD. METHOD render_parent_dir. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( |{ ri_html->icon( 'folder' ) }| ). ri_html->add( |{ build_dir_jump_link( '..' ) }| ). IF mo_repo->has_remote_source( ) = abap_true. ri_html->add( || ). " Dummy for online ENDIF. ri_html->add( '' ). ENDMETHOD. METHOD render_scripts. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_palette( iv_action = zif_abapgit_definitions=>c_action-go_repo ) ). ENDMETHOD. METHOD render_table_footer. DATA lv_action TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF mv_changes_only = abap_true. lv_action = ri_html->a( iv_txt = 'Show All' iv_act = c_actions-toggle_changes ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_table_footer( |(Only changes are shown. { lv_action })| ) ). ENDIF. ENDMETHOD. METHOD render_table_header. DATA: lt_col_spec TYPE zif_abapgit_definitions=>ty_col_spec_tt, ls_col_spec TYPE zif_abapgit_definitions=>ty_col_spec. CREATE OBJECT ri_html TYPE zcl_abapgit_html. " icon APPEND INITIAL LINE TO lt_col_spec. ls_col_spec-tech_name = 'OBJ_TYPE'. ls_col_spec-display_name = 'Type'. ls_col_spec-allow_order_by = abap_true. APPEND ls_col_spec TO lt_col_spec. ls_col_spec-tech_name = 'OBJ_NAME'. ls_col_spec-display_name = 'Name'. ls_col_spec-allow_order_by = abap_true. APPEND ls_col_spec TO lt_col_spec. ls_col_spec-tech_name = 'CHANGED_BY'. ls_col_spec-display_name = 'Changed by'. ls_col_spec-allow_order_by = abap_true. APPEND ls_col_spec TO lt_col_spec. IF mv_are_changes_recorded_in_tr = abap_true. ls_col_spec-tech_name = 'TRANSPORT'. ls_col_spec-display_name = 'Transport'. ls_col_spec-allow_order_by = abap_true. APPEND ls_col_spec TO lt_col_spec. ENDIF. ls_col_spec-tech_name = 'LSTATE'. ls_col_spec-display_name = 'Status'. ls_col_spec-allow_order_by = abap_true. ls_col_spec-css_class = 'cmd'. APPEND ls_col_spec TO lt_col_spec. ri_html->add( zcl_abapgit_gui_chunk_lib=>render_table_header( it_col_spec = lt_col_spec iv_order_by = mv_order_by iv_order_descending = mv_order_descending ) ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA lv_path TYPE string. DATA lv_key TYPE zif_abapgit_persistence=>ty_value. lv_key = ii_event->query( )->get( 'KEY' ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-go_repo. " Switch to another repo rs_handled-page = create( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. WHEN c_actions-go_data. rs_handled-page = zcl_abapgit_gui_page_data=>create( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN c_actions-go_unit. rs_handled-page = zcl_abapgit_gui_page_runit=>create( mo_repo ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN c_actions-toggle_hide_files. " Toggle file display mv_hide_files = zcl_abapgit_persistence_user=>get_instance( )->toggle_hide_files( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_actions-change_dir. " Change dir lv_path = ii_event->query( )->get( 'PATH' ). mv_cur_dir = zcl_abapgit_path=>change_dir( iv_cur_dir = mv_cur_dir iv_cd = lv_path ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_actions-toggle_folders. " Toggle folder view mv_show_folders = zcl_abapgit_persistence_user=>get_instance( )->toggle_show_folders( ). mv_cur_dir = '/'. " Root rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_actions-toggle_changes. " Toggle changes only view mv_changes_only = zcl_abapgit_persistence_user=>get_instance( )->toggle_changes_only( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_actions-toggle_diff_first. mv_diff_first = zcl_abapgit_persistence_user=>get_instance( )->set_diff_first( boolc( mv_diff_first = abap_false ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_actions-display_more. " Increase MAX lines limit mv_max_lines = mv_max_lines + mv_max_setting. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-change_order_by. mv_order_by = zcl_abapgit_persistence_user=>get_instance( )->set_order_by( ii_event->query( )->get( 'ORDERBY' ) ). mv_order_descending = zcl_abapgit_persistence_user=>get_instance( )->set_order_descending( abap_false ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-direction. mv_order_descending = zcl_abapgit_persistence_user=>get_instance( )->set_order_descending( boolc( ii_event->query( )->get( 'DIRECTION' ) = 'DESCENDING' ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-repo_open_in_master_lang. open_in_main_language( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. ls_hotkey_action-ui_component = 'Repo'. ls_hotkey_action-description = |Stage|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_stage. ls_hotkey_action-hotkey = |s|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Switch Branch|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-git_branch_switch. ls_hotkey_action-hotkey = |b|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Repository List|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-abapgit_home. ls_hotkey_action-hotkey = |o|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Refresh Repository|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_refresh. ls_hotkey_action-hotkey = |r|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Pull|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-git_pull. ls_hotkey_action-hotkey = |p|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Patch|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_patch. ls_hotkey_action-hotkey = |a|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Diff|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_repo_diff. ls_hotkey_action-hotkey = |d|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Uninstall Repository|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_purge. ls_hotkey_action-hotkey = |u|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Run Syntax Check|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_syntax_check. ls_hotkey_action-hotkey = |c|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Run Unit Tests|. ls_hotkey_action-action = c_actions-go_unit. ls_hotkey_action-hotkey = |t|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Run Code Inspector|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_code_inspector. ls_hotkey_action-hotkey = |i|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Show Log|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_log. ls_hotkey_action-hotkey = |l|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar EXPORTING iv_id = 'toolbar-main'. ro_toolbar->add( iv_txt = zcl_abapgit_gui_buttons=>repo_list( ) iv_act = zif_abapgit_definitions=>c_action-abapgit_home )->add( iv_txt = zcl_abapgit_gui_buttons=>help( ) io_sub = zcl_abapgit_gui_menus=>help( ) ). zcl_abapgit_gui_menus=>experimental( ro_toolbar ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA: lt_repo_items TYPE zif_abapgit_definitions=>ty_repo_item_tt, lo_browser TYPE REF TO zcl_abapgit_repo_content_list, lx_error TYPE REF TO zcx_abapgit_exception, lv_max TYPE abap_bool, lv_max_str TYPE string, lv_add_str TYPE string, li_log TYPE REF TO zif_abapgit_log, lv_msg TYPE string, lo_news TYPE REF TO zcl_abapgit_repo_news. FIELD-SYMBOLS LIKE LINE OF lt_repo_items. register_handlers( ). CREATE OBJECT mo_repo_aggregated_state. CREATE OBJECT ri_html TYPE zcl_abapgit_html. TRY. " Reinit, for the case of type change mo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( mo_repo->get_key( ) ). IF mv_connection_error = abap_true. " If connection doesn't work, render a minimal header ri_html->add( |
| ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_edit = abap_true iv_show_branch = abap_false iv_show_commit = abap_false iv_interactive_branch = abap_false ) ). ri_html->add( '
' ). ri_html->add( render_head_line( ) ). " Reset error flag to try connecting again next time CLEAR mv_connection_error. RETURN. ENDIF. check_connection( ). check_branch( ). mv_are_changes_recorded_in_tr = zcl_abapgit_factory=>get_sap_package( mo_repo->get_package( ) )->are_changes_recorded_in_tr_req( ). lo_news = zcl_abapgit_repo_news=>create( mo_repo ). ri_html->add( |
| ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo io_news = lo_news iv_show_edit = abap_true iv_interactive_branch = abap_true ) ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_news( io_news = lo_news ) ). zcl_abapgit_exit=>get_instance( )->wall_message_repo( is_repo_meta = mo_repo->ms_data ii_html = ri_html ). CREATE OBJECT lo_browser EXPORTING io_repo = mo_repo. lt_repo_items = lo_browser->list( iv_path = mv_cur_dir iv_by_folders = mv_show_folders iv_changes_only = mv_changes_only iv_transports = mv_are_changes_recorded_in_tr ). apply_order_by( CHANGING ct_repo_items = lt_repo_items ). LOOP AT lt_repo_items ASSIGNING . mo_repo_aggregated_state->sum_with_repo_item( ). ENDLOOP. ri_html->add( render_head_line( ) ). li_log = lo_browser->get_log( ). IF li_log->count( ) > 0. ri_html->add( '
' ). ri_html->add( zcl_abapgit_log_viewer=>to_html( li_log ) ). " shows eg. list of unsupported objects ri_html->add( '
' ). ENDIF. ri_html->add( '
' ). CLEAR lv_msg. IF lines( lt_repo_items ) = 0. IF mv_changes_only = abap_true. IF mo_repo->is_offline( ) = abap_true. " Offline match banner IF mo_repo->has_remote_source( ) = abap_true. lv_msg = 'Local state completely matches the ZIP file'. ELSE. lv_msg = 'Import a ZIP file to see if there are any changes'. ENDIF. ELSE. " Online match banner lv_msg = 'Local state completely matches the remote repository'. ENDIF. ELSE. lv_msg = |Package is empty. Show { build_dir_jump_link( 'parent' ) } package|. ENDIF. ELSE. " Repo content table ri_html->add( '' ). ri_html->add( render_table_header( ) ). IF zcl_abapgit_path=>is_root( mv_cur_dir ) = abap_false. ri_html->add( render_parent_dir( ) ). ENDIF. LOOP AT lt_repo_items ASSIGNING . IF mv_max_lines > 0 AND sy-tabix > mv_max_lines. lv_max = abap_true. EXIT. " current loop ENDIF. ri_html->add( render_item( is_item = iv_render_transports = mv_are_changes_recorded_in_tr ) ). ENDLOOP. ri_html->add( render_table_footer( ) ). ri_html->add( '
' ). ENDIF. IF NOT lv_msg IS INITIAL. ri_html->add( |
{ lv_msg }
| ). ENDIF. IF lv_max = abap_true. ri_html->add( '
' ). IF mv_max_lines = 1. lv_max_str = '1 object'. ELSE. lv_max_str = |first { mv_max_lines } objects|. ENDIF. lv_add_str = |+{ mv_max_setting }|. ri_html->add( |Only { lv_max_str } objects shown in list. Display { ri_html->a( iv_txt = lv_add_str iv_act = c_actions-display_more ) } more (change in Settings > { ri_html->a( iv_txt = 'Personal Settings' iv_act = zif_abapgit_definitions=>c_action-go_settings_personal ) })| ). ri_html->add( '
' ). ENDIF. ri_html->add( '
' ). ri_html->add( '
' ). CATCH zcx_abapgit_exception INTO lx_error. " Reset 'last shown repo' so next start will go to repo overview " and allow troubleshooting of issue zcl_abapgit_persistence_user=>get_instance( )->set_repo_show( || ). RAISE EXCEPTION lx_error. ENDTRY. register_deferred_script( render_scripts( ) ). ENDMETHOD. ENDCLASS. CLASS kHGwlZbCwKVqbmulVBzOHKguCDENGa DEFINITION DEFERRED. * renamed: zcl_abapgit_gui_page_repo_over :: lcl_table_scheme CLASS kHGwlZbCwKVqbmulVBzOHKguCDENGa DEFINITION FINAL. " TODO: move to a global class, when table is separated as a component PUBLIC SECTION. DATA mt_col_spec TYPE zif_abapgit_definitions=>ty_col_spec_tt READ-ONLY. METHODS add_column IMPORTING iv_tech_name TYPE string OPTIONAL iv_display_name TYPE string OPTIONAL iv_css_class TYPE string OPTIONAL iv_add_tz TYPE abap_bool OPTIONAL iv_title TYPE string OPTIONAL iv_allow_order_by TYPE any OPTIONAL RETURNING VALUE(ro_me) TYPE REF TO kHGwlZbCwKVqbmulVBzOHKguCDENGa. ENDCLASS. CLASS kHGwlZbCwKVqbmulVBzOHKguCDENGa IMPLEMENTATION. METHOD add_column. FIELD-SYMBOLS LIKE LINE OF mt_col_spec. APPEND INITIAL LINE TO mt_col_spec ASSIGNING . -display_name = iv_display_name. -tech_name = iv_tech_name. -title = iv_title. -css_class = iv_css_class. -add_tz = iv_add_tz. -allow_order_by = iv_allow_order_by. ro_me = me. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. METHOD apply_filter. DATA lv_pfxl TYPE i. DATA lv_idx TYPE i. DATA lv_filter_label TYPE string. FIELD-SYMBOLS LIKE LINE OF ct_overview. IF ms_list_settings-filter IS INITIAL. RETURN. ENDIF. lv_pfxl = strlen( c_label_filter_prefix ). IF strlen( ms_list_settings-filter ) > lv_pfxl AND ms_list_settings-filter+0(lv_pfxl) = c_label_filter_prefix. lv_filter_label = ms_list_settings-filter+lv_pfxl. IF lv_filter_label = 'all'. DELETE ct_overview WHERE labels IS INITIAL. ELSEIF lv_filter_label = 'none'. DELETE ct_overview WHERE labels IS NOT INITIAL. ELSE. LOOP AT ct_overview ASSIGNING . lv_idx = sy-tabix. READ TABLE -labels TRANSPORTING NO FIELDS WITH KEY table_line = lv_filter_label. IF sy-subrc <> 0. DELETE ct_overview INDEX lv_idx. ENDIF. ENDLOOP. ENDIF. ELSE. " Regular filter DELETE ct_overview WHERE key NS ms_list_settings-filter AND name NS ms_list_settings-filter AND url NS ms_list_settings-filter AND package NS ms_list_settings-filter AND branch NS ms_list_settings-filter AND created_by NS ms_list_settings-filter AND created_at NS ms_list_settings-filter AND deserialized_by NS ms_list_settings-filter AND deserialized_at NS ms_list_settings-filter. ENDIF. ENDMETHOD. METHOD apply_order_by. DATA: lt_sort TYPE abap_sortorder_tab, ls_sort LIKE LINE OF lt_sort. ls_sort-name = 'FAVORITE'. ls_sort-descending = abap_true. ls_sort-astext = abap_true. INSERT ls_sort INTO TABLE lt_sort. IF ms_list_settings-order_by IS NOT INITIAL. CLEAR ls_sort. IF ms_list_settings-order_by = 'CREATED_AT' OR ms_list_settings-order_by = 'DESERIALIZED_AT'. ls_sort-name = ms_list_settings-order_by && c_raw_field_suffix. ELSE. ls_sort-name = ms_list_settings-order_by. ls_sort-astext = abap_true. ENDIF. ls_sort-descending = ms_list_settings-order_descending. INSERT ls_sort INTO TABLE lt_sort. ENDIF. SORT ct_overview BY (lt_sort). ENDMETHOD. METHOD build_table_scheme. DATA lo_tab_scheme TYPE REF TO kHGwlZbCwKVqbmulVBzOHKguCDENGa. CREATE OBJECT lo_tab_scheme. lo_tab_scheme->add_column( iv_tech_name = 'FAVORITE' iv_css_class = 'wmin' iv_allow_order_by = abap_false )->add_column( iv_tech_name = 'TYPE' iv_css_class = 'wmin' iv_allow_order_by = abap_false )->add_column( iv_tech_name = 'NAME' iv_display_name = 'Name' iv_allow_order_by = abap_true ). IF mt_all_labels IS NOT INITIAL. lo_tab_scheme->add_column( iv_tech_name = 'LABELS' iv_display_name = 'Labels' iv_allow_order_by = abap_false ). ENDIF. lo_tab_scheme->add_column( iv_tech_name = 'PACKAGE' iv_display_name = 'Package' iv_css_class = 'package' iv_allow_order_by = abap_true )->add_column( iv_tech_name = 'URL' iv_display_name = 'Remote' iv_allow_order_by = abap_true )->add_column( iv_tech_name = 'BRANCH' iv_display_name = 'Branch/Tag' iv_allow_order_by = abap_true )->add_column( iv_tech_name = 'DESERIALIZED_BY' iv_display_name = 'Deserialized by' iv_css_class = 'ro-detail' iv_allow_order_by = abap_true )->add_column( iv_tech_name = 'DESERIALIZED_AT' iv_display_name = 'Deserialized at' iv_css_class = 'ro-detail' iv_allow_order_by = abap_true )->add_column( iv_tech_name = 'CREATED_BY' iv_display_name = 'Created by' iv_css_class = 'ro-detail' iv_allow_order_by = abap_true )->add_column( iv_tech_name = 'CREATED_AT' iv_display_name = 'Created at' iv_css_class = 'ro-detail' iv_add_tz = abap_true iv_allow_order_by = abap_true )->add_column( iv_tech_name = 'KEY' iv_display_name = 'Key' iv_css_class = 'ro-detail' iv_allow_order_by = abap_true )->add_column( iv_tech_name = 'GO' iv_css_class = 'ro-go wmin' iv_allow_order_by = abap_false ). rt_tab_scheme = lo_tab_scheme->mt_col_spec. ENDMETHOD. METHOD collect_all_labels. FIELD-SYMBOLS LIKE LINE OF it_overview. LOOP AT it_overview ASSIGNING . APPEND LINES OF -labels TO rt_list. ENDLOOP. SORT rt_list. DELETE rt_list WHERE table_line IS INITIAL. DELETE ADJACENT DUPLICATES FROM rt_list. ENDMETHOD. METHOD constructor. super->constructor( ). ms_list_settings = zcl_abapgit_persistence_user=>get_instance( )->get_list_settings( ). " Overwrite setting IF iv_only_favorites = abap_true. ms_list_settings-only_favorites = abap_true. ENDIF. ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_repo_over. CREATE OBJECT lo_component EXPORTING iv_only_favorites = iv_only_favorites. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Repository List' ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD map_repo_list_to_overview. DATA ls_overview LIKE LINE OF rt_overview. FIELD-SYMBOLS LIKE LINE OF it_repo_obj_list. LOOP AT it_repo_obj_list ASSIGNING . CLEAR ls_overview. ls_overview-favorite = zcl_abapgit_persistence_user=>get_instance( )->is_favorite_repo( ->ms_data-key ). ls_overview-type = ->ms_data-offline. ls_overview-key = ->ms_data-key. ls_overview-name = ->get_name( ). ls_overview-labels = zcl_abapgit_repo_labels=>split( ->ms_data-local_settings-labels ). ls_overview-url = ->ms_data-url. ls_overview-package = ->ms_data-package. ls_overview-branch = ->ms_data-branch_name. ls_overview-created_by = ->ms_data-created_by. ls_overview-write_protected = ->ms_data-local_settings-write_protected. ls_overview-flow = ->ms_data-local_settings-flow. ls_overview-created_at_raw = ->ms_data-created_at. IF ->ms_data-created_at IS NOT INITIAL. ls_overview-created_at = zcl_abapgit_gui_chunk_lib=>render_timestamp( ->ms_data-created_at ). ENDIF. ls_overview-deserialized_by = ->ms_data-deserialized_by. ls_overview-deserialized_at_raw = ->ms_data-deserialized_at. IF ->ms_data-deserialized_at IS NOT INITIAL. ls_overview-deserialized_at = zcl_abapgit_gui_chunk_lib=>render_timestamp( ->ms_data-deserialized_at ). ENDIF. INSERT ls_overview INTO TABLE rt_overview. ENDLOOP. ENDMETHOD. METHOD prepare_overviews. DATA lt_repo_obj_list TYPE zif_abapgit_repo_srv=>ty_repo_list. IF ms_list_settings-only_favorites = abap_true. lt_repo_obj_list = zcl_abapgit_repo_srv=>get_instance( )->list_favorites( ). ELSE. lt_repo_obj_list = zcl_abapgit_repo_srv=>get_instance( )->list( ). ENDIF. rt_overviews = map_repo_list_to_overview( lt_repo_obj_list ). " Hmmm, side effect, not ideal, but we need label list before filter applied mt_all_labels = collect_all_labels( rt_overviews ). apply_order_by( CHANGING ct_overview = rt_overviews ). apply_filter( CHANGING ct_overview = rt_overviews ). ENDMETHOD. METHOD render_action_toolbar. CONSTANTS: lc_dummy_key TYPE string VALUE `?key=#`, lc_offline_class TYPE string VALUE `action_offline_repo`, lc_online_class TYPE string VALUE `action_online_repo`, lc_action_class TYPE string VALUE `action_link`. DATA lo_toolbar TYPE REF TO zcl_abapgit_html_toolbar. DATA lo_toolbar_more_sub TYPE REF TO zcl_abapgit_html_toolbar. CREATE OBJECT lo_toolbar EXPORTING iv_id = 'toolbar-ovp'. lo_toolbar->add( iv_txt = |Pull| iv_act = |{ zif_abapgit_definitions=>c_action-git_pull }{ lc_dummy_key }| iv_class = |{ lc_action_class } { lc_online_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar->add( iv_txt = |Stage| iv_act = |{ zif_abapgit_definitions=>c_action-go_stage }{ lc_dummy_key }| iv_class = |{ lc_action_class } { lc_online_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar->add( iv_txt = |Patch| iv_act = |{ zif_abapgit_definitions=>c_action-go_patch }{ lc_dummy_key }| iv_class = |{ lc_action_class } { lc_online_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar->add( iv_txt = |Diff| iv_act = |{ zif_abapgit_definitions=>c_action-go_repo_diff }{ lc_dummy_key }| iv_class = |{ lc_action_class } { lc_online_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar->add( iv_txt = |Check| iv_act = |{ zif_abapgit_definitions=>c_action-repo_code_inspector }{ lc_dummy_key }| iv_class = |{ lc_action_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar->add( iv_txt = |Import| iv_act = |{ zif_abapgit_definitions=>c_action-zip_import }{ lc_dummy_key }| iv_class = |{ lc_action_class } { lc_offline_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar->add( iv_txt = |Export| iv_act = |{ zif_abapgit_definitions=>c_action-zip_export }{ lc_dummy_key }| iv_class = |{ lc_action_class } { lc_offline_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar->add( iv_txt = |Repo Settings| iv_act = |{ zif_abapgit_definitions=>c_action-repo_settings }{ lc_dummy_key }| iv_class = |{ lc_action_class }| iv_li_class = |{ lc_action_class }| ). CREATE OBJECT lo_toolbar_more_sub EXPORTING iv_id = 'toolbar-ovp-more_sub'. lo_toolbar_more_sub->add( iv_txt = |Stage by Transport| iv_act = |{ zif_abapgit_definitions=>c_action-go_stage_transport }{ lc_dummy_key }| iv_class = |{ lc_action_class } { lc_online_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar_more_sub->add( iv_txt = |Export by Transport| iv_act = |{ zif_abapgit_definitions=>c_action-zip_export_transport }{ lc_dummy_key }| iv_class = |{ lc_action_class } { lc_offline_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar_more_sub->add( iv_txt = 'Danger' iv_typ = zif_abapgit_html=>c_action_type-separator ). lo_toolbar_more_sub->add( iv_txt = |Remove Repository| iv_title = |Remove abapGit's records of the repository (the system's | && |development objects will remain unaffected)| iv_act = |{ zif_abapgit_definitions=>c_action-repo_remove }{ lc_dummy_key }| iv_class = |{ lc_action_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar_more_sub->add( iv_txt = |Remove Objects| iv_title = |Delete all development objects belonging to this package | && |(and subpackages) from the system, but keep repository in abapGit| iv_act = |{ zif_abapgit_definitions=>c_action-repo_delete_objects }{ lc_dummy_key }| iv_class = |{ lc_action_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar_more_sub->add( iv_txt = |Uninstall| iv_title = |Delete all development objects belonging to this package | && |(and subpackages) from the system, and remove the repository from abapGit| iv_act = |{ zif_abapgit_definitions=>c_action-repo_purge }{ lc_dummy_key }| iv_class = |{ lc_action_class }| iv_li_class = |{ lc_action_class }| ). lo_toolbar->add( iv_txt = |More| io_sub = lo_toolbar_more_sub iv_class = |{ lc_action_class }| iv_li_class = |{ lc_action_class }| ). ri_html = lo_toolbar->render( iv_right = abap_true ). ENDMETHOD. METHOD render_filter_bar. DATA lv_icon_class TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( |
| ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_text_input( iv_name = |filter| iv_label = |Filter: { render_filter_help_hint( ) }| iv_value = ms_list_settings-filter ) ). ri_html->add( || ). ri_html->add( |
| ). IF ms_list_settings-only_favorites = abap_true. lv_icon_class = `blue`. ELSE. lv_icon_class = `grey`. ENDIF. ri_html->add( '' ). ri_html->add( ri_html->a( iv_txt = | Only Favorites| iv_class = 'command' iv_act = |{ zif_abapgit_definitions=>c_action-toggle_favorites }| ) ). ri_html->add( ri_html->a( iv_txt = ' Detail' iv_act = |gHelper.toggleRepoListDetail()| iv_class = 'command' iv_typ = zif_abapgit_html=>c_action_type-onclick ) ). ri_html->add( '' ). ENDMETHOD. METHOD render_filter_help_hint. DATA lt_fragments TYPE string_table. APPEND `Filter is applied to all text fields in the below table.` TO lt_fragments. APPEND ` Search works for any portion of the text (so can be a mid part as well).` TO lt_fragments. APPEND `
Starting query from label:xxx will filter appropriate label.` TO lt_fragments. APPEND `Two "special" label queries are available:` TO lt_fragments. APPEND ` all (to select all repos that has at least one label)` TO lt_fragments. APPEND ` and none (to select unlabeled repos).` TO lt_fragments. rv_html = zcl_abapgit_gui_chunk_lib=>render_help_hint( concat_lines_of( table = lt_fragments ) ). ENDMETHOD. METHOD render_header_bar. ii_html->add( |
| ). ii_html->add( render_filter_bar( ) ). ii_html->add( render_action_toolbar( ) ). ii_html->add( |
| ). ENDMETHOD. METHOD render_header_label_list. IF mt_all_labels IS INITIAL. RETURN. ENDIF. ii_html->add( |
| ). ii_html->add( '' ). ii_html->add( zcl_abapgit_gui_chunk_lib=>render_label_list( it_labels = mt_all_labels io_label_colors = mo_label_colors iv_clickable_action = c_action-label_filter ) ). ii_html->add( |
| ). ENDMETHOD. METHOD render_repo_list. ii_html->add( || ). render_table_header( ii_html ). render_table_body( ii_html = ii_html it_repo_list = it_overview ). render_table_footer( ii_html ). ii_html->add( |
| ). ENDMETHOD. METHOD render_scripts. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). ri_html->add( 'var gHelper = new RepoOverViewHelper({ focusFilterKey: "f" });' ). ENDMETHOD. METHOD render_table_body. FIELD-SYMBOLS LIKE LINE OF it_repo_list. ii_html->add( '' ). LOOP AT it_repo_list ASSIGNING . render_table_item( ii_html = ii_html is_repo = ). ENDLOOP. ii_html->add( || ). ENDMETHOD. METHOD render_table_footer. DATA lv_action TYPE string. IF ms_list_settings-only_favorites = abap_true. lv_action = ii_html->a( iv_txt = 'Show All' iv_act = |{ zif_abapgit_definitions=>c_action-toggle_favorites }?force_state={ abap_false }| ). ii_html->add( zcl_abapgit_gui_chunk_lib=>render_table_footer( |(Only favorites are shown. { lv_action })| ) ). ENDIF. ENDMETHOD. METHOD render_table_header. ii_html->add( zcl_abapgit_gui_chunk_lib=>render_table_header( it_col_spec = build_table_scheme( ) iv_order_by = ms_list_settings-order_by iv_order_descending = ms_list_settings-order_descending ) ). ENDMETHOD. METHOD render_table_item. DATA: lv_is_online_repo TYPE abap_bool, lv_repo_type_icon TYPE string, lv_favorite_icon TYPE string, lv_fav_tr_class TYPE string, lv_lock TYPE string, lv_flow TYPE string. lv_is_online_repo = boolc( is_repo-type = abap_false ). " Start of row IF is_repo-favorite = abap_true. lv_fav_tr_class = ' class="favorite"'. ELSE. lv_fav_tr_class = ''. ENDIF. ii_html->add( || ). " Favorite lv_favorite_icon = ii_html->icon( iv_name = 'star/grey' " blue is added in css, based on TR style iv_class = 'pad-sides' iv_hint = 'Click to toggle favorite' ). ii_html->td( iv_class = 'wmin' iv_content = ii_html->a( iv_act = |{ zif_abapgit_definitions=>c_action-repo_toggle_fav }?key={ is_repo-key }| iv_txt = lv_favorite_icon ) ). " Online/Offline IF lv_is_online_repo = abap_true. lv_repo_type_icon = 'cloud-upload-alt/darkgrey'. ELSE. lv_repo_type_icon = 'plug/darkgrey'. ENDIF. ii_html->td( iv_class = 'wmin' iv_content = ii_html->icon( lv_repo_type_icon ) ). " Repo name IF is_repo-write_protected = abap_true. lv_lock = ii_html->icon( iv_name = 'lock/grey70' iv_class = 'm-em5-sides' iv_hint = 'Locked from pulls' ). ENDIF. IF is_repo-flow = abap_true. lv_flow = ii_html->icon( iv_name = 'flow/grey70' iv_class = 'm-em5-sides' iv_hint = 'Flow' ). ENDIF. ii_html->td( ii_html->a( iv_txt = is_repo-name iv_act = |{ c_action-select }?key={ is_repo-key }| ) && lv_lock && lv_flow ). " Labels IF mt_all_labels IS NOT INITIAL. ii_html->td( iv_content = zcl_abapgit_gui_chunk_lib=>render_label_list( it_labels = is_repo-labels io_label_colors = mo_label_colors iv_unlisted = abap_true iv_clickable_action = c_action-label_filter ) iv_class = 'labels' ). ENDIF. " Package ii_html->td( ii_content = zcl_abapgit_gui_chunk_lib=>render_package_name( iv_package = is_repo-package iv_suppress_title = boolc( NOT ms_list_settings-only_favorites = abap_true ) ) ). " Repo URL IF lv_is_online_repo = abap_true. ii_html->td( ii_content = zcl_abapgit_gui_chunk_lib=>render_repo_url( iv_url = is_repo-url iv_render_remote_edit_for_key = is_repo-key ) ). ELSE. ii_html->td( ). ENDIF. " Branch IF is_repo-branch IS INITIAL. ii_html->td( ). ELSE. ii_html->td( ii_content = zcl_abapgit_gui_chunk_lib=>render_branch_name( iv_branch = is_repo-branch iv_repo_key = is_repo-key ) ). ENDIF. " Details: deserialized by ii_html->td( iv_class = 'ro-detail' ii_content = zcl_abapgit_gui_chunk_lib=>render_user_name( iv_username = is_repo-deserialized_by iv_suppress_title = boolc( NOT ms_list_settings-only_favorites = abap_true ) ) ). " Details: deserialized at ii_html->td( iv_class = 'ro-detail' iv_content = is_repo-deserialized_at ). " Details: created by ii_html->td( iv_class = 'ro-detail' ii_content = zcl_abapgit_gui_chunk_lib=>render_user_name( iv_username = is_repo-created_by iv_suppress_title = boolc( NOT ms_list_settings-only_favorites = abap_true ) ) ). " Details: created at ii_html->td( iv_class = 'ro-detail' iv_content = is_repo-created_at ). " Details: repo key ii_html->td( iv_class = 'ro-detail' iv_content = |{ is_repo-key }| ). " Go-to action ii_html->td( iv_class = 'ro-go wmin' iv_content = ii_html->a( iv_title = 'Open' iv_txt = '▸' iv_act = |{ c_action-select }?key={ is_repo-key }| ) ). ii_html->add( `` ). ENDMETHOD. METHOD save_settings. zcl_abapgit_persistence_user=>get_instance( )->set_list_settings( ms_list_settings ). ENDMETHOD. METHOD set_filter. FIELD-SYMBOLS LIKE LINE OF it_postdata. READ TABLE it_postdata ASSIGNING INDEX 1. IF sy-subrc = 0. FIND FIRST OCCURRENCE OF REGEX `filter=(.*)` IN SUBMATCHES ms_list_settings-filter. ENDIF. ms_list_settings-filter = condense( ms_list_settings-filter ). save_settings( ). ENDMETHOD. METHOD set_order_by. IF ms_list_settings-order_by <> iv_order_by. set_order_direction( abap_false ). " Reset ordering ENDIF. ms_list_settings-order_by = iv_order_by. save_settings( ). ENDMETHOD. METHOD set_order_direction. ms_list_settings-order_descending = iv_order_descending. save_settings( ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA lv_key TYPE zif_abapgit_persistence=>ty_value. lv_key = ii_event->query( )->get( 'KEY' ). CASE ii_event->mv_action. WHEN c_action-select. zcl_abapgit_persistence_user=>get_instance( )->set_repo_show( lv_key ). TRY. zcl_abapgit_repo_srv=>get_instance( )->get( lv_key )->refresh( ). CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( lv_key ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN zif_abapgit_definitions=>c_action-change_order_by. set_order_by( ii_event->query( )->get( 'ORDERBY' ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-toggle_favorites. IF ii_event->query( )->has( 'FORCE_STATE' ) = abap_true. ms_list_settings-only_favorites = ii_event->query( )->get( 'FORCE_STATE' ). ELSE. ms_list_settings-only_favorites = boolc( ms_list_settings-only_favorites = abap_false ). ENDIF. save_settings( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-direction. set_order_direction( boolc( ii_event->query( )->get( 'DIRECTION' ) = 'DESCENDING' ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_action-apply_filter. set_filter( ii_event->mt_postdata ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_action-label_filter. IF ii_event->mv_getdata IS NOT INITIAL. ms_list_settings-filter = c_label_filter_prefix && ii_event->mv_getdata. ELSE. CLEAR ms_list_settings-filter. " Unexpected request ENDIF. save_settings( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. ls_hotkey_action-ui_component = 'Repo overview'. ls_hotkey_action-description = |New Online Repository|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_newonline. ls_hotkey_action-hotkey = |n|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |New Offline Repository|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_newoffline. ls_hotkey_action-hotkey = |o|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Global Settings|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_settings. ls_hotkey_action-hotkey = |x|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Stage|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_stage. ls_hotkey_action-hotkey = |s|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Diff|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_repo_diff. ls_hotkey_action-hotkey = |d|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Check|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-repo_code_inspector. ls_hotkey_action-hotkey = |c|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Pull|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-git_pull. ls_hotkey_action-hotkey = |p|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Patch|. ls_hotkey_action-action = zif_abapgit_definitions=>c_action-go_patch. ls_hotkey_action-hotkey = |a|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. " registered/handled in js ls_hotkey_action-description = |Previous Repository|. ls_hotkey_action-action = `#`. ls_hotkey_action-hotkey = |4|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Next Repository|. ls_hotkey_action-action = `##`. ls_hotkey_action-hotkey = |6|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Open Repository|. ls_hotkey_action-action = `###`. ls_hotkey_action-hotkey = |Enter|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Focus Filter|. ls_hotkey_action-action = `####`. ls_hotkey_action-hotkey = |f|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar EXPORTING iv_id = 'toolbar-main'. ro_toolbar->add( iv_txt = zcl_abapgit_gui_buttons=>flow( ) iv_act = zif_abapgit_definitions=>c_action-flow ). ro_toolbar->add( iv_txt = zcl_abapgit_gui_buttons=>new_online( ) iv_act = zif_abapgit_definitions=>c_action-repo_newonline )->add( iv_txt = zcl_abapgit_gui_buttons=>new_offline( ) iv_act = zif_abapgit_definitions=>c_action-repo_newoffline )->add( iv_txt = zcl_abapgit_gui_buttons=>settings( ) iv_act = zif_abapgit_definitions=>c_action-go_settings )->add( iv_txt = zcl_abapgit_gui_buttons=>advanced( ) io_sub = zcl_abapgit_gui_menus=>advanced( ) )->add( iv_txt = zcl_abapgit_gui_buttons=>help( ) io_sub = zcl_abapgit_gui_menus=>help( ) ). zcl_abapgit_gui_menus=>experimental( ro_toolbar ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA lt_overview TYPE ty_overviews. DATA ls_settings TYPE zif_abapgit_definitions=>ty_s_user_settings. ls_settings = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_user_settings( ). mo_label_colors = zcl_abapgit_repo_labels=>split_colors_into_map( ls_settings-label_colors ). lt_overview = prepare_overviews( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. zcl_abapgit_exit=>get_instance( )->wall_message_list( ri_html ). ri_html->add( |
| ). render_header_bar( ri_html ). render_header_label_list( ri_html ). render_repo_list( ii_html = ri_html it_overview = lt_overview ). ri_html->add( |
| ). register_deferred_script( render_scripts( ) ). register_deferred_script( zcl_abapgit_gui_chunk_lib=>render_repo_palette( c_action-select ) ). register_handlers( ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_PULL IMPLEMENTATION. METHOD choose_transport_request. DATA lv_transport_request TYPE trkorr. lv_transport_request = zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( ). IF lv_transport_request IS NOT INITIAL. mo_form_data->set( iv_key = c_id-transport_request iv_val = lv_transport_request ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( ). mo_repo = io_repo. mi_obj_filter = ii_obj_filter. CREATE OBJECT mo_form_data. mo_form_data->set( iv_key = c_id-transport_request iv_val = iv_trkorr ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_pull. CREATE OBJECT lo_component EXPORTING io_repo = io_repo iv_trkorr = iv_trkorr ii_obj_filter = ii_obj_filter. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Pull' ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD form. DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. FIELD-SYMBOLS LIKE LINE OF ms_checks-overwrite. IF mi_obj_filter IS NOT INITIAL. lt_filter = mi_obj_filter->get_filter( ). ENDIF. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'pull-form' ). ro_form->start_group( iv_name = 'id-objects' iv_label = 'Objects' ). LOOP AT ms_checks-overwrite ASSIGNING . IF lines( lt_filter ) > 0. READ TABLE lt_filter WITH KEY object = -obj_type obj_name = -obj_name TRANSPORTING NO FIELDS. IF sy-subrc <> 0. CONTINUE. ENDIF. ENDIF. ro_form->checkbox( iv_label = |{ -obj_type } { -obj_name }| iv_name = |{ -obj_type }-{ -obj_name }| ). ENDLOOP. ro_form->text( iv_name = c_id-transport_request iv_required = abap_true iv_upper_case = abap_true iv_side_action = c_action-choose_tr iv_max = 10 iv_label = |Transport Request| ). ro_form->command( iv_label = 'Pull' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_action-pull )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA lv_value TYPE string. FIELD-SYMBOLS LIKE LINE OF ms_checks-overwrite. mo_form_data->merge( ii_event->form_data( ) ). CASE ii_event->mv_action. WHEN c_action-refresh. mo_repo->refresh( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_action-choose_tr. choose_transport_request( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_action-pull. ms_checks-transport-transport = mo_form_data->get( c_id-transport_request ). LOOP AT ms_checks-overwrite ASSIGNING . lv_value = mo_form_data->get( |{ -obj_type }-{ -obj_name }| ). IF lv_value = 'on'. -decision = zif_abapgit_definitions=>c_yes. ELSE. -decision = zif_abapgit_definitions=>c_no. ENDIF. ENDLOOP. * todo, show log? zcl_abapgit_services_repo=>real_deserialize( is_checks = ms_checks io_repo = mo_repo ). rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar EXPORTING iv_id = 'toolbar-main'. ro_toolbar->add( iv_txt = 'Refresh' iv_act = c_action-refresh ). ro_toolbar->add( iv_txt = 'Back' iv_act = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ms_checks = mo_repo->deserialize_checks( ). IF lines( ms_checks-overwrite ) = 0. zcx_abapgit_exception=>raise( 'There is nothing to pull. The local state completely matches the remote repository.' ). ENDIF. ri_html->add( form( )->render( mo_form_data ) ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_patch IMPLEMENTATION. METHOD add_menu_begin. io_menu->add( iv_txt = c_action_texts-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 = c_action_titles-refresh_local ). io_menu->add( iv_txt = c_action_texts-refresh_all iv_typ = zif_abapgit_html=>c_action_type-dummy iv_act = c_actions-refresh_all iv_id = c_actions-refresh_all iv_title = c_action_titles-refresh_all ). ENDMETHOD. METHOD add_menu_end. io_menu->add( iv_txt = 'Stage' iv_act = c_patch_actions-stage iv_id = 'stage' iv_typ = zif_abapgit_html=>c_action_type-dummy ). add_view_sub_menu( io_menu ). 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 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 apply_patch_from_form_fields. DATA: lv_add TYPE string, lv_remove TYPE string. lv_add = ii_event->form_data( )->get( c_patch_action-add ). lv_remove = ii_event->form_data( )->get( c_patch_action-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 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 constructor. super->constructor( iv_key = iv_key is_file = is_file is_object = is_object it_files = it_files ). IF mo_repo->is_offline( ) = abap_true. zcx_abapgit_exception=>raise( |Patching is only possible for online repositories.| ). ENDIF. mo_repo_online ?= mo_repo. " While patching we always want to be in split mode CLEAR: mv_unified. CREATE OBJECT mo_stage. ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_patch. CREATE OBJECT lo_component EXPORTING iv_key = iv_key is_file = is_file is_object = is_object it_files = it_files. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Patch' iv_page_layout = zcl_abapgit_gui_page=>c_page_layout-full_width ii_page_menu_provider = lo_component ii_child_component = lo_component ). 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_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_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 insert_nav. " add beacon at beginning of file rv_insert_nav = abap_true. 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 refresh. DATA: lt_diff_files_old TYPE ty_file_diffs. lt_diff_files_old = mt_diff_files. super->refresh( iv_action ). restore_patch_flags( lt_diff_files_old ). ENDMETHOD. METHOD render_beacon_begin_of_row. mv_section_count = mv_section_count + 1. ii_html->add( || ). ii_html->add_checkbox( |patch_section_{ get_normalized_fname_with_path( is_diff ) }_{ mv_section_count }| ). ii_html->add( '' ). ENDMETHOD. METHOD render_diff_head_after_state. DATA: lv_act_id TYPE string. lv_act_id = |{ c_actions-refresh_local_object }_{ is_diff-obj_type }_{ is_diff-obj_name }|. IF is_diff-obj_type IS NOT INITIAL AND is_diff-obj_name IS NOT INITIAL. " Dummy link is handled in JS (based on ID) ii_html->add( '' ). ii_html->add_a( iv_txt = ii_html->icon( iv_name = 'redo-alt-solid' iv_class = 'pad-sides' iv_hint = 'Local refresh of this object' ) iv_id = lv_act_id iv_act = lv_act_id iv_typ = zif_abapgit_html=>c_action_type-dummy iv_class = |url| ). ii_html->add( '' ). ENDIF. ENDMETHOD. METHOD render_line_split_row. render_patch( ii_html = ii_html iv_filename = iv_filename is_diff_line = is_diff_line iv_index = iv_index ). super->render_line_split_row( ii_html = ii_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 render_patch. CONSTANTS: BEGIN OF lc_css_class, patch TYPE string VALUE `patch`, 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 ). IF lv_is_patch_possible = abap_true. lv_id = |{ iv_filename }_{ mv_section_count }_{ iv_index }|. ii_html->add( || ). ii_html->add_checkbox( iv_id = |patch_line_{ lv_id }| iv_checked = lv_patched ). ii_html->add( || ). ELSE. ii_html->add( || ). ii_html->add( || ). ENDIF. ENDMETHOD. METHOD render_patch_head. ii_html->add( || ). ii_html->add_checkbox( |patch_file_{ get_normalized_fname_with_path( is_diff ) }| ). ii_html->add( '' ). ENDMETHOD. METHOD render_scripts. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). ri_html->add( 'preparePatch();' ). ri_html->add( 'registerStagePatch();' ). ENDMETHOD. METHOD render_table_head_non_unified. render_patch_head( ii_html = ii_html is_diff = is_diff ). super->render_table_head_non_unified( ii_html = ii_html is_diff = is_diff ). 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. IF -o_diff IS NOT BOUND. CONTINUE. " e.g. binary files 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 start_staging. apply_patch_from_form_fields( ii_event ). add_to_stage( ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. CASE ii_event->mv_action. WHEN c_patch_actions-stage. start_staging( ii_event ). rs_handled-page = zcl_abapgit_gui_page_commit=>create( io_repo = mo_repo_online io_stage = mo_stage ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN OTHERS. IF is_refresh( ii_event->mv_action ) = abap_true. apply_patch_from_form_fields( ii_event ). refresh( ii_event->mv_action ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled = super->zif_abapgit_gui_event_handler~on_event( ii_event ). ENDIF. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA ls_hotkey_action LIKE LINE OF rt_hotkey_actions. ls_hotkey_action-ui_component = 'Patch'. ls_hotkey_action-description = |Stage Changes|. ls_hotkey_action-action = |stagePatch|. ls_hotkey_action-hotkey = |s|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Refresh Local|. ls_hotkey_action-action = |refreshLocal|. ls_hotkey_action-hotkey = |r|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Refresh All|. ls_hotkey_action-action = |refreshAll|. ls_hotkey_action-hotkey = |a|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. CLEAR mv_section_count. IF mv_pushed = abap_true. refresh_full( ). calculate_diff( ). CLEAR mv_pushed. ENDIF. register_handlers( ). ri_html = super->zif_abapgit_gui_renderable~render( ). register_deferred_script( render_scripts( ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_merge_sel IMPLEMENTATION. METHOD constructor. super->constructor( ). CREATE OBJECT mo_form_data. mo_repo ?= ii_repo. read_branches( ). mo_form = get_form_schema( ). mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_merge_sel. CREATE OBJECT lo_component EXPORTING ii_repo = ii_repo. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Merge Branches' ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. FIELD-SYMBOLS LIKE LINE OF mt_branches. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'merge-branches-form' iv_help_page = 'https://docs.abapgit.org/' ). " todo, add docs ro_form->start_group( iv_name = c_id-branches iv_label = 'Branch Selection' iv_hint = 'Select the branches that should be merged' )->radio( iv_name = c_id-source iv_label = 'Source Branch' iv_default_value = substring( val = mo_repo->get_selected_branch( ) off = 11 ) iv_condense = abap_true ). LOOP AT mt_branches ASSIGNING . ro_form->option( iv_label = -display_name iv_value = -display_name ). ENDLOOP. ro_form->radio( iv_name = c_id-target iv_label = 'Target Branch' iv_condense = abap_true ). LOOP AT mt_branches ASSIGNING . ro_form->option( iv_label = -display_name iv_value = -display_name ). ENDLOOP. ro_form->command( iv_label = 'Preview Merge' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-merge )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD read_branches. DATA lo_branches TYPE REF TO zcl_abapgit_git_branch_list. lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( mo_repo->get_url( ) ). mt_branches = lo_branches->get_branches_only( ). DELETE mt_branches WHERE name = zif_abapgit_git_definitions=>c_head_name. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). CASE ii_event->mv_action. WHEN c_event-merge. IF mo_form_data->get( c_id-source ) = mo_form_data->get( c_id-target ). zcx_abapgit_exception=>raise( 'Select different branches' ). ENDIF. rs_handled-page = zcl_abapgit_gui_page_merge=>create( io_repo = mo_repo iv_source = mo_form_data->get( c_id-source ) iv_target = mo_form_data->get( c_id-target ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN OTHERS. ASSERT 1 = 1. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( `
` ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false iv_interactive_branch = abap_false ) ). ri_html->add( mo_form->render( io_values = mo_form_data ) ). ri_html->add( `
` ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_merge_res IMPLEMENTATION. METHOD apply_merged_content. DATA: lv_merge_content TYPE string, lv_new_file_content TYPE xstring. FIELD-SYMBOLS: TYPE zif_abapgit_merge=>ty_merge_conflict. lv_merge_content = ii_event->form_data( )->get( 'MERGE_CONTENT' ). REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_merge_content WITH cl_abap_char_utilities=>newline. lv_new_file_content = zcl_abapgit_convert=>string_to_xstring_utf8( lv_merge_content ). READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. -result_sha1 = zcl_abapgit_hash=>sha1_blob( lv_new_file_content ). -result_data = lv_new_file_content. mo_merge->resolve_conflict( ). ENDMETHOD. METHOD constructor. super->constructor( ). mo_repo = io_repo. mo_merge_page = io_merge_page. mo_merge = io_merge. mv_merge_mode = c_merge_mode-selection. mv_current_conflict_index = 1. mt_conflicts = io_merge->get_conflicts( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_merge_res. CREATE OBJECT lo_component EXPORTING io_repo = io_repo io_merge_page = io_merge_page io_merge = io_merge. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Resolve Merge Conflicts' ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD is_binary. FIELD-SYMBOLS LIKE iv_d1. IF iv_d1 IS NOT INITIAL. " One of them might be new and so empty ASSIGN iv_d1 TO . ELSE. ASSIGN iv_d2 TO . ENDIF. rv_yes = zcl_abapgit_utils=>is_binary( ). ENDMETHOD. METHOD render_beacon. DATA: lv_beacon TYPE string, lt_beacons TYPE zif_abapgit_definitions=>ty_string_tt. CREATE OBJECT ri_html TYPE zcl_abapgit_html. 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. ELSE. lv_beacon = '---'. ENDIF. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( |@@ { is_diff_line-new_num } @@ { lv_beacon }| ). ri_html->add( '' ). ri_html->add( '' ). ENDMETHOD. METHOD render_diff. DATA lv_target_content TYPE string. FIELD-SYMBOLS TYPE zif_abapgit_merge=>ty_merge_conflict. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( |
| ). ri_html->add( render_diff_head( is_diff ) ). " Content IF is_diff-type <> 'binary'. IF mv_merge_mode = c_merge_mode-selection. ri_html->add( '
' ). ri_html->add( '' ). ri_html->add( render_table_head( ) ). ri_html->add( render_lines( is_diff ) ). ri_html->add( '
' ). ri_html->add( '
' ). ELSE. "Table for Div-Table and textarea ri_html->add( '
' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( ' ' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '
CodeMerge - ' ). ri_html->add_a( iv_act = 'submitFormById(''merge_form'');' iv_txt = 'Apply' iv_typ = zif_abapgit_html=>c_action_type-onclick iv_opt = zif_abapgit_html=>c_html_opt-strong ). ri_html->add( '
' ). "Diff-Table of source and target file ri_html->add( '' ). ri_html->add( render_table_head( ) ). ri_html->add( render_lines( is_diff ) ). ri_html->add( '
' ). READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. IF sy-subrc = 0. lv_target_content = zcl_abapgit_convert=>xstring_to_string_utf8( -target_data ). lv_target_content = escape( val = lv_target_content format = cl_abap_format=>e_html_text ). ENDIF. ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( |
add( |method="post" action="sapevent:apply_merge">| ). ri_html->add( || ). ri_html->add( '' ). ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( '
' ). ENDIF. ELSE. ri_html->add( '
' ). ri_html->add( 'The content seems to be binary.' ). ri_html->add( 'Cannot display as diff.' ). ri_html->add( '
' ). ENDIF. ri_html->add( '
' ). ENDMETHOD. METHOD render_diff_head. DATA ls_stats TYPE zif_abapgit_definitions=>ty_count. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). IF is_diff-type <> 'binary' AND is_diff-o_diff IS NOT INITIAL. ls_stats = is_diff-o_diff->stats( ). ri_html->add( |+ { ls_stats-insert }| ). ri_html->add( |- { ls_stats-delete }| ). ri_html->add( |~ { ls_stats-update }| ). ENDIF. ri_html->add( |{ is_diff-filename }| ). ri_html->add( '
' ). ENDMETHOD. METHOD render_lines. DATA: lo_highlighter TYPE REF TO zcl_abapgit_syntax_highlighter, lt_diffs TYPE zif_abapgit_definitions=>ty_diffs_tt, lv_insert_nav TYPE abap_bool. FIELD-SYMBOLS LIKE LINE OF lt_diffs. lo_highlighter = zcl_abapgit_syntax_factory=>create( is_diff-filename ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. lt_diffs = is_diff-o_diff->get( ). LOOP AT lt_diffs ASSIGNING . IF -short = abap_false. lv_insert_nav = abap_true. CONTINUE. ENDIF. IF lv_insert_nav = abap_true. " Insert separator line with navigation ri_html->add( render_beacon( is_diff_line = is_diff = is_diff ) ). lv_insert_nav = abap_false. ENDIF. IF lo_highlighter IS BOUND. -new = lo_highlighter->process_line( -new ). -old = lo_highlighter->process_line( -old ). ELSE. -new = escape( val = -new format = cl_abap_format=>e_html_attr ). -old = escape( val = -old format = cl_abap_format=>e_html_attr ). ENDIF. CONDENSE -new_num. "get rid of leading spaces CONDENSE -old_num. ri_html->add( render_line_split( ) ). ENDLOOP. ENDMETHOD. METHOD render_line_split. DATA: lv_new TYPE string, lv_old TYPE string, lv_mark TYPE string, lv_bg TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. " New line lv_mark = ` `. IF is_diff_line-result = zif_abapgit_definitions=>c_diff-update. lv_bg = ' diff_upd'. lv_mark = `~`. ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-insert. lv_bg = ' diff_ins'. lv_mark = `+`. ENDIF. lv_new = || && |{ lv_mark }{ is_diff_line-new }|. " Old line CLEAR lv_bg. lv_mark = ` `. IF is_diff_line-result = zif_abapgit_definitions=>c_diff-update. lv_bg = ' diff_upd'. lv_mark = `~`. ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-delete. lv_bg = ' diff_del'. lv_mark = `-`. ENDIF. lv_old = || && |{ lv_mark }{ is_diff_line-old }|. " render line, inverse sides if remote is newer ri_html->add( '' ). ri_html->add( lv_old ). " Target ri_html->add( lv_new ). " Source ri_html->add( '' ). ENDMETHOD. METHOD render_table_head. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). IF mv_merge_mode = c_merge_mode-selection. ri_html->add( '
' ). ri_html->add( 'Target - ' && mo_repo->get_selected_branch( ) && ' - ' ). ri_html->add_a( iv_act = 'submitFormById(''target_form'');' iv_txt = 'Apply' iv_typ = zif_abapgit_html=>c_action_type-onclick iv_opt = zif_abapgit_html=>c_html_opt-strong ). ri_html->add( ' ' ). ri_html->add( '
' ). ri_html->add( '' ). ri_html->add( '
' ). ri_html->add( 'Source - ' && mo_merge->get_source_branch( ) && ' - ' ). ri_html->add_a( iv_act = 'submitFormById(''source_form'');' iv_txt = 'Apply' iv_typ = zif_abapgit_html=>c_action_type-onclick iv_opt = zif_abapgit_html=>c_html_opt-strong ). ri_html->add( ' ' ). ri_html->add( '
' ). ELSE. ri_html->add( 'Target - ' && mo_repo->get_selected_branch( ) && ' ' ). ri_html->add( '' ). ri_html->add( 'Source - ' && mo_merge->get_source_branch( ) && ' ' ). ENDIF. ri_html->add( '' ). ri_html->add( '' ). ENDMETHOD. METHOD resolve_diff. DATA lv_offs TYPE i. FIELD-SYMBOLS TYPE zif_abapgit_merge=>ty_merge_conflict. CLEAR ms_diff_file. READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. IF sy-subrc <> 0. RETURN. ENDIF. ms_diff_file-path = -path. ms_diff_file-filename = -filename. ms_diff_file-type = reverse( -filename ). FIND FIRST OCCURRENCE OF '.' IN ms_diff_file-type MATCH OFFSET lv_offs. ms_diff_file-type = reverse( substring( val = ms_diff_file-type len = lv_offs ) ). IF ms_diff_file-type <> 'xml' AND ms_diff_file-type <> 'abap'. ms_diff_file-type = 'other'. ENDIF. IF ms_diff_file-type = 'other' AND is_binary( iv_d1 = -source_data iv_d2 = -target_data ) = abap_true. ms_diff_file-type = 'binary'. ENDIF. IF ms_diff_file-type <> 'binary'. CREATE OBJECT ms_diff_file-o_diff EXPORTING iv_new = -source_data iv_old = -target_data. ENDIF. ENDMETHOD. METHOD toggle_merge_mode. IF mv_merge_mode = c_merge_mode-selection. mv_merge_mode = c_merge_mode-merge. ELSE. mv_merge_mode = c_merge_mode-selection. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. FIELD-SYMBOLS TYPE zif_abapgit_merge=>ty_merge_conflict. CASE ii_event->mv_action. WHEN c_actions-apply_merge OR c_actions-apply_source OR c_actions-apply_target OR c_actions-cancel. CASE ii_event->mv_action. WHEN c_actions-apply_merge. apply_merged_content( ii_event ). WHEN c_actions-apply_source. READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. -result_sha1 = -source_sha1. -result_data = -source_data. mo_merge->resolve_conflict( ). WHEN c_actions-apply_target. READ TABLE mt_conflicts ASSIGNING INDEX mv_current_conflict_index. -result_sha1 = -target_sha1. -result_data = -target_data. mo_merge->resolve_conflict( ). ENDCASE. mv_current_conflict_index = mv_current_conflict_index + 1. IF mv_current_conflict_index > lines( mt_conflicts ). CLEAR mv_current_conflict_index. ENDIF. IF mv_current_conflict_index IS NOT INITIAL. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled-page = mo_merge_page. rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. ENDIF. WHEN c_actions-toggle_mode. toggle_merge_mode( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar. ro_toolbar->add( iv_txt = 'Toggle merge mode' iv_act = c_actions-toggle_mode ). ro_toolbar->add( iv_txt = 'Cancel' iv_act = c_actions-cancel ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). resolve_diff( ). IF ms_diff_file IS INITIAL. zcx_abapgit_exception=>raise( 'no conflict found' ). ENDIF. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( |
| ). ri_html->add( render_diff( ms_diff_file ) ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_merge IMPLEMENTATION. METHOD constructor. super->constructor( ). mo_repo = io_repo. io_repo->select_branch( |{ zif_abapgit_git_definitions=>c_git_branch-heads_prefix }{ iv_target }| ). CREATE OBJECT mi_merge TYPE zcl_abapgit_merge EXPORTING io_repo = io_repo iv_source_branch = iv_source. mi_merge->run( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_merge. CREATE OBJECT lo_component EXPORTING io_repo = io_repo iv_source = iv_source iv_target = iv_target. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Merge' ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD show_file. FIELD-SYMBOLS LIKE LINE OF it_expanded. READ TABLE it_expanded ASSIGNING WITH KEY path_name COMPONENTS path = is_file-path name = is_file-name. IF sy-subrc = 0. IF -sha1 = is_result-sha1. ii_html->add( |{ -path }{ -name }{ -sha1(7) }| ). ELSE. ii_html->add( |{ -path }{ -name }{ -sha1(7) }| ). ENDIF. ELSE. ii_html->add( '' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. CASE ii_event->mv_action. WHEN c_actions-merge. IF mi_merge->has_conflicts( ) = abap_true. zcx_abapgit_exception=>raise( 'conflicts exists' ). ENDIF. IF mi_merge->get_result( )-stage->count( ) = 0. zcx_abapgit_exception=>raise( 'nothing to merge' ). ENDIF. IF mo_repo->get_local_settings( )-code_inspector_check_variant IS NOT INITIAL. rs_handled-page = zcl_abapgit_gui_page_code_insp=>create( io_repo = mo_repo io_stage = mi_merge->get_result( )-stage ). ELSE. rs_handled-page = zcl_abapgit_gui_page_commit=>create( io_repo = mo_repo io_stage = mi_merge->get_result( )-stage ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. WHEN c_actions-res_conflicts. rs_handled-page = zcl_abapgit_gui_page_merge_res=>create( io_repo = mo_repo io_merge_page = me io_merge = mi_merge ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar. ro_toolbar->add( iv_txt = 'Merge' iv_act = c_actions-merge iv_cur = abap_false ). IF mi_merge->has_conflicts( ) = abap_true. ro_toolbar->add( iv_txt = 'Resolve Conflicts' iv_act = c_actions-res_conflicts ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA: ls_merge TYPE zif_abapgit_merge=>ty_merge, lt_files LIKE ls_merge-stree, ls_result LIKE LINE OF ls_merge-result. FIELD-SYMBOLS LIKE LINE OF lt_files. register_handlers( ). ls_merge = mi_merge->get_result( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_package = abap_false iv_show_branch = abap_false ) ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '
Source' ). ri_html->add( ls_merge-source-name ). ri_html->add( '
Target' ). ri_html->add( ls_merge-target-name ). ri_html->add( '
Ancestor' ). ri_html->add( ls_merge-common-commit ). ri_html->add( '
' ). ri_html->add( '
' ). APPEND LINES OF ls_merge-stree TO lt_files. APPEND LINES OF ls_merge-ttree TO lt_files. APPEND LINES OF ls_merge-ctree TO lt_files. SORT lt_files BY path DESCENDING name ASCENDING. DELETE ADJACENT DUPLICATES FROM lt_files COMPARING path name. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). LOOP AT lt_files ASSIGNING . CLEAR ls_result. READ TABLE ls_merge-result INTO ls_result WITH KEY path_name COMPONENTS path = -path name = -name. ri_html->add( '' ). show_file( it_expanded = ls_merge-stree ii_html = ri_html is_file = is_result = ls_result ). show_file( it_expanded = ls_merge-ttree ii_html = ri_html is_file = is_result = ls_result ). show_file( it_expanded = ls_merge-ctree ii_html = ri_html is_file = is_result = ls_result ). show_file( it_expanded = ls_merge-result ii_html = ri_html is_file = is_result = ls_result ). ri_html->add( '' ). ENDLOOP. ri_html->add( '
SourceTargetAncestorResult
' ). ri_html->add( '
' ). ri_html->add( '' ). ri_html->add( ls_merge-conflict ). ri_html->add( '' ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_ex_pckage IMPLEMENTATION. METHOD constructor. super->constructor( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_form = get_form_schema( ). mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_ex_pckage. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Export Package to ZIP' ii_child_component = lo_component ). ENDMETHOD. METHOD export_package. DATA lv_package TYPE devclass. DATA lv_folder_logic TYPE string. DATA lv_ign_subpkg TYPE abap_bool. DATA lv_main_lang_only TYPE abap_bool. lv_package = mo_form_data->get( c_id-package ). lv_folder_logic = mo_form_data->get( c_id-folder_logic ). lv_ign_subpkg = mo_form_data->get( c_id-ignore_subpackages ). lv_main_lang_only = mo_form_data->get( c_id-main_lang_only ). zcl_abapgit_zip=>export_package( iv_package = lv_package iv_folder_logic = lv_folder_logic iv_ign_subpkg = lv_ign_subpkg iv_main_lang_only = lv_main_lang_only ). ENDMETHOD. METHOD get_form_schema. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'export-package-to-files' ). ro_form->text( iv_name = c_id-package iv_label = 'Package' iv_required = abap_true iv_upper_case = abap_true iv_side_action = c_event-choose_package iv_max = 30 )->radio( iv_name = c_id-folder_logic iv_label = 'Folder Logic' iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix iv_hint = 'Define how package folders are named in repository' )->option( iv_label = 'Prefix' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix )->option( iv_label = 'Full' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-full )->option( iv_label = 'Mixed' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-mixed )->checkbox( iv_name = c_id-ignore_subpackages iv_label = 'Ignore Subpackages' iv_hint = 'Export selected package only' )->checkbox( iv_name = c_id-main_lang_only iv_label = 'Serialize Main Language Only' iv_hint = 'Ignore translations, export just main language' )->command( iv_label = 'Export Package to ZIP' iv_action = c_event-export_package iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). CASE ii_event->mv_action. WHEN c_event-export_package. mo_validation_log = mo_form_util->validate( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_false. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. export_package( ). MESSAGE 'Package successfully exported' TYPE 'S'. rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. ENDIF. WHEN c_event-choose_package. mo_form_data->set( iv_key = c_id-package iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ). IF mo_form_data->get( c_id-package ) IS NOT INITIAL. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_ex_object IMPLEMENTATION. METHOD constructor. super->constructor( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_form_data->set( iv_key = c_id-only_main iv_val = abap_true ). mo_form = get_form_schema( ). mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_ex_object. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Export Objects to Files' ii_child_component = lo_component ). ENDMETHOD. METHOD export_object. DATA lv_object_type TYPE trobjtype. DATA lt_names TYPE STANDARD TABLE OF sobj_name WITH DEFAULT KEY. DATA lv_name LIKE LINE OF lt_names. DATA lv_list TYPE string. DATA lv_only_main TYPE abap_bool. lv_object_type = mo_form_data->get( c_id-object_type ). lv_list = mo_form_data->get( c_id-object_name ). lv_only_main = mo_form_data->get( c_id-only_main ). REPLACE ALL OCCURRENCES OF |\r| IN lv_list WITH ''. SPLIT lv_list AT |\n| INTO TABLE lt_names. LOOP AT lt_names INTO lv_name. IF lv_name IS INITIAL. CONTINUE. ENDIF. zcl_abapgit_zip=>export_object( iv_main_language_only = lv_only_main iv_object_type = lv_object_type iv_object_name = lv_name ). ENDLOOP. ENDMETHOD. METHOD get_form_schema. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'export-object-to-files' ). ro_form->text( iv_label = 'Object Type' iv_name = c_id-object_type iv_required = abap_true iv_upper_case = abap_true iv_side_action = c_event-choose_object_type ). ro_form->textarea( iv_label = 'Object Names' iv_name = c_id-object_name iv_required = abap_true iv_placeholder = 'One object name per line' iv_upper_case = abap_true ). ro_form->checkbox( iv_label = 'Only Main Language' iv_name = c_id-only_main ). ro_form->command( iv_label = 'Export' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-export )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). CASE ii_event->mv_action. WHEN c_event-export. mo_validation_log = mo_form_util->validate( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_false. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. export_object( ). MESSAGE 'Object successfully exported' TYPE 'S'. rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. ENDIF. WHEN c_event-choose_object_type. mo_form_data->set( iv_key = c_id-object_type iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TADIR-OBJECT' ) ). IF mo_form_data->get( c_id-object_type ) IS NOT INITIAL. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_diff_base IMPLEMENTATION. METHOD add_filter_sub_menu. DATA: lo_sub_filter TYPE REF TO zcl_abapgit_html_toolbar, lv_user TYPE string, lt_extensions TYPE SORTED TABLE OF string WITH UNIQUE DEFAULT KEY, lt_obj_types TYPE SORTED TABLE OF string WITH UNIQUE DEFAULT KEY, lt_users TYPE SORTED TABLE OF string WITH UNIQUE DEFAULT KEY. FIELD-SYMBOLS: LIKE LINE OF mt_diff_files, TYPE string. " Get unique filter values LOOP AT mt_diff_files ASSIGNING . lv_user = -changed_by. INSERT -type INTO TABLE lt_extensions. INSERT -obj_type INTO TABLE lt_obj_types. INSERT lv_user INTO TABLE lt_users. ENDLOOP. IF lines( lt_extensions ) > 1 OR lines( lt_obj_types ) > 1 OR lines( lt_users ) > 1. CREATE OBJECT lo_sub_filter EXPORTING iv_id = 'diff-filter'. IF lines( lt_users ) > 1. lo_sub_filter->add( iv_txt = 'Only my changes' iv_typ = zif_abapgit_html=>c_action_type-onclick iv_aux = |{ sy-uname }| iv_chk = abap_false ). ENDIF. " File extensions IF lines( lt_extensions ) > 1. lo_sub_filter->add( iv_txt = 'Extension' iv_typ = zif_abapgit_html=>c_action_type-separator ). LOOP AT lt_extensions ASSIGNING . lo_sub_filter->add( iv_txt = iv_typ = zif_abapgit_html=>c_action_type-onclick iv_aux = 'extension' iv_chk = abap_true ). ENDLOOP. ENDIF. " Object types IF lines( lt_obj_types ) > 1. lo_sub_filter->add( iv_txt = 'Object Type' iv_typ = zif_abapgit_html=>c_action_type-separator ). LOOP AT lt_obj_types ASSIGNING . lo_sub_filter->add( iv_txt = iv_typ = zif_abapgit_html=>c_action_type-onclick iv_aux = 'object-type' iv_chk = abap_true ). ENDLOOP. ENDIF. " Changed by IF lines( lt_users ) > 1. lo_sub_filter->add( iv_txt = 'Changed By' iv_typ = zif_abapgit_html=>c_action_type-separator ). LOOP AT lt_users ASSIGNING . lo_sub_filter->add( iv_txt = iv_typ = zif_abapgit_html=>c_action_type-onclick iv_aux = 'changed-by' iv_chk = abap_true ). ENDLOOP. ENDIF. io_menu->add( iv_txt = 'Filter' io_sub = lo_sub_filter ). ENDIF. ENDMETHOD. METHOD add_jump_sub_menu. DATA: lo_sub_jump TYPE REF TO zcl_abapgit_html_toolbar, lv_jump_target TYPE string. FIELD-SYMBOLS: LIKE LINE OF mt_diff_files. CREATE OBJECT lo_sub_jump EXPORTING iv_id = 'jump'. LOOP AT mt_diff_files ASSIGNING . lv_jump_target = -path && -filename. lo_sub_jump->add( iv_id = |li_jump_{ sy-tabix }| iv_txt = lv_jump_target iv_typ = zif_abapgit_html=>c_action_type-onclick ). ENDLOOP. io_menu->add( iv_txt = 'Jump' io_sub = lo_sub_jump ). ENDMETHOD. METHOD add_menu_begin. io_menu->add( iv_txt = c_action_texts-refresh_local iv_typ = zif_abapgit_html=>c_action_type-sapevent iv_act = c_actions-refresh_local iv_id = c_actions-refresh_local iv_title = c_action_titles-refresh_local ). io_menu->add( iv_txt = c_action_texts-refresh_all iv_typ = zif_abapgit_html=>c_action_type-sapevent iv_act = c_actions-refresh_all iv_id = c_actions-refresh_all iv_title = c_action_titles-refresh_all ). ENDMETHOD. METHOD add_menu_end. io_menu->add( iv_txt = 'Split/Unified' iv_act = c_actions-toggle_unified ). add_view_sub_menu( io_menu ). ENDMETHOD. METHOD add_view_sub_menu. DATA lo_sub_view TYPE REF TO zcl_abapgit_html_toolbar. DATA lv_txt TYPE string. CREATE OBJECT lo_sub_view EXPORTING iv_id = 'diff-view'. IF ms_view-hide_diffs = abap_true. lv_txt = 'Expand All Diffs'. ELSE. lv_txt = 'Collapse All Diffs'. ENDIF. lo_sub_view->add( iv_txt = lv_txt iv_act = c_actions-toggle_hide_diffs ). lo_sub_view->add( iv_txt = 'Show Hidden Characters' iv_act = c_actions-toggle_hidden_chars iv_chk = ms_view-hidden_chars ). lo_sub_view->add( iv_txt = 'Ignore Whitespace' iv_act = c_actions-toggle_ignore_indent iv_chk = ms_view-ignore_indent ). lo_sub_view->add( iv_txt = 'Ignore Comments' iv_act = c_actions-toggle_ignore_comments iv_chk = ms_view-ignore_comments ). lo_sub_view->add( iv_txt = 'Ignore Pretty-Print Case' iv_act = c_actions-toggle_ignore_case iv_chk = ms_view-ignore_case ). io_menu->add( iv_txt = 'View' io_sub = lo_sub_view ). ENDMETHOD. METHOD append_diff. DATA: lv_offs TYPE i, ls_r_dummy LIKE LINE OF it_remote ##NEEDED, ls_l_dummy LIKE LINE OF it_local ##NEEDED. FIELD-SYMBOLS: LIKE LINE OF it_remote, LIKE LINE OF it_local, LIKE LINE OF mt_diff_files. READ TABLE it_remote ASSIGNING WITH KEY file_path COMPONENTS path = is_status-path filename = is_status-filename. IF sy-subrc <> 0. ASSIGN ls_r_dummy TO . ENDIF. READ TABLE it_local ASSIGNING WITH KEY file-filename = is_status-filename file-path = is_status-path. IF sy-subrc <> 0. ASSIGN ls_l_dummy TO . ENDIF. IF IS INITIAL AND IS INITIAL. zcx_abapgit_exception=>raise( |DIFF: file not found { is_status-filename }| ). ENDIF. APPEND INITIAL LINE TO mt_diff_files ASSIGNING . -path = is_status-path. -filename = is_status-filename. -obj_type = is_status-obj_type. -obj_name = is_status-obj_name. -lstate = is_status-lstate. -rstate = is_status-rstate. IF -lstate IS NOT INITIAL AND -rstate IS NOT INITIAL. -fstate = c_fstate-both. ELSEIF -lstate IS NOT INITIAL. -fstate = c_fstate-local. ELSE. "rstate IS NOT INITIAL, lstate = empty. -fstate = c_fstate-remote. ENDIF. " Changed by IF -item-obj_type IS NOT INITIAL. -changed_by = zcl_abapgit_objects=>changed_by( is_item = -item iv_filename = is_status-filename ). ENDIF. IF -changed_by IS INITIAL. -changed_by = zcl_abapgit_objects_super=>c_user_unknown. ENDIF. " Extension IF -file-filename IS NOT INITIAL. -type = reverse( -file-filename ). ELSE. -type = reverse( -filename ). ENDIF. FIND FIRST OCCURRENCE OF '.' IN -type MATCH OFFSET lv_offs. -type = reverse( substring( val = -type len = lv_offs ) ). IF -type <> 'xml' AND -type <> 'abap'. -type = 'other'. ENDIF. IF -type = 'other' AND is_binary( iv_d1 = -data iv_d2 = -file-data ) = abap_true. -type = 'binary'. ENDIF. " Diff data IF -type <> 'binary'. IF -fstate = c_fstate-remote. " Remote file leading changes CREATE OBJECT -o_diff EXPORTING iv_new = -data iv_old = -file-data iv_ignore_indentation = ms_view-ignore_indent iv_ignore_comments = ms_view-ignore_comments iv_ignore_case = ms_view-ignore_case. ELSE. " Local leading changes or both were modified CREATE OBJECT -o_diff EXPORTING iv_new = -file-data iv_old = -data iv_ignore_indentation = ms_view-ignore_indent iv_ignore_comments = ms_view-ignore_comments iv_ignore_case = ms_view-ignore_case. ENDIF. ENDIF. ENDMETHOD. METHOD calculate_diff. DATA: lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt, lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt, lt_status TYPE zif_abapgit_definitions=>ty_results_tt. DATA li_exit TYPE REF TO zif_abapgit_exit. 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( ). lt_status = zcl_abapgit_repo_status=>calculate( mo_repo ). li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->pre_calculate_repo_status( EXPORTING is_repo_meta = mo_repo->ms_data CHANGING ct_local = lt_local ct_remote = lt_remote ). IF is_file IS NOT INITIAL. " Diff for one file READ TABLE lt_status ASSIGNING WITH KEY path = is_file-path filename = is_file-filename. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |File { is_file-path }{ is_file-filename } not found| ). ENDIF. append_diff( it_remote = lt_remote it_local = lt_local is_status = ). ELSEIF is_object IS NOT INITIAL. " Diff for whole object LOOP AT lt_status ASSIGNING USING KEY sec_key WHERE obj_type = is_object-obj_type AND obj_name = is_object-obj_name AND match IS INITIAL. append_diff( it_remote = lt_remote it_local = lt_local is_status = ). ENDLOOP. ELSE. " Diff for the whole repo SORT lt_status BY path ASCENDING filename ASCENDING. LOOP AT lt_status ASSIGNING WHERE match IS INITIAL. IF is_file_requested( it_files = it_files is_status = ) = abap_true. append_diff( it_remote = lt_remote it_local = lt_local is_status = ). ENDIF. ENDLOOP. ENDIF. ENDMETHOD. METHOD constructor. DATA: lv_ts TYPE timestamp. super->constructor( ). mv_unified = zcl_abapgit_persistence_user=>get_instance( )->get_diff_unified( ). mv_repo_key = iv_key. mo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). GET TIME STAMP FIELD lv_ts. mv_seed = |diff{ lv_ts }|. " Generate based on time ASSERT is_file IS INITIAL OR is_object IS INITIAL. " just one passed calculate_diff( is_file = is_file is_object = is_object it_files = it_files ). IF lines( mt_diff_files ) = 0. zcx_abapgit_exception=>raise( 'There are no differences to show. The local state completely matches the remote repository.' ). ENDIF. ENDMETHOD. METHOD get_normalized_fname_with_path. rv_filename = normalize_path( is_diff-path ) && `_` && normalize_filename( is_diff-filename ). ENDMETHOD. METHOD get_page_layout. TRY. IF zcl_abapgit_persistence_user=>get_instance( )->get_diff_unified( ) = abap_true. rv_page_layout = zcl_abapgit_gui_page=>c_page_layout-centered. ELSE. rv_page_layout = zcl_abapgit_gui_page=>c_page_layout-full_width. ENDIF. CATCH zcx_abapgit_exception. rv_page_layout = zcl_abapgit_gui_page=>c_page_layout-full_width. ENDTRY. ENDMETHOD. METHOD has_diffs. LOOP AT it_diffs TRANSPORTING NO FIELDS WHERE result IS NOT INITIAL. rv_has_diffs = abap_true. EXIT. ENDLOOP. ENDMETHOD. METHOD insert_nav. ENDMETHOD. METHOD is_binary. FIELD-SYMBOLS LIKE iv_d1. IF iv_d1 IS NOT INITIAL. " One of them might be new and so empty ASSIGN iv_d1 TO . ELSE. ASSIGN iv_d2 TO . ENDIF. rv_yes = zcl_abapgit_utils=>is_binary( ). ENDMETHOD. METHOD is_file_requested. IF lines( it_files ) = 0. rv_is_file_requested = abap_true. RETURN. ENDIF. READ TABLE it_files WITH KEY file-path = is_status-path file-filename = is_status-filename TRANSPORTING NO FIELDS. rv_is_file_requested = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD is_refresh. FIND FIRST OCCURRENCE OF REGEX |^{ c_actions-refresh_prefix }| IN iv_action. rv_is_refrseh = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD modify_files_before_diff_calc. DATA ls_file LIKE LINE OF rt_files. FIELD-SYMBOLS TYPE ty_file_diff. " We need to supply files again in calculate_diff. Because " we only want to refresh the visible files. Otherwise all " diff files would appear. " Which is not wanted when we previously only selected particular files. LOOP AT it_diff_files_old ASSIGNING . CLEAR ls_file. MOVE-CORRESPONDING TO ls_file-file. INSERT ls_file INTO TABLE rt_files. ENDLOOP. 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 refresh. DATA: lt_diff_files_old TYPE ty_file_diffs, lt_files TYPE zif_abapgit_definitions=>ty_stage_tt. lt_diff_files_old = mt_diff_files. CASE iv_action. WHEN c_actions-refresh_all. refresh_full( ). WHEN c_actions-refresh_local. refresh_local( ). WHEN OTHERS. refresh_local_object( iv_action ). ENDCASE. lt_files = modify_files_before_diff_calc( lt_diff_files_old ). calculate_diff( it_files = lt_files ). 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 = to_upper( lv_obj_type ) iv_obj_name = to_upper( lv_obj_name ) ). ELSE. zcx_abapgit_exception=>raise( |Invalid refresh action { iv_action }| ). ENDIF. ENDMETHOD. METHOD render_beacon. DATA: lv_beacon TYPE string, lt_beacons TYPE zif_abapgit_definitions=>ty_string_tt. CREATE OBJECT ri_html TYPE zcl_abapgit_html. 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. ELSE. lv_beacon = '---'. ENDIF. ri_html->add( '' ). ri_html->add( '' ). render_beacon_begin_of_row( ii_html = ri_html is_diff = is_diff ). IF mv_unified = abap_true. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( |@@ { is_diff_line-new_num } @@ { lv_beacon }| ). ELSE. ri_html->add( |@@ { is_diff_line-new_num } @@ { lv_beacon }| ). ENDIF. ri_html->add( '' ). ri_html->add( '' ). ENDMETHOD. METHOD render_beacon_begin_of_row. ii_html->add( '' ). ENDMETHOD. METHOD render_diff. DATA lv_display TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( |
| ). ri_html->add( render_diff_head( is_diff ) ). " Content IF ms_view-hide_diffs = abap_true. lv_display = ' nodisplay'. ENDIF. IF is_diff-type <> 'binary'. ri_html->add( |
| ). ri_html->add( || ). ri_html->add( render_table_head( is_diff ) ). ri_html->add( render_lines( is_diff ) ). ri_html->add( '
' ). ELSE. ri_html->add( '
' ). ri_html->add( 'The content seems to be binary.' ). ri_html->add( 'Cannot display as diff.' ). ENDIF. ri_html->add( '
' ). ri_html->add( '
' ). ENDMETHOD. METHOD render_diff_head. DATA: ls_stats TYPE zif_abapgit_definitions=>ty_count, lv_icon TYPE string, lv_jump TYPE string, lv_link TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). IF ms_view-hide_diffs = abap_true. lv_icon = 'chevron-right'. ELSE. lv_icon = 'chevron-down'. ENDIF. ri_html->add_icon( iv_name = lv_icon iv_hint = 'Collapse/Expand' iv_class = 'cursor-pointer' iv_onclick = 'onDiffCollapse(event)' ). IF is_diff-type <> 'binary'. ls_stats = is_diff-o_diff->stats( ). IF is_diff-fstate = c_fstate-both. " Merge stats into 'update' if both were changed ls_stats-update = ls_stats-update + ls_stats-insert + ls_stats-delete. CLEAR: ls_stats-insert, ls_stats-delete. ENDIF. ri_html->add( |+ { ls_stats-insert }| ). ri_html->add( |- { ls_stats-delete }| ). ri_html->add( |~ { ls_stats-update }| ). ENDIF. " no links for nonexistent or deleted objects IF NOT ( is_diff-lstate = zif_abapgit_definitions=>c_state-unchanged AND is_diff-rstate = zif_abapgit_definitions=>c_state-added ) AND NOT is_diff-lstate = zif_abapgit_definitions=>c_state-deleted. lv_jump = zcl_abapgit_html_action_utils=>jump_encode( iv_obj_type = |{ is_diff-obj_type }| iv_obj_name = |{ is_diff-obj_name }| iv_filename = is_diff-filename ). lv_link = ri_html->a( iv_txt = |{ is_diff-path }{ is_diff-filename }| iv_act = |{ zif_abapgit_definitions=>c_action-jump }?{ lv_jump }| ). ENDIF. IF lv_link IS NOT INITIAL. ri_html->add( |{ lv_link }| ). ELSE. ri_html->add( |{ is_diff-path }{ is_diff-filename }| ). ENDIF. ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = is_diff-lstate iv_rstate = is_diff-rstate ) ). render_diff_head_after_state( ii_html = ri_html is_diff = is_diff ). ri_html->add( 'Last Changed by: ' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name( is_diff-changed_by ) ). ri_html->add( '' ). ri_html->add( '
' ). ENDMETHOD. METHOD render_diff_head_after_state. IF is_diff-fstate = c_fstate-both AND mv_unified = abap_true. ii_html->add( 'Attention: Unified mode' && ' highlighting for MM assumes local file is newer ! ' ). ENDIF. IF is_diff-obj_type IS NOT INITIAL AND is_diff-obj_name IS NOT INITIAL. ii_html->add( '' ). ii_html->add_a( iv_txt = ii_html->icon( iv_name = 'redo-alt-solid' iv_class = 'pad-sides' iv_hint = 'Local refresh of this object' ) iv_act = |{ c_actions-refresh_local_object }_{ is_diff-obj_type }_{ is_diff-obj_name }| iv_class = |url| ). ii_html->add( '' ). ENDIF. ENDMETHOD. METHOD render_lines. DATA: lo_highlighter TYPE REF TO zcl_abapgit_syntax_highlighter, lt_diffs TYPE zif_abapgit_definitions=>ty_diffs_tt, lv_insert_nav TYPE abap_bool, lv_tabix TYPE syst-tabix. FIELD-SYMBOLS LIKE LINE OF lt_diffs. FIELD-SYMBOLS LIKE LINE OF lt_diffs. lo_highlighter = zcl_abapgit_syntax_factory=>create( iv_filename = is_diff-filename iv_hidden_chars = ms_view-hidden_chars ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. lt_diffs = is_diff-o_diff->get( ). IF has_diffs( lt_diffs ) = abap_false. ri_html->add( render_line_no_diffs( ) ). RETURN. ENDIF. lv_insert_nav = insert_nav( ). LOOP AT lt_diffs ASSIGNING . lv_tabix = sy-tabix. IF -short = abap_false. lv_insert_nav = abap_true. CONTINUE. ENDIF. IF lv_insert_nav = abap_true. " Insert separator line with navigation " Get line where diff really starts READ TABLE lt_diffs ASSIGNING INDEX lv_tabix + 8. IF sy-subrc <> 0. " Occurs only for small files/diffs with less than 8 lines. " Therefore let's use the first line as beacon ASSIGN TO . ASSERT IS ASSIGNED. ENDIF. ri_html->add( render_beacon( is_diff_line = is_diff = is_diff ) ). lv_insert_nav = abap_false. ENDIF. IF lo_highlighter IS BOUND. -new = lo_highlighter->process_line( -new ). -old = lo_highlighter->process_line( -old ). ELSE. -new = escape( val = -new format = cl_abap_format=>e_html_attr ). -old = escape( val = -old format = cl_abap_format=>e_html_attr ). ENDIF. CONDENSE -new_num. "get rid of leading spaces CONDENSE -old_num. IF mv_unified = abap_true. ri_html->add( render_line_unified( is_diff_line = ) ). ELSE. ri_html->add( render_line_split( is_diff_line = iv_filename = get_normalized_fname_with_path( is_diff ) iv_fstate = is_diff-fstate iv_index = lv_tabix ) ). ENDIF. ENDLOOP. IF mv_unified = abap_true. ri_html->add( render_line_unified( ) ). " Release delayed lines ENDIF. ENDMETHOD. METHOD render_line_no_diffs. DATA ls_diff_line TYPE zif_abapgit_definitions=>ty_diff. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF mv_unified = abap_true. ls_diff_line-old = 'No diffs found'. ri_html->add( render_line_unified( is_diff_line = ls_diff_line ) ). ELSE. ls_diff_line-new = 'No diffs found'. ri_html->add( render_line_split( is_diff_line = ls_diff_line iv_filename = '' iv_fstate = '' iv_index = 1 ) ). ENDIF. ENDMETHOD. METHOD render_line_split. DATA: lv_new TYPE string, lv_old TYPE string, lv_mark TYPE string, lv_bg TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. " Note: CSS classes "new" and "old" are used to enable column-based copy to clipboard " New line lv_mark = ` `. IF is_diff_line-result IS NOT INITIAL. IF iv_fstate = c_fstate-both OR is_diff_line-result = zif_abapgit_definitions=>c_diff-update. lv_bg = ' diff_upd'. lv_mark = `~`. ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-insert. lv_bg = ' diff_ins'. lv_mark = `+`. ENDIF. ENDIF. lv_new = || && |{ lv_mark }| && |{ is_diff_line-new }|. " Old line CLEAR lv_bg. lv_mark = ` `. IF is_diff_line-result IS NOT INITIAL. IF iv_fstate = c_fstate-both OR is_diff_line-result = zif_abapgit_definitions=>c_diff-update. lv_bg = ' diff_upd'. lv_mark = `~`. ELSEIF is_diff_line-result = zif_abapgit_definitions=>c_diff-delete. lv_bg = ' diff_del'. lv_mark = `-`. ENDIF. ENDIF. lv_old = || && |{ lv_mark }| && |{ is_diff_line-old }|. " render line, inverse sides if remote is newer ri_html->add( '' ). render_line_split_row( ii_html = ri_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 ). ri_html->add( '' ). ENDMETHOD. METHOD render_line_split_row. IF iv_fstate = c_fstate-remote. " Remote file leading changes ii_html->add( iv_old ). " local ii_html->add( iv_new ). " remote ELSE. " Local leading changes or both were modified ii_html->add( iv_new ). " local ii_html->add( iv_old ). " remote ENDIF. ENDMETHOD. METHOD render_line_unified. FIELD-SYMBOLS LIKE LINE OF mt_delayed_lines. CREATE OBJECT ri_html TYPE zcl_abapgit_html. " Note: CSS classes "new" and "old" are used to enable column-based copy to clipboard " Release delayed subsequent update lines IF is_diff_line-result <> zif_abapgit_definitions=>c_diff-update. LOOP AT mt_delayed_lines ASSIGNING . ri_html->add( '' ). ri_html->add( || && || && |-| && |{ -old }| ). ri_html->add( '' ). ENDLOOP. LOOP AT mt_delayed_lines ASSIGNING . ri_html->add( '' ). ri_html->add( || && || && |+| && |{ -new }| ). ri_html->add( '' ). ENDLOOP. CLEAR mt_delayed_lines. ENDIF. ri_html->add( '' ). CASE is_diff_line-result. WHEN zif_abapgit_definitions=>c_diff-update. APPEND is_diff_line TO mt_delayed_lines. " Delay output of subsequent updates WHEN zif_abapgit_definitions=>c_diff-insert. ri_html->add( || && || && |+| && |{ is_diff_line-new }| ). WHEN zif_abapgit_definitions=>c_diff-delete. ri_html->add( || && || && |-| && |{ is_diff_line-old }| ). WHEN OTHERS. "none ri_html->add( || && || && | | && |{ is_diff_line-old }| ). ENDCASE. ri_html->add( '' ). ENDMETHOD. METHOD render_scripts. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). ri_html->add( 'restoreScrollPosition();' ). ri_html->add( 'var gHelper = new DiffHelper({' ). ri_html->add( | seed: "{ mv_seed }",| ). ri_html->add( ' ids: {' ). ri_html->add( ' jump: "jump",' ). ri_html->add( ' diffList: "diff-list",' ). ri_html->add( ' filterMenu: "diff-filter",' ). ri_html->add( ' }' ). ri_html->add( '});' ). ri_html->add( 'addMarginBottom();' ). ri_html->add( 'var gGoJumpPalette = new CommandPalette(enumerateJumpAllFiles, {' ). ri_html->add( ' toggleKey: "F2",' ). ri_html->add( ' hotkeyDescription: "Jump to File ..."' ). ri_html->add( '});' ). " Feature for selecting ABAP code by column and copy to clipboard ri_html->add( 'var columnSelection = new DiffColumnSelection();' ). ENDMETHOD. METHOD render_table_head. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( '' ). IF mv_unified = abap_true. render_table_head_unified( ri_html ). ELSE. render_table_head_non_unified( ii_html = ri_html is_diff = is_diff ). ENDIF. ri_html->add( '' ). ri_html->add( '' ). ENDMETHOD. METHOD render_table_head_non_unified. ii_html->add( '' ). ii_html->add( '' ). ii_html->add( 'LOCAL' ). ii_html->add( '' ). ii_html->add( '' ). ii_html->add( 'REMOTE' ). ENDMETHOD. METHOD render_table_head_unified. ii_html->add( 'old' ). ii_html->add( 'new' ). ii_html->add( '' ). ii_html->add( 'code' ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA ls_view LIKE ms_view. ls_view = ms_view. CASE ii_event->mv_action. WHEN c_actions-toggle_unified. " Toggle file display mv_unified = zcl_abapgit_persistence_user=>get_instance( )->toggle_diff_unified( ). rs_handled-page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Diff' iv_page_layout = get_page_layout( ) ii_page_menu_provider = me ii_child_component = me ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. WHEN c_actions-toggle_hide_diffs. " Toggle display of diffs ms_view-hide_diffs = boolc( ms_view-hide_diffs = abap_false ). WHEN c_actions-toggle_hidden_chars. " Toggle display of hidden characters ms_view-hidden_chars = boolc( ms_view-hidden_chars = abap_false ). WHEN c_actions-toggle_ignore_indent. " Toggle ignore indentation ms_view-ignore_indent = boolc( ms_view-ignore_indent = abap_false ). WHEN c_actions-toggle_ignore_comments. " Toggle ignore comments ms_view-ignore_comments = boolc( ms_view-ignore_comments = abap_false ). WHEN c_actions-toggle_ignore_case. " Toggle case sensitivity ms_view-ignore_case = boolc( ms_view-ignore_case = abap_false ). WHEN OTHERS. IF is_refresh( ii_event->mv_action ) = abap_true. refresh( ii_event->mv_action ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. ENDCASE. " If view has changed, refresh local files recalculating diff, and update menu IF ms_view <> ls_view. IF ms_view-hide_diffs = ls_view-hide_diffs. refresh( c_actions-refresh_local ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. ls_hotkey_action-ui_component = 'Diff'. ls_hotkey_action-description = |Refresh Local|. ls_hotkey_action-action = c_actions-refresh_local. ls_hotkey_action-hotkey = |r|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Refresh All|. ls_hotkey_action-action = c_actions-refresh_all. ls_hotkey_action-hotkey = |a|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Toggle Split/Unified|. ls_hotkey_action-action = c_actions-toggle_unified. ls_hotkey_action-hotkey = |u|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Toggle Hidden Characters|. ls_hotkey_action-action = c_actions-toggle_hidden_chars. ls_hotkey_action-hotkey = |h|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar EXPORTING iv_id = 'toolbar-main'. add_menu_begin( ro_toolbar ). add_jump_sub_menu( ro_toolbar ). add_filter_sub_menu( ro_toolbar ). add_menu_end( ro_toolbar ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA: ls_diff_file LIKE LINE OF mt_diff_files, li_progress TYPE REF TO zif_abapgit_progress. CREATE OBJECT ri_html TYPE zcl_abapgit_html. li_progress = zcl_abapgit_progress=>get_instance( lines( mt_diff_files ) ). ri_html->add( `
` ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( mo_repo ) ). ri_html->add( `
` ). ri_html->add( |
| ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_js_error_banner( ) ). LOOP AT mt_diff_files INTO ls_diff_file. li_progress->show( iv_current = sy-tabix iv_text = |Render Diff - { ls_diff_file-filename }| ). ri_html->add( render_diff( ls_diff_file ) ). ENDLOOP. IF sy-subrc <> 0. ri_html->add( |No more diffs| ). ENDIF. ri_html->add( '
' ). register_deferred_script( render_scripts( ) ). li_progress->off( ). register_handlers( ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_diff IMPLEMENTATION. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_diff. CREATE OBJECT lo_component EXPORTING iv_key = iv_key is_file = is_file is_object = is_object it_files = it_files. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Diff' iv_page_layout = get_page_layout( ) ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_debuginfo IMPLEMENTATION. METHOD build_toolbar. CREATE OBJECT ro_menu EXPORTING iv_id = 'toolbar-debug'. ro_menu->add( iv_txt = 'Save' iv_act = c_action-save ). ro_menu->add( iv_txt = 'Back' iv_act = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_debuginfo. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Debug Info' io_page_menu = build_toolbar( ) ii_child_component = lo_component ). ENDMETHOD. METHOD get_jump_object. DATA lv_encode TYPE string. DATA li_html TYPE REF TO zif_abapgit_html. CREATE OBJECT li_html TYPE zcl_abapgit_html. lv_encode = zcl_abapgit_html_action_utils=>jump_encode( iv_obj_type = |{ iv_obj_type }| iv_obj_name = |{ iv_obj_name }| ). rv_html = li_html->a( iv_txt = |{ iv_obj_name }| iv_act = |{ zif_abapgit_definitions=>c_action-jump }?{ lv_encode }| ). ENDMETHOD. METHOD render_debug_info. DATA: ls_release TYPE zif_abapgit_environment=>ty_release_sp, lv_gui_version TYPE string, lv_devclass TYPE devclass, lo_frontend_serv TYPE REF TO zif_abapgit_frontend_services. lo_frontend_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). TRY. lo_frontend_serv->get_gui_version( IMPORTING ev_gui_version_string = lv_gui_version ). CATCH zcx_abapgit_exception ##NO_HANDLER. " Continue rendering even if this fails ENDTRY. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. ri_html->add( '

abapGit - Standalone Version

' ). ri_html->add( '
To keep abapGit up-to-date (or also to contribute) you need to' ). ri_html->add( |install it as a repository ({ ri_html->a( iv_txt = 'Developer Version' iv_act = 'https://github.com/abapGit/abapGit' iv_typ = zif_abapgit_html=>c_action_type-url ) }).
| ). ELSE. lv_devclass = zcl_abapgit_factory=>get_tadir( )->get_object_package( iv_object = 'CLAS' iv_obj_name = 'ZCX_ABAPGIT_EXCEPTION' ). ri_html->add( '

abapGit - Developer Version

' ). ri_html->add( |
abapGit is installed in package { lv_devclass }
| ). ENDIF. ri_html->add( '
' ). ri_html->add_a( iv_txt = 'Contribution guidelines for abapGit' iv_act = |{ zif_abapgit_definitions=>c_action-url }?url=https://github.com/abapGit/abapGit/blob/main/CONTRIBUTING.md| iv_class = |url| ). ri_html->add( '
' ). ls_release = zcl_abapgit_factory=>get_environment( )->get_basis_release( ). ri_html->add( '

Environment

' ). ri_html->add( || ). ri_html->add( || ). ri_html->add( || ). ri_html->add( || ). ri_html->add( || ). ri_html->add( || ). ri_html->add( || ). ri_html->add( || ). ri_html->add( |
abapGit version:{ zif_abapgit_version=>c_abap_version }
XML version: { zif_abapgit_version=>c_xml_version }
GUI version: { lv_gui_version }
APACK version: { zcl_abapgit_apack_migration=>c_apack_interface_version }
LCL_TIME: { zcl_abapgit_git_time=>get_unix( ) }
SY time: { sy-datum } { sy-uzeit } { sy-tzone }
SY release: { ls_release-release } SP { ls_release-sp }
| ). ri_html->add( |
| ). ENDMETHOD. METHOD render_exit_info. DATA lt_source TYPE string_table. DATA ls_class_key TYPE seoclskey. DATA lo_oo_serializer TYPE REF TO zcl_abapgit_oo_serializer. DATA lo_class TYPE REF TO cl_oo_class. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '

User Exits

' ). IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. " Standalone version lt_source = zcl_abapgit_factory=>get_sap_report( )->read_report( c_exit_standalone ). IF sy-subrc = 0. ri_html->add( |
User exits are active (include { get_jump_object( iv_obj_type = 'PROG' iv_obj_name = c_exit_standalone ) } found)

| ). ri_html->add( render_exit_info_methods( lt_source ) ). ELSE. ri_html->add( |
No user exits implemented (include { c_exit_standalone } not found)

| ). ENDIF. ELSE. " Developer version TRY. ls_class_key-clsname = c_exit_class. DO. CREATE OBJECT lo_oo_serializer. lt_source = lo_oo_serializer->serialize_abap_clif_source( ls_class_key ). ri_html->add( '
' ). ri_html->add( |User exits are active (class { get_jump_object( ls_class_key-clsname ) } found)| ). ri_html->add( '

' ). ri_html->add( render_exit_info_methods( it_source = lt_source iv_clsname = ls_class_key-clsname ) ). " Is there a super class of exit? CREATE OBJECT lo_class EXPORTING clsname = ls_class_key-clsname. ls_class_key-clsname = lo_class->get_superclass( ). IF ls_class_key-clsname IS INITIAL. EXIT. ENDIF. ri_html->add( '
' ). ENDDO. CATCH cx_root. ri_html->add( |
No user exits implemented (class { c_exit_class } not found)

| ). ENDTRY. ENDIF. ENDMETHOD. METHOD render_exit_info_methods. DATA: lo_scanner TYPE REF TO cl_oo_source_scanner_class, lx_exc TYPE REF TO cx_root, lt_methods TYPE cl_oo_source_scanner_class=>type_method_implementations, lv_method LIKE LINE OF lt_methods, lt_source TYPE seop_source_string, lv_count TYPE i, lv_source TYPE string, lv_rest TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). TRY. lo_scanner = cl_oo_source_scanner_class=>create_class_scanner( clif_name = iv_clsname source = it_source ). lo_scanner->scan( ). lt_methods = lo_scanner->get_method_implementations( ). LOOP AT lt_methods INTO lv_method WHERE table_line CS c_exit_interface. lt_source = lo_scanner->get_method_impl_source( lv_method ). DELETE lt_source INDEX 1. DELETE lt_source INDEX lines( lt_source ). CONCATENATE LINES OF lt_source INTO lv_source. lv_source = to_upper( condense( val = lv_source del = ` ` ) ). SPLIT lv_method AT '~' INTO lv_rest lv_method. ri_html->add( || ). lv_count = lv_count + 1. ENDLOOP. IF lv_count = 0. ri_html->add( || ). ENDIF. CATCH cx_root INTO lx_exc. ri_html->add( || ). ENDTRY. ri_html->add( '
ExitImplemented?
{ lv_method }| ). IF lv_source IS INITIAL OR lv_source = 'RETURN.' OR lv_source = 'EXIT.'. ri_html->add( 'No' ). ELSE. ri_html->add( 'Yes' ). ENDIF. ri_html->add( |
No exit methods implemented
{ lx_exc->get_text( ) }
' ). ENDMETHOD. METHOD render_scripts. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). ri_html->add( 'debugOutput("
Browser:" + navigator.userAgent + ' && '"
Frontend time:" + new Date() + "
", "debug_info");' ). ENDMETHOD. METHOD render_supported_object_types. DATA: lv_list TYPE string, li_html TYPE REF TO zif_abapgit_html, lt_types TYPE zcl_abapgit_objects=>ty_types_tt, lv_type LIKE LINE OF lt_types, lt_obj TYPE STANDARD TABLE OF ko100 WITH DEFAULT KEY, lv_class TYPE seoclsname, li_object TYPE REF TO zif_abapgit_object, ls_item TYPE zif_abapgit_definitions=>ty_item, ls_metadata TYPE zif_abapgit_definitions=>ty_metadata, lv_step TYPE zif_abapgit_definitions=>ty_deserialization_step, lt_steps TYPE zif_abapgit_definitions=>ty_deserialization_step_tt. FIELD-SYMBOLS: TYPE ko100. CALL FUNCTION 'TR_OBJECT_TABLE' TABLES wt_object_text = lt_obj. lt_types = zcl_abapgit_objects=>supported_list( ). CREATE OBJECT li_html TYPE zcl_abapgit_html. rv_html = '

Object Types

'. rv_html = rv_html && li_html->a( iv_txt = 'Complete list of object types supported by abapGit' iv_act = |{ zif_abapgit_definitions=>c_action-url }?url=https://docs.abapgit.org/ref-supported.html| iv_class = |url| ). rv_html = rv_html && |

Supported object types in this system:

|. rv_html = rv_html && ||. rv_html = rv_html && ||. rv_html = rv_html && ||. rv_html = rv_html && ||. LOOP AT lt_types INTO lv_type. lv_class = 'ZCL_ABAPGIT_OBJECT_' && lv_type. rv_html = rv_html && ||. rv_html = rv_html && ||. READ TABLE lt_obj ASSIGNING WITH KEY pgmid = 'R3TR' object = lv_type. IF sy-subrc = 0. rv_html = rv_html && ||. ELSE. rv_html = rv_html && ||. ENDIF. TRY. ls_item-obj_type = lv_type. ls_item-obj_name = 'TEST'. CREATE OBJECT li_object TYPE (lv_class) EXPORTING is_item = ls_item iv_language = sy-langu. rv_html = rv_html && ||. CATCH cx_sy_create_object_error zcx_abapgit_exception. TRY. " 2nd step, try looking for plugins CREATE OBJECT li_object TYPE zcl_abapgit_objects_bridge EXPORTING is_item = ls_item. CATCH cx_sy_create_object_error zcx_abapgit_exception. rv_html = rv_html && ||. CONTINUE. ENDTRY. rv_html = rv_html && ||. ENDTRY. ls_metadata = li_object->get_metadata( ). rv_html = rv_html && ||. lt_steps = li_object->get_deserialize_steps( ). CLEAR lv_list. LOOP AT lt_steps INTO lv_step. CASE lv_step. WHEN zif_abapgit_object=>gc_step_id-early. lv_step = |{ lv_step } (1)|. WHEN zif_abapgit_object=>gc_step_id-ddic. lv_step = |{ lv_step } (2)|. WHEN zif_abapgit_object=>gc_step_id-abap. lv_step = |{ lv_step } (3)|. WHEN zif_abapgit_object=>gc_step_id-late. lv_step = |{ lv_step } (4)|. WHEN OTHERS. ASSERT 1 = 2. ENDCASE. IF lv_list IS INITIAL. lv_list = lv_step. ELSE. lv_list = lv_list && `, ` && lv_step. ENDIF. ENDLOOP. rv_html = rv_html && ||. rv_html = rv_html && ||. ENDLOOP. rv_html = rv_html && |
ObjectDescriptionClassVersionSteps
{ lv_type }{ -text }No description{ get_jump_object( lv_class ) }{ lv_class } - error instantiating class{ get_jump_object( lv_class ) } (Plug-in){ ls_metadata-version }{ lv_list }
|. rv_html = rv_html && |
|. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA: lv_path TYPE string, lv_filename TYPE string, li_fe_serv TYPE REF TO zif_abapgit_frontend_services. CASE ii_event->mv_action. WHEN c_action-save. CONCATENATE 'abapGit_Debug_Info_' sy-datlo '_' sy-timlo '.html' INTO lv_filename. li_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). lv_path = li_fe_serv->show_file_save_dialog( iv_title = 'abapGit - Debug Info' iv_extension = 'html' iv_default_filename = lv_filename ). li_fe_serv->file_download( iv_path = lv_path iv_xstr = zcl_abapgit_convert=>string_to_xstring_utf8( mv_html ) ). MESSAGE 'abapGit Debug Info successfully saved' TYPE 'S'. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN OTHERS. ASSERT 1 = 1. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( render_debug_info( ) ). ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( render_exit_info( ) ). ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( render_supported_object_types( ) ). ri_html->add( '
' ). mv_html = 'abapGit Debug Info'. mv_html = |{ ri_html->render( ) }|. register_deferred_script( render_scripts( ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_data IMPLEMENTATION. METHOD add_via_transport. DATA lv_trkorr TYPE trkorr. DATA ls_request TYPE zif_abapgit_cts_api=>ty_transport_data. DATA ls_key LIKE LINE OF ls_request-keys. DATA lv_where TYPE string. DATA ls_config TYPE zif_abapgit_data_config=>ty_config. lv_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_transport( ). IF lv_trkorr IS INITIAL. RETURN. ENDIF. ls_request = zcl_abapgit_factory=>get_cts_api( )->read( lv_trkorr ). IF lines( ls_request-keys ) = 0. zcx_abapgit_exception=>raise( |No keys found, select task| ). ENDIF. LOOP AT ls_request-keys INTO ls_key WHERE object = 'TABU'. ASSERT ls_key-objname IS NOT INITIAL. ASSERT ls_key-tabkey IS NOT INITIAL. CLEAR ls_config. ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. ls_config-name = to_upper( ls_key-objname ). lv_where = concatenated_key_to_where( iv_table = ls_key-objname iv_tabkey = ls_key-tabkey ). APPEND lv_where TO ls_config-where. mi_config->add_config( ls_config ). ENDLOOP. ENDMETHOD. METHOD build_where. DATA lv_where LIKE LINE OF rt_where. SPLIT io_map->get( c_id-where ) AT |\n| INTO TABLE rt_where. DELETE rt_where WHERE table_line IS INITIAL. LOOP AT rt_where INTO lv_where. IF strlen( lv_where ) <= 2. DELETE rt_where INDEX sy-tabix. ENDIF. ENDLOOP. ENDMETHOD. METHOD concatenated_key_to_where. DATA lo_structdescr TYPE REF TO cl_abap_structdescr. DATA lo_typedescr TYPE REF TO cl_abap_typedescr. DATA lt_fields TYPE zcl_abapgit_data_utils=>ty_names. DATA lv_field LIKE LINE OF lt_fields. DATA lv_table TYPE tadir-obj_name. DATA lv_length TYPE i. DATA lv_tabix TYPE i. DATA lv_key TYPE c LENGTH 900. lv_key = iv_tabkey. lo_structdescr ?= cl_abap_typedescr=>describe_by_name( iv_table ). lv_table = iv_table. lt_fields = zcl_abapgit_data_utils=>list_key_fields( lv_table ). LOOP AT lt_fields INTO lv_field. lv_tabix = sy-tabix. lo_typedescr = cl_abap_typedescr=>describe_by_name( |{ iv_table }-{ lv_field }| ). lv_length = lo_typedescr->length / cl_abap_char_utilities=>charsize. IF lv_tabix = 1 AND lo_typedescr->get_relative_name( ) = 'MANDT'. lv_key = lv_key+lv_length. CONTINUE. ENDIF. IF lv_key = |*|. EXIT. " current loop ENDIF. IF NOT rv_where IS INITIAL. rv_where = |{ rv_where } AND |. ENDIF. rv_where = |{ rv_where }{ to_lower( lv_field ) } = '{ lv_key(lv_length) }'|. lv_key = lv_key+lv_length. ENDLOOP. ENDMETHOD. METHOD constructor. super->constructor( ). mo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). mi_config = mo_repo->get_data_config( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_data. CREATE OBJECT lo_component EXPORTING iv_key = iv_key. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Data Config' ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD event_add. DATA lo_map TYPE REF TO zcl_abapgit_string_map. DATA ls_config TYPE zif_abapgit_data_config=>ty_config. lo_map = ii_event->form_data( ). ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. ls_config-name = to_upper( lo_map->get( c_id-table ) ). ls_config-skip_initial = lo_map->get( c_id-skip_initial ). ls_config-where = build_where( lo_map ). mi_config->add_config( ls_config ). ENDMETHOD. METHOD event_remove. DATA lo_map TYPE REF TO zcl_abapgit_string_map. DATA ls_config TYPE zif_abapgit_data_config=>ty_config. lo_map = ii_event->form_data( ). ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. ls_config-name = to_upper( lo_map->get( c_id-table ) ). mi_config->remove_config( ls_config ). ENDMETHOD. METHOD event_update. DATA lo_map TYPE REF TO zcl_abapgit_string_map. DATA ls_config TYPE zif_abapgit_data_config=>ty_config. lo_map = ii_event->form_data( ). ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. ls_config-name = to_upper( lo_map->get( c_id-table ) ). ls_config-skip_initial = lo_map->has( to_upper( c_id-skip_initial ) ). ls_config-where = build_where( lo_map ). mi_config->update_config( ls_config ). ENDMETHOD. METHOD render_add. DATA lo_form TYPE REF TO zcl_abapgit_html_form. DATA lo_form_data TYPE REF TO zcl_abapgit_string_map. CREATE OBJECT ri_html TYPE zcl_abapgit_html. CREATE OBJECT lo_form_data. lo_form = zcl_abapgit_html_form=>create( ). lo_form->text( iv_label = 'Table' iv_name = c_id-table iv_required = abap_true ). lo_form->checkbox( iv_label = 'Skip Initial Values' iv_name = c_id-skip_initial ). lo_form->textarea( iv_label = 'Where' iv_placeholder = 'Conditions separated by newline' iv_name = c_id-where ). lo_form->command( iv_label = 'Add' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-add ). ri_html->add( lo_form->render( lo_form_data ) ). ENDMETHOD. METHOD render_existing. DATA lo_form TYPE REF TO zcl_abapgit_html_form. DATA lo_form_data TYPE REF TO zcl_abapgit_string_map. DATA lt_configs TYPE zif_abapgit_data_config=>ty_config_tt. DATA ls_config LIKE LINE OF lt_configs. CREATE OBJECT ri_html TYPE zcl_abapgit_html. CREATE OBJECT lo_form_data. lt_configs = mi_config->get_configs( ). LOOP AT lt_configs INTO ls_config. lo_form = zcl_abapgit_html_form=>create( ). CREATE OBJECT lo_form_data. lo_form_data->set( iv_key = c_id-table iv_val = |{ ls_config-name }| ). lo_form->text( iv_label = 'Table' iv_name = c_id-table iv_readonly = abap_true ). lo_form_data->set( iv_key = c_id-skip_initial iv_val = ls_config-skip_initial ). lo_form->checkbox( iv_label = 'Skip Initial Values' iv_name = c_id-skip_initial ). lo_form_data->set( iv_key = c_id-where iv_val = concat_lines_of( table = ls_config-where sep = |\n| ) ). lo_form->textarea( iv_label = 'Where' iv_placeholder = 'Conditions separated by newline' iv_name = c_id-where ). lo_form->command( iv_label = 'Update' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-update ). lo_form->command( iv_label = 'Remove' iv_action = c_event-remove ). ri_html->add( lo_form->render( lo_form_data ) ). ENDLOOP. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. CASE ii_event->mv_action. WHEN c_event-add. event_add( ii_event ). mo_repo->refresh( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_event-update. event_update( ii_event ). mo_repo->refresh( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_event-remove. event_remove( ii_event ). mo_repo->refresh( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_event-add_via_transport. add_via_transport( ). mo_repo->refresh( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar. ro_toolbar->add( iv_txt = 'Add Via Transport' iv_act = c_event-add_via_transport ). ro_toolbar->add( iv_txt = 'Back' iv_act = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( render_existing( ) ). ri_html->add( render_add( ) ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_commit IMPLEMENTATION. METHOD branch_name_to_internal. rv_new_branch_name = zcl_abapgit_git_branch_list=>complete_heads_branch_name( zcl_abapgit_git_branch_list=>normalize_branch_name( iv_branch_name ) ). ENDMETHOD. METHOD constructor. super->constructor( ). mo_repo = io_repo. mo_stage = io_stage. mt_stage = mo_stage->get_all( ). mv_sci_result = iv_sci_result. " Get settings from DB mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_form = get_form_schema( ). mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_commit. CREATE OBJECT lo_component EXPORTING io_repo = io_repo io_stage = io_stage iv_sci_result = iv_sci_result. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Commit' ii_child_component = lo_component ). ENDMETHOD. METHOD get_comment_default. rv_text = mo_settings->get_commitmsg_comment_default( ). IF rv_text IS INITIAL. RETURN. ENDIF. REPLACE '$FILE' IN rv_text WITH get_comment_file( mt_stage ). REPLACE '$OBJECT' IN rv_text WITH get_comment_object( mt_stage ). ENDMETHOD. METHOD get_comment_file. DATA lv_count TYPE i. FIELD-SYMBOLS LIKE LINE OF it_stage. lv_count = lines( it_stage ). IF lv_count = 1. " Just one file so we use the file name READ TABLE it_stage ASSIGNING INDEX 1. ASSERT sy-subrc = 0. rv_text = -file-filename. ELSE. " For multiple file we use the count instead rv_text = |{ lv_count } files|. ENDIF. ENDMETHOD. METHOD get_comment_object. DATA: lv_count TYPE i, ls_item TYPE zif_abapgit_definitions=>ty_item, lt_items TYPE zif_abapgit_definitions=>ty_items_tt. FIELD-SYMBOLS LIKE LINE OF it_stage. " Get objects LOOP AT it_stage ASSIGNING . CLEAR ls_item. ls_item-obj_type = -status-obj_type. ls_item-obj_name = -status-obj_name. COLLECT ls_item INTO lt_items. ENDLOOP. lv_count = lines( lt_items ). IF lv_count = 1. " Just one object so we use the object name READ TABLE lt_items INTO ls_item INDEX 1. ASSERT sy-subrc = 0. CONCATENATE ls_item-obj_type ls_item-obj_name INTO rv_text SEPARATED BY space. ELSE. " For multiple objects we use the count instead rv_text = |{ lv_count } objects|. ENDIF. ENDMETHOD. METHOD get_committer_email. DATA li_user TYPE REF TO zif_abapgit_persist_user. li_user = zcl_abapgit_persistence_user=>get_instance( ). rv_email = li_user->get_repo_git_user_email( mo_repo->get_url( ) ). IF rv_email IS INITIAL. rv_email = li_user->get_default_git_user_email( ). ENDIF. IF rv_email IS INITIAL. " get default from user record rv_email = zcl_abapgit_user_record=>get_instance( sy-uname )->get_email( ). ENDIF. ENDMETHOD. METHOD get_committer_name. DATA li_user TYPE REF TO zif_abapgit_persist_user. li_user = zcl_abapgit_persistence_user=>get_instance( ). rv_user = li_user->get_repo_git_user_name( mo_repo->get_url( ) ). IF rv_user IS INITIAL. rv_user = li_user->get_default_git_user_name( ). ENDIF. IF rv_user IS INITIAL. " get default from user record rv_user = zcl_abapgit_user_record=>get_instance( sy-uname )->get_name( ). ENDIF. ENDMETHOD. METHOD get_defaults. ms_commit-committer_name = get_committer_name( ). ms_commit-committer_email = get_committer_email( ). ms_commit-comment = get_comment_default( ). " Committer mo_form_data->set( iv_key = c_id-committer_name iv_val = ms_commit-committer_name ). mo_form_data->set( iv_key = c_id-committer_email iv_val = ms_commit-committer_email ). " Message mo_form_data->set( iv_key = c_id-comment iv_val = ms_commit-comment ). ENDMETHOD. METHOD get_form_schema. DATA lv_commitmsg_comment_length TYPE i. CONSTANTS lc_commitmsg_comment_min_len TYPE i VALUE 1. CONSTANTS lc_commitmsg_comment_max_len TYPE i VALUE 255. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'commit-form' iv_help_page = 'https://docs.abapgit.org/guide-stage-commit.html' ). lv_commitmsg_comment_length = mo_settings->get_commitmsg_comment_length( ). ro_form->text( iv_name = c_id-comment iv_label = 'Comment' iv_required = abap_true iv_min = lc_commitmsg_comment_min_len iv_max = lv_commitmsg_comment_length iv_placeholder = |Add a mandatory comment with max { lc_commitmsg_comment_max_len } characters| )->textarea( iv_name = c_id-body iv_label = 'Body' iv_rows = 6 iv_cols = mo_settings->get_commitmsg_body_size( ) iv_placeholder = 'Add an optional description...' )->text( iv_name = c_id-committer_name iv_label = 'Committer Name' iv_required = abap_true )->text( iv_name = c_id-committer_email iv_label = 'Committer Email' iv_required = abap_true ). IF mo_settings->get_commitmsg_hide_author( ) IS INITIAL. ro_form->text( iv_name = c_id-author_name iv_label = 'Author Name' iv_placeholder = 'Optionally, specify an author (same as committer by default)' )->text( iv_name = c_id-author_email iv_label = 'Author Email' ). ENDIF. ro_form->text( iv_name = c_id-new_branch_name iv_label = 'New Branch Name' iv_placeholder = 'Optionally, enter a new branch name for this commit' iv_condense = abap_true ). ro_form->command( iv_label = 'Commit' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-commit )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD render_stage_details. FIELD-SYMBOLS LIKE LINE OF mt_stage. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). LOOP AT mt_stage ASSIGNING . ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ENDLOOP. ri_html->add( '' ). ri_html->add( '
Staged Files (See Summary Above)
' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = -status-lstate iv_rstate = -status-rstate ) ). ri_html->add( '' ). ri_html->add( zcl_abapgit_stage=>method_description( -method ) ). ri_html->add( '' ). ri_html->add( -file-path && -file-filename ). ri_html->add( '
' ). ENDMETHOD. METHOD render_stage_summary. DATA: BEGIN OF ls_sum, method TYPE string, count TYPE i, END OF ls_sum, lt_sum LIKE STANDARD TABLE OF ls_sum WITH DEFAULT KEY. FIELD-SYMBOLS LIKE LINE OF mt_stage. CREATE OBJECT ri_html TYPE zcl_abapgit_html. LOOP AT mt_stage ASSIGNING . ls_sum-method = -method. ls_sum-count = 1. COLLECT ls_sum INTO lt_sum. ENDLOOP. ri_html->add( 'Stage Summary: ' ). READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-add. IF sy-subrc = 0. ri_html->add( |+ { ls_sum-count }| ). ENDIF. READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-rm. IF sy-subrc = 0. ri_html->add( |- { ls_sum-count }| ). ENDIF. READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-ignore. IF sy-subrc = 0. ri_html->add( |~ { ls_sum-count }| ). ENDIF. IF lines( mt_stage ) = 1. ri_html->add( 'file' ). ELSE. ri_html->add( 'files' ). ENDIF. ri_html->add( '(See Details Below)' ). ENDMETHOD. METHOD validate_form. DATA: lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, lv_new_branch_name TYPE string. ro_validation_log = mo_form_util->validate( io_form_data ). IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-committer_email ) ) = abap_false. ro_validation_log->set( iv_key = c_id-committer_email iv_val = |Invalid email address| ). ENDIF. IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-author_email ) ) = abap_false. ro_validation_log->set( iv_key = c_id-author_email iv_val = |Invalid email address| ). ENDIF. lv_new_branch_name = io_form_data->get( c_id-new_branch_name ). IF lv_new_branch_name IS NOT INITIAL. " check if branch already exists lt_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( mo_repo->get_url( ) )->get_branches_only( ). READ TABLE lt_branches TRANSPORTING NO FIELDS WITH TABLE KEY name_key COMPONENTS name = branch_name_to_internal( lv_new_branch_name ). IF sy-subrc = 0. ro_validation_log->set( iv_key = c_id-new_branch_name iv_val = |Branch already exists| ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA lv_new_branch_name TYPE string. mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). CASE ii_event->mv_action. WHEN c_event-commit. " Validate form entries before committing mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. " new branch fields not needed in commit data mo_form_data->strict( abap_false ). mo_form_data->to_abap( CHANGING cs_container = ms_commit ). REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN ms_commit-body WITH cl_abap_char_utilities=>newline. lv_new_branch_name = mo_form_data->get( c_id-new_branch_name ). " create new branch and commit to it if branch name is not empty IF lv_new_branch_name IS NOT INITIAL. lv_new_branch_name = branch_name_to_internal( lv_new_branch_name ). " creates a new branch and automatically switches to it mo_repo->create_branch( lv_new_branch_name ). ENDIF. zcl_abapgit_services_git=>commit( is_commit = ms_commit io_repo = mo_repo io_stage = mo_stage ). MESSAGE 'Commit was successful' TYPE 'S'. rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. WHEN OTHERS. ASSERT 1 = 1. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). IF mo_form_util->is_empty( mo_form_data ) = abap_true. get_defaults( ). ENDIF. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( mo_repo ) ). ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( render_stage_summary( ) ). ri_html->add( '
' ). ri_html->add( mo_form->render( iv_form_class = 'w800px' io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( '
' ). ri_html->add( render_stage_details( ) ). ri_html->add( '
' ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_repo IMPLEMENTATION. METHOD constructor. super->constructor( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_repo = io_repo. mo_form = get_form_schema( ). mo_form_data = read_settings( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_repo. CREATE OBJECT lo_component EXPORTING io_repo = io_repo. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Repository Settings' io_page_menu = zcl_abapgit_gui_menus=>repo_settings( iv_key = io_repo->get_key( ) iv_act = zif_abapgit_definitions=>c_action-repo_settings ) ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'repo-settings-form' iv_help_page = 'https://docs.abapgit.org/settings-dot-abapgit.html' ). ro_form->start_group( iv_name = c_id-dot iv_label = 'Repository Settings (.abapgit.xml)' iv_hint = 'Settings stored in root folder in .abapgit.xml file' )->text( iv_name = c_id-name iv_label = 'Name' iv_hint = 'Official name (can be overwritten by local display name)' )->text( iv_name = c_id-version_constant iv_label = 'Version Constant' iv_placeholder = 'CLASS=>VERSION_CONSTANT or INTERFACE=>VERSION_CONSTANT' iv_upper_case = abap_true )->text( iv_name = c_id-version_value iv_label = 'Version Value' iv_readonly = abap_true )->start_group( iv_name = c_id-i18n iv_label = 'Texts' )->text( iv_name = c_id-main_language iv_label = 'Main Language' iv_hint = 'Main language of repository (cannot be changed)' iv_readonly = abap_true )->text( iv_name = c_id-i18n_langs iv_label = 'Serialize Translations for Additional Languages' iv_hint = 'Comma-separate 2-letter ISO language codes e.g. "DE,ES,..." - should not include main language' )->checkbox( iv_name = c_id-use_lxe iv_label = 'Use Experimental LXE Approach for Translations' iv_hint = 'It''s mandatory to specify the list of languages above in addition to this setting' )->start_group( iv_name = c_id-file_system iv_label = 'Files' )->radio( iv_name = c_id-folder_logic iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix iv_label = 'Folder Logic' iv_hint = 'Define how package folders are named in repository' )->option( iv_label = 'Prefix' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix )->option( iv_label = 'Full' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-full )->option( iv_label = 'Mixed' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-mixed )->text( iv_name = c_id-starting_folder iv_label = 'Starting Folder' iv_hint = 'Root folder that defines where serialization starts' )->textarea( iv_name = c_id-ignore iv_label = 'Ignore Files' iv_hint = 'List of files in starting folder that shall not be serialized' )->start_group( iv_name = c_id-abap_system iv_label = 'ABAP' )->table( iv_name = c_id-requirements iv_label = 'Requirements' iv_hint = 'List of software components with minimum release and patch' )->column( iv_label = 'Software Component' iv_width = '40%' )->column( iv_label = 'Minimum Release' iv_width = '30%' )->column( iv_label = 'Minimum Patch' iv_width = '30%' )->text( iv_name = c_id-original_system iv_label = 'Original System' iv_upper_case = abap_true iv_max = 3 iv_hint = 'Sets the source system of objects during deserialize in downstream systems' && ' (use "SID" to force the source system to sy-sysid)' ). IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. ro_form->radio( iv_name = c_id-abap_langu_vers iv_default_value = '' iv_condense = abap_true iv_label = 'ABAP Language Version' iv_hint = 'Define the ABAP language version for objects in the repository' )->option( iv_label = 'Any (Object-specific ABAP Language Version)' iv_value = '' )->option( iv_label = 'Ignore (ABAP Language Version not serialized)' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-ignore )->option( iv_label = 'Standard ABAP' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-standard )->option( iv_label = 'ABAP for Key Users' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user )->option( iv_label = 'ABAP for Cloud Development' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development ). ENDIF. ro_form->command( iv_label = 'Save Settings' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-save )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD read_settings. DATA: lo_dot TYPE REF TO zcl_abapgit_dot_abapgit, ls_dot TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit, lv_main_lang TYPE spras, lv_language TYPE t002t-sptxt, lv_ignore TYPE string, ls_requirements LIKE LINE OF ls_dot-requirements, lv_row TYPE i, lv_val TYPE string. " Get settings from DB lo_dot = mo_repo->get_dot_abapgit( ). ls_dot = lo_dot->get_data( ). lv_main_lang = lo_dot->get_main_language( ). CREATE OBJECT ro_form_data. " Repository Settings SELECT SINGLE sptxt INTO lv_language FROM t002t WHERE spras = sy-langu AND sprsl = lv_main_lang. IF sy-subrc <> 0. lv_language = 'Unknown language; Check your .abapgit.xml file'. ENDIF. ro_form_data->set( iv_key = c_id-name iv_val = ls_dot-name ). ro_form_data->set( iv_key = c_id-main_language iv_val = |{ lv_main_lang } ({ lv_language })| ). ro_form_data->set( iv_key = c_id-i18n_langs iv_val = zcl_abapgit_lxe_texts=>convert_table_to_lang_string( lo_dot->get_i18n_languages( ) ) ). ro_form_data->set( iv_key = c_id-use_lxe iv_val = boolc( lo_dot->use_lxe( ) = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-folder_logic iv_val = ls_dot-folder_logic ). ro_form_data->set( iv_key = c_id-starting_folder iv_val = ls_dot-starting_folder ). ro_form_data->set( iv_key = c_id-version_constant iv_val = ls_dot-version_constant ). TRY. ro_form_data->set( iv_key = c_id-version_value iv_val = zcl_abapgit_version=>get_version_constant_value( ls_dot-version_constant ) ). CATCH zcx_abapgit_exception. ro_form_data->set( iv_key = c_id-version_value iv_val = '' ). ENDTRY. lv_ignore = concat_lines_of( table = ls_dot-ignore sep = cl_abap_char_utilities=>newline ). ro_form_data->set( iv_key = c_id-ignore iv_val = lv_ignore ). LOOP AT ls_dot-requirements INTO ls_requirements. lv_row = lv_row + 1. DO 3 TIMES. CASE sy-index. WHEN 1. lv_val = ls_requirements-component. WHEN 2. lv_val = ls_requirements-min_release. WHEN 3. lv_val = ls_requirements-min_patch. ENDCASE. ro_form_data->set( iv_key = |{ c_id-requirements }-{ lv_row }-{ sy-index }| iv_val = lv_val ). ENDDO. ENDLOOP. DO c_empty_rows TIMES. lv_row = lv_row + 1. DO 3 TIMES. ro_form_data->set( iv_key = |{ c_id-requirements }-{ lv_row }-{ sy-index }| iv_val = '' ). ENDDO. ENDDO. mv_requirements_count = lv_row. ro_form_data->set( iv_key = |{ c_id-requirements }-{ zif_abapgit_html_form=>c_rows }| iv_val = |{ mv_requirements_count }| ). IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. ro_form_data->set( iv_key = c_id-abap_langu_vers iv_val = ls_dot-abap_language_version ). ENDIF. ro_form_data->set( iv_key = c_id-original_system iv_val = ls_dot-original_system ). ENDMETHOD. METHOD save_settings. DATA: lo_dot TYPE REF TO zcl_abapgit_dot_abapgit, lv_ignore TYPE string, lt_ignore TYPE STANDARD TABLE OF string WITH DEFAULT KEY, ls_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement, lt_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt. lo_dot = mo_repo->get_dot_abapgit( ). lo_dot->set_name( mo_form_data->get( c_id-name ) ). lo_dot->set_folder_logic( mo_form_data->get( c_id-folder_logic ) ). lo_dot->set_starting_folder( mo_form_data->get( c_id-starting_folder ) ). lo_dot->set_version_constant( mo_form_data->get( c_id-version_constant ) ). lo_dot->set_original_system( mo_form_data->get( c_id-original_system ) ). IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. lo_dot->set_abap_language_version( mo_form_data->get( c_id-abap_langu_vers ) ). ENDIF. lo_dot->set_i18n_languages( zcl_abapgit_lxe_texts=>convert_lang_string_to_table( iv_langs = mo_form_data->get( c_id-i18n_langs ) iv_skip_main_language = lo_dot->get_main_language( ) ) ). lo_dot->use_lxe( boolc( mo_form_data->get( c_id-use_lxe ) = abap_true ) ). " Remove all ignores lt_ignore = lo_dot->get_data( )-ignore. LOOP AT lt_ignore INTO lv_ignore. lo_dot->remove_ignore( iv_path = '' iv_filename = lv_ignore ). ENDLOOP. " Add newly entered ignores lt_ignore = zcl_abapgit_convert=>split_string( mo_form_data->get( c_id-ignore ) ). LOOP AT lt_ignore INTO lv_ignore. lv_ignore = condense( lv_ignore ). IF lv_ignore IS NOT INITIAL. lo_dot->add_ignore( iv_path = '' iv_filename = lv_ignore ). ENDIF. ENDLOOP. " Requirements DO mv_requirements_count TIMES. ls_requirements-component = to_upper( mo_form_data->get( |{ c_id-requirements }-{ sy-index }-1| ) ). ls_requirements-min_release = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-2| ). ls_requirements-min_patch = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-3| ). APPEND ls_requirements TO lt_requirements. ENDDO. SORT lt_requirements BY component min_release min_patch. DELETE lt_requirements WHERE component IS INITIAL. DELETE ADJACENT DUPLICATES FROM lt_requirements COMPARING ALL FIELDS. lo_dot->set_requirements( lt_requirements ). mo_repo->set_dot_abapgit( lo_dot ). mo_repo->refresh( ). COMMIT WORK AND WAIT. MESSAGE 'Settings successfully saved' TYPE 'S'. mo_form_data = read_settings( ). ENDMETHOD. METHOD validate_form. CONSTANTS lc_allowed(36) TYPE c VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'. DATA: lt_lang_list TYPE zif_abapgit_definitions=>ty_languages, lv_folder TYPE string, lv_len TYPE i, lv_component TYPE zif_abapgit_dot_abapgit=>ty_requirement-component, lv_min_release TYPE zif_abapgit_dot_abapgit=>ty_requirement-min_release, lv_min_patch TYPE zif_abapgit_dot_abapgit=>ty_requirement-min_patch, lv_version_constant TYPE string, lv_original_system TYPE string, lx_exception TYPE REF TO zcx_abapgit_exception. ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). lv_folder = io_form_data->get( c_id-starting_folder ). lv_len = strlen( lv_folder ) - 1. IF lv_len > 0 AND lv_folder(1) <> '/'. ro_validation_log->set( iv_key = c_id-starting_folder iv_val = |The folder must begin with /| ). ELSEIF lv_len > 0 AND lv_folder+lv_len(1) <> '/'. ro_validation_log->set( iv_key = c_id-starting_folder iv_val = |The folder must end with /| ). ELSEIF lv_folder CA '\'. ro_validation_log->set( iv_key = c_id-starting_folder iv_val = |Use / instead of \\| ). ENDIF. DO mv_requirements_count TIMES. lv_component = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-1| ). lv_min_release = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-2| ). lv_min_patch = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-3| ). IF lv_component IS INITIAL AND ( lv_min_release IS NOT INITIAL OR lv_min_patch IS NOT INITIAL ). ro_validation_log->set( iv_key = c_id-requirements iv_val = |If you enter a release or patch, you must also enter a software component| ). ELSEIF lv_component IS NOT INITIAL AND lv_min_release IS INITIAL. ro_validation_log->set( iv_key = c_id-requirements iv_val = |If you enter a software component, you must also enter a minimum release| ). ENDIF. ENDDO. TRY. lv_version_constant = io_form_data->get( c_id-version_constant ). IF lv_version_constant IS NOT INITIAL. zcl_abapgit_version=>get_version_constant_value( lv_version_constant ). validate_version_constant( lv_version_constant ). ENDIF. CATCH zcx_abapgit_exception INTO lx_exception. ro_validation_log->set( iv_key = c_id-version_constant iv_val = lx_exception->get_text( ) ). ENDTRY. lt_lang_list = zcl_abapgit_lxe_texts=>convert_lang_string_to_table( iv_langs = io_form_data->get( c_id-i18n_langs ) iv_skip_main_language = mo_repo->get_dot_abapgit( )->get_main_language( ) ). IF io_form_data->get( c_id-use_lxe ) = abap_true AND lt_lang_list IS INITIAL. ro_validation_log->set( iv_key = c_id-i18n_langs iv_val = 'LXE approach requires a non-empty list of languages' ). ENDIF. lv_original_system = io_form_data->get( c_id-original_system ). IF lv_original_system CN lc_allowed. ro_validation_log->set( iv_key = c_id-original_system iv_val = 'System name must be alphanumerical' ). ENDIF. ENDMETHOD. METHOD validate_version_constant. DATA: lv_version_class TYPE seoclsname, lv_version_component TYPE string, lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. SPLIT iv_version_constant AT '=>' INTO lv_version_class lv_version_component. lt_local = mo_repo->get_files_local( ). READ TABLE lt_local TRANSPORTING NO FIELDS WITH KEY item-obj_type = 'CLAS' item-obj_name = lv_version_class. IF sy-subrc <> 0. READ TABLE lt_local TRANSPORTING NO FIELDS WITH KEY item-obj_type = 'INTF' item-obj_name = lv_version_class. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Object { lv_version_class } is not included in this repository| ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-go_back. rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( io_form_data = mo_form_data io_compare_with = read_settings( ) ). WHEN c_event-save. " Validate all form entries mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. save_settings( ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( `
` ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false iv_interactive_branch = abap_true ) ). ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( `
` ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_remo IMPLEMENTATION. METHOD check_protection. IF mo_repo->is_offline( ) = abap_true. zcx_abapgit_exception=>raise( 'Unexpected switch for offline repo' ). ENDIF. IF mo_repo->get_local_settings( )-write_protected = abap_true. zcx_abapgit_exception=>raise( 'Cannot switch. Repository is write-protected in local settings' ). ENDIF. ENDMETHOD. METHOD choose_branch. DATA lv_url TYPE zif_abapgit_persistence=>ty_repo-url. DATA lv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name. DATA ls_branch TYPE zif_abapgit_git_definitions=>ty_git_branch. DATA lv_popup_cancelled TYPE abap_bool. IF iv_is_return = abap_false. IF mo_form_data->get( c_id-offline ) = abap_true. RETURN. ENDIF. lv_url = mo_form_data->get( c_id-url ). lv_branch_name = mo_form_data->get( c_id-branch ). mo_popup_picklist = zcl_abapgit_popup_branch_list=>create( iv_show_new_option = abap_false iv_url = lv_url iv_default_branch = lv_branch_name )->create_picklist( )->set_id( c_event-choose_branch )->set_in_page( ). ELSE. lv_popup_cancelled = mo_popup_picklist->was_cancelled( ). IF lv_popup_cancelled = abap_false. mo_popup_picklist->get_result_item( CHANGING cs_selected = ls_branch ). IF ls_branch IS NOT INITIAL. mo_form_data->set( iv_key = c_id-branch iv_val = ls_branch-display_name ). ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD choose_commit. DATA: lv_url TYPE string, lv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name, li_popups TYPE REF TO zif_abapgit_popups. IF mo_form_data->get( c_id-offline ) = abap_true. RETURN. ENDIF. lv_url = mo_form_data->get( c_id-url ). lv_branch_name = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && mo_form_data->get( c_id-branch ). li_popups = zcl_abapgit_ui_factory=>get_popups( ). rv_commit = li_popups->commit_list_popup( iv_repo_url = lv_url iv_branch_name = lv_branch_name )-sha1. ENDMETHOD. METHOD choose_pr. DATA ls_pull TYPE zif_abapgit_pr_enum_provider=>ty_pull_request. DATA lv_url TYPE ty_remote_settings-url. DATA lv_popup_cancelled TYPE abap_bool. IF iv_is_return = abap_false. IF mo_form_data->get( c_id-offline ) = abap_true. zcx_abapgit_exception=>raise( 'Not possible for offline repositories' ). ENDIF. lv_url = mo_form_data->get( c_id-url ). mo_popup_picklist = zcl_abapgit_popup_pull_request=>create( lv_url )->create_picklist( )->set_id( c_event-choose_pull_request )->set_in_page( abap_true ). ELSE. lv_popup_cancelled = mo_popup_picklist->was_cancelled( ). IF lv_popup_cancelled = abap_false. mo_popup_picklist->get_result_item( CHANGING cs_selected = ls_pull ). IF ls_pull IS NOT INITIAL. mo_form_data->set( iv_key = c_id-pull_request iv_val = ls_pull-head_url && '@' && ls_pull-head_branch ). ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD choose_tag. DATA ls_tag TYPE zif_abapgit_git_definitions=>ty_git_branch. DATA lv_url TYPE ty_remote_settings-url. DATA lv_popup_cancelled TYPE abap_bool. IF iv_is_return = abap_false. IF mo_form_data->get( c_id-offline ) = abap_true. RETURN. ELSEIF mo_repo->is_offline( ) = abap_true. MESSAGE 'Please save conversion to online repository before choosing a tag' TYPE 'S'. RETURN. ENDIF. lv_url = mo_form_data->get( c_id-url ). mo_popup_picklist = zcl_abapgit_popup_tag_list=>create( lv_url )->create_picklist( )->set_id( c_event-choose_tag )->set_in_page( ). ELSE. lv_popup_cancelled = mo_popup_picklist->was_cancelled( ). IF lv_popup_cancelled = abap_false. mo_popup_picklist->get_result_item( CHANGING cs_selected = ls_tag ). IF ls_tag IS NOT INITIAL. mo_form_data->set( iv_key = c_id-tag iv_val = ls_tag-display_name ). ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD choose_url. " todo, get url history from DB and show selection popup #3639 rv_url = ''. ENDMETHOD. METHOD constructor. super->constructor( ). mo_repo = io_repo. ms_settings_snapshot = get_remote_settings_from_repo( mo_repo ). mo_form = get_form_schema( ). mo_form_data = initialize_form_data( ). CREATE OBJECT mo_validation_log. ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_remo. CREATE OBJECT lo_component EXPORTING io_repo = io_repo. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Remote Settings' io_page_menu = zcl_abapgit_gui_menus=>repo_settings( iv_key = io_repo->get_key( ) iv_act = zif_abapgit_definitions=>c_action-repo_remote_settings ) ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. DATA: lv_button TYPE string, lv_icon TYPE string, lv_offline TYPE abap_bool, lv_head_type TYPE ty_head_type. IF io_existing_form_data IS BOUND AND io_existing_form_data->is_empty( ) = abap_false. lv_offline = io_existing_form_data->get( c_id-offline ). IF lv_offline = abap_false. lv_head_type = io_existing_form_data->get( c_id-head_type ). ENDIF. ELSE. lv_offline = ms_settings_snapshot-offline. lv_head_type = ms_settings_snapshot-head_type. ENDIF. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'repo-remote-settings-form' iv_help_page = 'https://docs.abapgit.org/settings-remote.html' ). IF lv_offline = abap_true. lv_button = 'Switch to Online'. lv_icon = 'plug/darkgrey'. ELSE. lv_button = 'Switch to Offline'. lv_icon = 'cloud-upload-alt/darkgrey'. ENDIF. ro_form->start_group( iv_name = c_id-general iv_label = 'General' iv_hint = 'Change the general type and origin of the repository' )->text( iv_name = c_id-repo_type iv_label = |Type of Repository: { zcl_abapgit_html=>icon( lv_icon ) }| iv_readonly = abap_true )->hidden( c_id-offline ). IF lv_offline = abap_false. ro_form->text( iv_name = c_id-url iv_condense = abap_true iv_label = 'Git Repository URL' iv_hint = 'URL of original repository' iv_placeholder = 'https://github.com/...git' ). ro_form->start_group( iv_name = c_id-head_group iv_label = 'Head' )->radio( iv_label = 'Type' iv_name = c_id-head_type iv_action = c_event-change_head_type )->option( iv_label = 'Branch' iv_value = c_head_types-branch )->option( iv_label = 'Tag' iv_value = c_head_types-tag )->option( iv_label = 'Commit' iv_value = c_head_types-commit )->option( iv_label = 'Pull Request' iv_value = c_head_types-pull_request ). IF lv_head_type = c_head_types-branch OR lv_head_type = c_head_types-commit. ro_form->text( iv_name = c_id-branch iv_label = 'Branch' iv_required = abap_true iv_side_action = c_event-choose_branch ). ENDIF. IF lv_head_type = c_head_types-tag. ro_form->text( iv_name = c_id-tag iv_label = 'Tag' iv_required = abap_true iv_side_action = c_event-choose_tag ). ENDIF. IF lv_head_type = c_head_types-commit. ro_form->text( iv_name = c_id-commit iv_label = 'Commit' iv_required = abap_true iv_min = 40 iv_max = 40 iv_side_action = c_event-choose_commit ). ENDIF. IF lv_head_type = c_head_types-pull_request. ro_form->text( iv_name = c_id-pull_request iv_label = 'Pull Request' iv_required = abap_true iv_side_action = c_event-choose_pull_request ). ENDIF. ENDIF. ro_form->command( iv_label = 'Save Settings' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-save )->command( iv_label = lv_button iv_action = c_event-switch )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD get_remote_settings_from_form. rs_settings-offline = io_form_data->get( c_id-offline ). IF rs_settings-offline = abap_false. rs_settings-url = io_form_data->get( c_id-url ). rs_settings-head_type = io_form_data->get( c_id-head_type ). CASE rs_settings-head_type. WHEN c_head_types-branch. rs_settings-branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && io_form_data->get( c_id-branch ). WHEN c_head_types-tag. rs_settings-tag = zif_abapgit_git_definitions=>c_git_branch-tags_prefix && io_form_data->get( c_id-tag ). WHEN c_head_types-commit. rs_settings-branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && io_form_data->get( c_id-branch ). rs_settings-commit = io_form_data->get( c_id-commit ). WHEN c_head_types-pull_request. rs_settings-pull_request = io_form_data->get( c_id-pull_request ). ENDCASE. ENDIF. ENDMETHOD. METHOD get_remote_settings_from_repo. DATA: lo_repo_online TYPE REF TO zcl_abapgit_repo_online, lv_branch TYPE ty_remote_settings-branch. IF io_repo->is_offline( ) = abap_false. lo_repo_online ?= io_repo. rs_settings-url = lo_repo_online->get_url( ). rs_settings-offline = abap_false. rs_settings-switched_origin = lo_repo_online->get_switched_origin( ). IF lo_repo_online->get_selected_commit( ) IS NOT INITIAL. rs_settings-commit = lo_repo_online->get_selected_commit( ). rs_settings-branch = lo_repo_online->get_selected_branch( ). rs_settings-head_type = c_head_types-commit. ELSEIF lo_repo_online->get_switched_origin( ) IS NOT INITIAL. " get_switched_origin( ) returns the original repo url + HEAD concatenated with @ " get_branch( ) returns the branch of the PR in the source repo " get_url( ) returns the source repo of the PR branch rs_settings-switched_origin = lo_repo_online->get_switched_origin( ). SPLIT rs_settings-switched_origin AT '@' INTO rs_settings-url rs_settings-branch. IF rs_settings-branch CP zif_abapgit_git_definitions=>c_git_branch-tags. rs_settings-tag = rs_settings-branch. CLEAR rs_settings-branch. ENDIF. lv_branch = lo_repo_online->get_selected_branch( ). REPLACE FIRST OCCURRENCE OF zif_abapgit_git_definitions=>c_git_branch-heads_prefix IN lv_branch WITH space. CONDENSE lv_branch. rs_settings-pull_request = |{ lo_repo_online->get_url( ) }@{ lv_branch }|. rs_settings-head_type = c_head_types-pull_request. ELSE. rs_settings-branch = lo_repo_online->get_selected_branch( ). rs_settings-head_type = c_head_types-branch. IF rs_settings-branch CP zif_abapgit_git_definitions=>c_git_branch-tags. rs_settings-head_type = c_head_types-tag. rs_settings-tag = rs_settings-branch. CLEAR rs_settings-branch. ENDIF. ENDIF. ELSE. rs_settings-offline = abap_true. ENDIF. ENDMETHOD. METHOD handle_picklist_state. IF mo_popup_picklist IS BOUND AND ( mo_popup_picklist->is_fulfilled( ) = abap_true OR mo_popup_picklist->is_in_page( ) = abap_false ). " Picklist is either fulfilled OR " it was on its own page and user went back from it via F3/ESC and the picklist had no "graceful back" handler CASE mo_popup_picklist->id( ). WHEN c_event-choose_pull_request. choose_pr( abap_true ). WHEN c_event-choose_branch. choose_branch( abap_true ). WHEN c_event-choose_tag. choose_tag( abap_true ). WHEN OTHERS. zcx_abapgit_exception=>raise( |Unexpected picklist id { mo_popup_picklist->id( ) }| ). ENDCASE. CLEAR mo_popup_picklist. ENDIF. ENDMETHOD. METHOD initialize_form_data. DATA: lv_type TYPE string, lv_head TYPE string. CREATE OBJECT ro_form_data. IF ms_settings_snapshot-offline = abap_true. lv_type = c_repo_type-offline. ELSE. lv_type = c_repo_type-online. ENDIF. ro_form_data->set( iv_key = c_id-offline iv_val = ms_settings_snapshot-offline ). ro_form_data->set( iv_key = c_id-repo_type iv_val = lv_type ). IF ms_settings_snapshot-offline = abap_false. ro_form_data->set( iv_key = c_id-url iv_val = ms_settings_snapshot-url ). ro_form_data->set( iv_key = c_id-head_type iv_val = ms_settings_snapshot-head_type ). " When pull request is selected the previously selected branch/tag is also loaded to be able to switch back to it lv_head = zcl_abapgit_git_branch_list=>get_display_name( ms_settings_snapshot-branch ). ro_form_data->set( iv_key = c_id-branch iv_val = lv_head ). lv_head = zcl_abapgit_git_branch_list=>get_display_name( ms_settings_snapshot-tag ). ro_form_data->set( iv_key = c_id-tag iv_val = lv_head ). ro_form_data->set( iv_key = c_id-commit iv_val = ms_settings_snapshot-commit ). ro_form_data->set( iv_key = c_id-pull_request iv_val = ms_settings_snapshot-pull_request ). ENDIF. ENDMETHOD. METHOD prepare_for_compare. ro_form_data = zcl_abapgit_string_map=>create( )->merge( io_form_data ). CASE ro_form_data->get( c_id-head_type ). WHEN c_head_types-branch. ro_form_data->set( iv_key = c_id-pull_request iv_val = '' ). ro_form_data->set( iv_key = c_id-commit iv_val = '' ). ro_form_data->set( iv_key = c_id-tag iv_val = '' ). WHEN c_head_types-tag. ro_form_data->set( iv_key = c_id-pull_request iv_val = '' ). ro_form_data->set( iv_key = c_id-commit iv_val = '' ). ro_form_data->set( iv_key = c_id-branch iv_val = '' ). WHEN c_head_types-commit. ro_form_data->set( iv_key = c_id-pull_request iv_val = '' ). WHEN c_head_types-pull_request. ro_form_data->set( iv_key = c_id-commit iv_val = '' ). ENDCASE. ENDMETHOD. METHOD render_content. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false iv_interactive_branch = abap_false ) ). ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ENDMETHOD. METHOD save_settings. DATA: lo_repo_online TYPE REF TO zcl_abapgit_repo_online, ls_settings_new TYPE ty_remote_settings. ls_settings_new = get_remote_settings_from_form( mo_form_data ). " Switch online / offline IF ls_settings_new-offline <> ms_settings_snapshot-offline. " Remember key, switch, retrieve new instance (todo, refactor #2244) mo_repo->switch_repo_type( ls_settings_new-offline ). mo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( mo_repo->get_key( ) ). ENDIF. IF mo_repo->is_offline( ) = abap_false. " Online: Save url lo_repo_online ?= mo_repo. lo_repo_online->set_url( ls_settings_new-url ). ENDIF. CASE ls_settings_new-head_type. WHEN c_head_types-branch. switch_to_pull_req( iv_revert = abap_true ). switch_to_commit( iv_revert = abap_true ). switch_to_branch_tag( ls_settings_new-branch ). WHEN c_head_types-tag. switch_to_pull_req( iv_revert = abap_true ). switch_to_commit( iv_revert = abap_true ). switch_to_branch_tag( ls_settings_new-tag ). WHEN c_head_types-commit. switch_to_pull_req( iv_revert = abap_true ). switch_to_commit( iv_commit = ls_settings_new-commit ). WHEN c_head_types-pull_request. switch_to_commit( iv_revert = abap_true ). switch_to_pull_req( iv_pull = ls_settings_new-pull_request ). ENDCASE. IF mo_repo->is_offline( ) = abap_false AND ls_settings_new-head_type <> c_head_types-pull_request. " Switching from PR to something else will reset the URL in repo->switch_origin( space ) " -> set URL again lo_repo_online->set_url( ls_settings_new-url ). ENDIF. COMMIT WORK AND WAIT. MESSAGE 'Settings successfully saved' TYPE 'S'. mv_refresh_on_back = abap_true. ms_settings_snapshot = get_remote_settings_from_repo( mo_repo ). ENDMETHOD. METHOD switch_online_offline. DATA: lv_offline_new TYPE abap_bool, lv_url TYPE ty_remote_settings-url, lv_branch TYPE ty_remote_settings-branch. lv_offline_new = boolc( mo_form_data->get( c_id-offline ) = abap_false ). mo_form_data->set( iv_key = c_id-offline iv_val = lv_offline_new ). IF lv_offline_new = abap_true. lv_url = mo_form_data->get( c_id-url ). mv_offline_switch_saved_url = lv_url. mo_form_data->set( iv_key = c_id-url iv_val = '' ). mo_form_data->set( iv_key = c_id-repo_type iv_val = c_repo_type-offline ). ELSE. mo_form_data->set( iv_key = c_id-repo_type iv_val = c_repo_type-online ). IF mv_offline_switch_saved_url IS NOT INITIAL. mo_form_data->set( iv_key = c_id-url iv_val = mv_offline_switch_saved_url ). ENDIF. lv_url = mo_form_data->get( c_id-url ). IF mo_form_data->get( c_id-head_type ) IS INITIAL. TRY. mo_form_data->set( iv_key = c_id-head_type iv_val = c_head_types-branch ). IF lv_url CP 'http*'. lv_branch = zcl_abapgit_git_factory=>get_git_transport( )->branches( lv_url )->get_head_symref( ). mo_form_data->set( iv_key = c_id-branch iv_val = lv_branch ). ENDIF. CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. ENDIF. ENDIF. ENDMETHOD. METHOD switch_to_branch_tag. DATA lo_repo TYPE REF TO zcl_abapgit_repo_online. check_protection( ). lo_repo ?= mo_repo. lo_repo->select_branch( iv_name ). ENDMETHOD. METHOD switch_to_commit. DATA lo_repo TYPE REF TO zcl_abapgit_repo_online. check_protection( ). lo_repo ?= mo_repo. IF iv_revert = abap_true. lo_repo->select_commit( '' ). ELSE. lo_repo->select_commit( iv_commit ). ENDIF. ENDMETHOD. METHOD switch_to_pull_req. DATA: lo_repo TYPE REF TO zcl_abapgit_repo_online, lv_url TYPE ty_remote_settings-url, lv_branch TYPE ty_remote_settings-branch. check_protection( ). lo_repo ?= mo_repo. " Switching twice does not work so reset to original repo first lo_repo->switch_origin( '' ). IF iv_revert = abap_false. SPLIT iv_pull AT '@' INTO lv_url lv_branch. lo_repo->switch_origin( iv_url = lv_url iv_branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && lv_branch ). ENDIF. ENDMETHOD. METHOD validate_form. DATA: lx_error TYPE REF TO zcx_abapgit_exception, lo_branch_list TYPE REF TO zcl_abapgit_git_branch_list, lo_url TYPE REF TO zcl_abapgit_git_url, lv_offline TYPE abap_bool, lv_head_type TYPE ty_head_type, lv_branch TYPE ty_remote_settings-branch, lv_url TYPE ty_remote_settings-url, lv_branch_check_error_id TYPE string, lv_pull_request TYPE ty_remote_settings-pull_request, lv_commit TYPE ty_remote_settings-commit. ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). lv_offline = io_form_data->get( c_id-offline ). lv_url = io_form_data->get( c_id-url ). IF lv_offline = abap_false AND lv_url NP 'http*'. ro_validation_log->set( iv_key = c_id-url iv_val = 'Enter the URL of the repository and save' ). ELSEIF lv_offline = abap_false. TRY. zcl_abapgit_url=>name( iv_url = lv_url iv_validate = abap_true ). " Provider-specific URL check CREATE OBJECT lo_url. lo_url->validate_url( lv_url ). CATCH zcx_abapgit_exception INTO lx_error. ro_validation_log->set( iv_key = c_id-url iv_val = lx_error->get_text( ) ). ENDTRY. IF iv_connection_check = abap_true. zcl_abapgit_http=>check_connection( lv_url ). ENDIF. ENDIF. IF lv_offline = abap_false. lv_head_type = io_form_data->get( c_id-head_type ). CASE lv_head_type. WHEN c_head_types-branch. lv_branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && io_form_data->get( c_id-branch ). CONDENSE lv_branch. lv_branch_check_error_id = c_id-branch. WHEN c_head_types-tag. lv_branch = zif_abapgit_git_definitions=>c_git_branch-tags_prefix && io_form_data->get( c_id-tag ). CONDENSE lv_branch. lv_branch_check_error_id = c_id-tag. WHEN c_head_types-pull_request. lv_pull_request = io_form_data->get( c_id-pull_request ). SPLIT lv_pull_request AT '@' INTO lv_url lv_branch. IF lv_branch IS NOT INITIAL. lv_branch = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && lv_branch. ENDIF. lv_branch_check_error_id = c_id-pull_request. WHEN c_head_types-commit. lv_commit = io_form_data->get( c_id-commit ). " Cannot check for commit existence currently (needs API that doesn't rely on finding the first commit " in the branch), check format instead IF lv_commit CN '0123456789abcdef' AND ro_validation_log->get( c_id-commit ) IS INITIAL. ro_validation_log->set( iv_key = c_id-commit iv_val = 'Commit needs to be hexadecimal and in lowercase' ). ENDIF. WHEN OTHERS. ro_validation_log->set( iv_key = c_id-head_type iv_val = 'Unknown head type' ). ENDCASE. IF lv_branch IS NOT INITIAL. " Problems with getting branches in general are raised to the page lo_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( lv_url ). TRY. " Issues with finding a particular branch are shown next to corresponding field lo_branch_list->find_by_name( lv_branch ). CATCH zcx_abapgit_exception INTO lx_error. ro_validation_log->set( iv_key = lv_branch_check_error_id iv_val = lx_error->get_text( ) ). ENDTRY. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA: lv_url TYPE ty_remote_settings-url, lv_commit TYPE ty_remote_settings-commit. mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-go_back. IF mv_refresh_on_back = abap_true. " Note this doesn't trigger if the tab is switched first mo_repo->refresh( ). ENDIF. rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( io_form_data = prepare_for_compare( mo_form_data ) io_compare_with = initialize_form_data( ) ). WHEN c_event-choose_url. lv_url = choose_url( ). IF lv_url IS INITIAL. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ELSE. mo_form_data->set( iv_key = c_id-url iv_val = lv_url ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. WHEN c_event-change_head_type. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. mo_validation_log->clear( ). WHEN c_event-choose_branch. choose_branch( ). " Uniformly handle state below WHEN c_event-choose_tag. choose_tag( ). " Uniformly handle state below WHEN c_event-choose_pull_request. choose_pr( ). " Uniformly handle state below WHEN c_event-choose_commit. lv_commit = choose_commit( ). IF lv_commit IS INITIAL. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ELSE. mo_form_data->set( iv_key = c_id-commit iv_val = lv_commit ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. WHEN c_event-switch. switch_online_offline( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_event-save. mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. save_settings( ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. IF mo_popup_picklist IS BOUND. " Uniform popup state handling " This should happen only for a new popup because " on the first re-render main component event handling is blocked " and not called again until the popup destruction IF mo_popup_picklist->is_in_page( ) = abap_true. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. rs_handled-page = zcl_abapgit_gui_page_hoc=>create( ii_child_component = mo_popup_picklist iv_show_as_modal = abap_true ). ENDIF. ENDIF. " If staying on form, initialize it with current settings IF rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render AND mo_popup_picklist IS NOT BOUND. " Switching tabs must change the form layout mo_form = get_form_schema( mo_form_data ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions, lv_head_type TYPE ty_head_type, lv_offline TYPE abap_bool. IF mo_form_data IS BOUND AND mo_form_data->is_empty( ) = abap_false. lv_offline = mo_form_data->get( c_id-offline ). IF lv_offline = abap_false. lv_head_type = mo_form_data->get( c_id-head_type ). ENDIF. ELSE. lv_offline = ms_settings_snapshot-offline. IF lv_offline = abap_false. lv_head_type = ms_settings_snapshot-head_type. ENDIF. ENDIF. ls_hotkey_action-ui_component = 'Remote'. ls_hotkey_action-description = 'Choose URL'. ls_hotkey_action-action = c_event-choose_url. ls_hotkey_action-hotkey = 'u'. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. IF lv_head_type = c_head_types-branch OR lv_head_type = c_head_types-commit. ls_hotkey_action-description = 'Choose Branch'. ls_hotkey_action-action = c_event-choose_branch. ls_hotkey_action-hotkey = 'b'. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDIF. IF lv_head_type = c_head_types-tag. ls_hotkey_action-description = 'Choose Tag'. ls_hotkey_action-action = c_event-choose_tag. ls_hotkey_action-hotkey = 't'. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDIF. IF lv_head_type = c_head_types-commit. ls_hotkey_action-description = 'Choose Commit'. ls_hotkey_action-action = c_event-choose_commit. ls_hotkey_action-hotkey = 'c'. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDIF. IF lv_head_type = c_head_types-pull_request. ls_hotkey_action-description = 'Choose Pull Request'. ls_hotkey_action-action = c_event-choose_pull_request. ls_hotkey_action-hotkey = 'p'. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDIF. IF lv_offline = abap_true. ls_hotkey_action-description = 'Switch to Online'. ls_hotkey_action-action = c_event-switch. ls_hotkey_action-hotkey = 'o'. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ELSE. ls_hotkey_action-description = 'Switch to Offline'. ls_hotkey_action-action = c_event-switch. ls_hotkey_action-hotkey = 'o'. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. handle_picklist_state( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->wrap( iv_tag = 'div' iv_class = 'repo' " It's OK because it's repo settings ... for now ii_content = render_content( ) ). IF mo_popup_picklist IS NOT BOUND OR mo_popup_picklist->is_in_page( ) = abap_false. register_handlers( ). ELSEIF mo_popup_picklist->is_in_page( ) = abap_true. " Block usual page events if the popup is an in-page popup ri_html->add( zcl_abapgit_gui_in_page_modal=>create( mo_popup_picklist ) ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_pers IMPLEMENTATION. METHOD constructor. super->constructor( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_form = get_form_schema( ). mo_form_data = read_settings( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_pers. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Personal Settings' io_page_menu = zcl_abapgit_gui_menus=>settings( zif_abapgit_definitions=>c_action-go_settings_personal ) ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'personal-setting-form' iv_help_page = 'https://docs.abapgit.org/guide-settings-personal.html' ). ro_form->start_group( iv_name = c_id-startup iv_label = 'Startup' )->checkbox( iv_name = c_id-show_default_repo iv_label = 'Show Last Opened Repository' iv_hint = 'Recommended to check, if you are using ADT' )->start_group( iv_name = c_id-ui iv_label = 'User Interface' )->radio( iv_name = c_id-ui_theme iv_default_value = zcl_abapgit_settings=>c_ui_theme-default iv_label = 'Theme' )->option( iv_label = 'Default' iv_value = zcl_abapgit_settings=>c_ui_theme-default )->option( iv_label = 'Dark' iv_value = zcl_abapgit_settings=>c_ui_theme-dark )->option( iv_label = 'Belize' iv_value = zcl_abapgit_settings=>c_ui_theme-belize )->option( iv_label = 'Synced with SAP GUI' iv_value = zcl_abapgit_settings=>c_ui_theme-synced_with_gui )->radio( iv_name = c_id-icon_scaling iv_default_value = '' iv_label = 'Icon Scaling (HDPI)' iv_hint = 'Adjust size of icons for High DPI displays' )->option( iv_label = 'Automatic' iv_value = '' )->option( iv_label = 'Small' iv_value = zcl_abapgit_settings=>c_icon_scaling-small )->option( iv_label = 'Large' iv_value = zcl_abapgit_settings=>c_icon_scaling-large )->number( iv_name = c_id-max_lines iv_label = 'List Size' iv_hint = 'Maximum number of objects listed (0 = All)' iv_min = 0 iv_max = 10000 )->textarea( iv_name = c_id-label_colors iv_rows = 3 iv_label = `Repo label colors ` && render_repo_labels_help_hint( ) )->start_group( iv_name = c_id-interaction iv_label = 'Interaction' )->checkbox( iv_name = c_id-activate_wo_popup iv_label = 'Activate Objects Without Popup' iv_hint = 'Activates objects automatically without showing popup' )->checkbox( iv_name = c_id-adt_jump_enabled iv_label = 'Enable Jump to ABAP Development Tools (If Available)' iv_hint = 'Recommended to check, if you are using ADT' )->checkbox( iv_name = c_id-link_hints_enabled iv_label = 'Enable Vimium-like Link Hints' iv_hint = 'When you hit the key, abapGit will identify clickable things and put a label beside it' )->text( iv_name = c_id-link_hint_key iv_label = 'Key to Activate Link Hints' iv_min = 0 iv_max = 1 )->start_group( iv_name = c_id-resources iv_label = 'System Resources' )->checkbox( iv_name = c_id-parallel_proc_disabled iv_label = 'Disable Parallel Processing' iv_hint = 'If disabled, abapGit will use only a single thread to serialize objects' )->command( iv_label = 'Save Settings' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-save )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). " Not available via this form: " - User-specific hotkey settings have been discontinued " - hide_sapgui_hint is set via ZCL_ABAPGIT_SERVICES_ABAPGIT-CHECK_SAPGUI ENDMETHOD. METHOD read_settings. " Get settings from DB mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). ms_settings = mo_settings->get_user_settings( ). CREATE OBJECT ro_form_data. " Startup ro_form_data->set( iv_key = c_id-show_default_repo iv_val = boolc( ms_settings-show_default_repo = abap_true ) ) ##TYPE. " UI ro_form_data->set( iv_key = c_id-ui_theme iv_val = ms_settings-ui_theme ). ro_form_data->set( iv_key = c_id-icon_scaling iv_val = |{ ms_settings-icon_scaling }| ). ro_form_data->set( iv_key = c_id-max_lines iv_val = |{ ms_settings-max_lines }| ). ro_form_data->set( iv_key = c_id-label_colors iv_val = ms_settings-label_colors ). " Interaction ro_form_data->set( iv_key = c_id-activate_wo_popup iv_val = boolc( ms_settings-activate_wo_popup = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-adt_jump_enabled iv_val = boolc( ms_settings-adt_jump_enabled = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-link_hints_enabled iv_val = boolc( ms_settings-link_hints_enabled = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-link_hint_key iv_val = |{ ms_settings-link_hint_key }| ). " Resources ro_form_data->set( iv_key = c_id-parallel_proc_disabled iv_val = boolc( ms_settings-parallel_proc_disabled = abap_true ) ) ##TYPE. ENDMETHOD. METHOD render_repo_labels_help_hint. DATA lt_fragments TYPE string_table. DATA lt_labels TYPE string_table. DATA lv_l TYPE string. DATA lo_colors TYPE REF TO zcl_abapgit_string_map. APPEND `

` TO lt_fragments. APPEND `Comma-separated list of label:color pairs.` TO lt_fragments. APPEND ` color part can be either a pre-defined style (see below), or` TO lt_fragments. APPEND ` #fg/bg/border styles, where fg, ` TO lt_fragments. APPEND ` bg, and border are RGB color codes (3 or 6 long).` TO lt_fragments. APPEND ` You can also specify just fg, bg, or` TO lt_fragments. APPEND ` border (defaults will be used for missing parts).` TO lt_fragments. APPEND ` E.g. utils:brown, work:#ff0000/880000, client X:#ddd, client Y:#/333` TO lt_fragments. APPEND `
Available styles:` TO lt_fragments. APPEND `

` TO lt_fragments. APPEND `white` TO lt_labels. APPEND `white-b` TO lt_labels. APPEND `white-r` TO lt_labels. APPEND `grey` TO lt_labels. APPEND `dark-w` TO lt_labels. APPEND `dark-y` TO lt_labels. APPEND `dark-r` TO lt_labels. APPEND `dark-b` TO lt_labels. APPEND `lightblue` TO lt_labels. APPEND `darkblue` TO lt_labels. APPEND `lightgreen` TO lt_labels. APPEND `darkgreen` TO lt_labels. APPEND `lightred` TO lt_labels. APPEND `darkred` TO lt_labels. APPEND `yellow` TO lt_labels. APPEND `darkyellow` TO lt_labels. APPEND `orange` TO lt_labels. APPEND `brown` TO lt_labels. APPEND `pink` TO lt_labels. APPEND `teal` TO lt_labels. APPEND `darkviolet` TO lt_labels. lo_colors = zcl_abapgit_string_map=>create( ). LOOP AT lt_labels INTO lv_l. TRY. lo_colors->set( iv_key = lv_l iv_val = lv_l ). CATCH zcx_abapgit_exception. ENDTRY. ENDLOOP. APPEND zcl_abapgit_gui_chunk_lib=>render_label_list( it_labels = lt_labels io_label_colors = lo_colors ) TO lt_fragments. APPEND `

see also rl-* styles in common.css

` TO lt_fragments. rv_html = zcl_abapgit_gui_chunk_lib=>render_help_hint( concat_lines_of( table = lt_fragments ) ). ENDMETHOD. METHOD save_settings. DATA li_persistence TYPE REF TO zif_abapgit_persist_settings. " Startup ms_settings-show_default_repo = mo_form_data->get( c_id-show_default_repo ). " UI ms_settings-ui_theme = mo_form_data->get( c_id-ui_theme ). ms_settings-icon_scaling = mo_form_data->get( c_id-icon_scaling ). ms_settings-max_lines = mo_form_data->get( c_id-max_lines ). ms_settings-label_colors = zcl_abapgit_repo_labels=>normalize_colors( mo_form_data->get( c_id-label_colors ) ). " Interaction ms_settings-activate_wo_popup = mo_form_data->get( c_id-activate_wo_popup ). ms_settings-adt_jump_enabled = mo_form_data->get( c_id-adt_jump_enabled ). ms_settings-link_hints_enabled = mo_form_data->get( c_id-link_hints_enabled ). ms_settings-link_hint_key = mo_form_data->get( c_id-link_hint_key ). " Resources ms_settings-parallel_proc_disabled = mo_form_data->get( c_id-parallel_proc_disabled ). " Store in DB mo_settings->set_user_settings( ms_settings ). li_persistence = zcl_abapgit_persist_factory=>get_settings( ). li_persistence->modify( mo_settings ). COMMIT WORK AND WAIT. MESSAGE 'Settings successfully saved' TYPE 'S'. mo_form_data = read_settings( ). ENDMETHOD. METHOD validate_form. DATA lx_error TYPE REF TO zcx_abapgit_exception. ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). TRY. zcl_abapgit_repo_labels=>validate_colors( io_form_data->get( c_id-label_colors ) ). CATCH zcx_abapgit_exception INTO lx_error. ro_validation_log->set( iv_key = c_id-label_colors iv_val = lx_error->get_text( ) ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-go_back. rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( io_form_data = mo_form_data io_compare_with = read_settings( ) ). WHEN c_event-save. " Validate form entries before saving mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. save_settings( ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_locl IMPLEMENTATION. METHOD choose_check_variant. DATA ls_variant TYPE zif_abapgit_code_inspector=>ty_variant. DATA lv_popup_cancelled TYPE abap_bool. IF iv_is_return = abap_false. mo_popup_picklist = zcl_abapgit_popup_code_insp=>create( )->create_picklist( )->set_id( c_event-choose_check_variant )->set_in_page( abap_false ). ELSE. lv_popup_cancelled = mo_popup_picklist->was_cancelled( ). IF lv_popup_cancelled = abap_false. mo_popup_picklist->get_result_item( CHANGING cs_selected = ls_variant ). IF ls_variant IS NOT INITIAL. mo_form_data->set( iv_key = c_id-code_inspector_check_variant iv_val = ls_variant-name ). ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD choose_customizing_request. DATA: ls_transport_type TYPE zif_abapgit_definitions=>ty_transport_type, lv_customizing_request TYPE trkorr. ls_transport_type-request = zif_abapgit_cts_api=>c_transport_type-cust_request. ls_transport_type-task = zif_abapgit_cts_api=>c_transport_type-cust_task. lv_customizing_request = zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( ls_transport_type ). IF lv_customizing_request IS NOT INITIAL. mo_form_data->set( iv_key = c_id-customizing_request iv_val = lv_customizing_request ). ENDIF. ENDMETHOD. METHOD choose_labels. DATA: lv_old_labels TYPE string, lv_new_labels TYPE string. lv_old_labels = mo_form_data->get( c_id-labels ). lv_new_labels = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_labels( lv_old_labels ). mo_form_data->set( iv_key = c_id-labels iv_val = lv_new_labels ). ENDMETHOD. METHOD choose_transport_request. DATA: lv_transport_request TYPE trkorr. lv_transport_request = zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( ). IF lv_transport_request IS NOT INITIAL. mo_form_data->set( iv_key = c_id-transport_request iv_val = lv_transport_request ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_repo = io_repo. mo_form = get_form_schema( ). mo_form_data = read_settings( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_locl. CREATE OBJECT lo_component EXPORTING io_repo = io_repo. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Local Settings & Checks' io_page_menu = zcl_abapgit_gui_menus=>repo_settings( iv_key = io_repo->get_key( ) iv_act = zif_abapgit_definitions=>c_action-repo_local_settings ) ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. DATA: li_package TYPE REF TO zif_abapgit_sap_package. li_package = zcl_abapgit_factory=>get_sap_package( mo_repo->get_package( ) ). ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'repo-local-settings-form' iv_help_page = 'https://docs.abapgit.org/settings-local.html' ). ro_form->start_group( iv_name = c_id-local iv_label = 'Local Settings' iv_hint = 'Settings valid for this system only' )->text( iv_name = c_id-display_name iv_label = 'Display Name' iv_hint = 'Name to show instead of original repo name (optional)' ). IF li_package->are_changes_recorded_in_tr_req( ) = abap_true. ro_form->text( iv_name = c_id-transport_request iv_side_action = c_event-choose_transport_request iv_label = |Transport Request| iv_hint = 'Transport request; All changes are recorded therein and no transport popup appears|' ). ENDIF. IF is_customizing_included( ) = abap_true. ro_form->text( iv_name = c_id-customizing_request iv_side_action = c_event-choose_customizing_request iv_label = |Customizing Request| iv_hint = 'Customizing request; All changes are recorded therein and no customizing popup appears|' ). ENDIF. ro_form->text( iv_name = c_id-labels iv_side_action = c_event-choose_labels iv_label = |Labels (comma-separated, allowed chars: "{ zcl_abapgit_repo_labels=>c_allowed_chars }")| iv_hint = 'Comma-separated labels for grouping and repo organization (optional)' )->checkbox( iv_name = c_id-write_protected iv_label = 'Write Protected' iv_hint = 'Lock repository against changes from remote (pull)' )->checkbox( iv_name = c_id-ignore_subpackages iv_label = 'Ignore Subpackages' iv_hint = 'Synchronize root package only' )->checkbox( iv_name = c_id-only_local_objects iv_label = 'Only Local Objects' iv_hint = 'Ignore objects imported from other systems; serialize only objects created in this system' )->checkbox( iv_name = c_id-main_language_only iv_label = 'Only Serialize Main Language' iv_hint = 'Ignore translations; serialize only main language of repository' ). ro_form->checkbox( iv_name = c_id-flow iv_readonly = boolc( li_package->are_changes_recorded_in_tr_req( ) = abap_false ) iv_label = 'BETA: Enable abapGit flow for this repository (requires transported packages)' ). ro_form->start_group( iv_name = c_id-checks iv_label = 'Local Checks' iv_hint = 'Code Inspector check performed to run from menu and before commit' )->text( iv_name = c_id-code_inspector_check_variant iv_side_action = c_event-choose_check_variant iv_label = 'Code Inspector Check Variant' iv_hint = 'Global check variant for Code Inspector or ABAP Test Cockpit' )->checkbox( iv_name = c_id-block_commit iv_label = 'Block Commit If Code Inspection Has Errors' iv_hint = 'Prevent staging if errors of priority 1 or 2 were found during check' )->command( iv_label = 'Save Settings' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-save )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD handle_picklist_state. IF mo_popup_picklist IS BOUND AND ( mo_popup_picklist->is_fulfilled( ) = abap_true OR mo_popup_picklist->is_in_page( ) = abap_false ). " Picklist is either fulfilled OR " it was on its own page and user went back from it via F3/ESC and the picklist had no "graceful back" handler CASE mo_popup_picklist->id( ). WHEN c_event-choose_check_variant. choose_check_variant( abap_true ). WHEN OTHERS. zcx_abapgit_exception=>raise( |Unexpected picklist id { mo_popup_picklist->id( ) }| ). ENDCASE. CLEAR mo_popup_picklist. ENDIF. ENDMETHOD. METHOD is_customizing_included. DATA lt_files TYPE zif_abapgit_definitions=>ty_files_item_tt. lt_files = mo_repo->get_files_local( ). READ TABLE lt_files TRANSPORTING NO FIELDS WITH KEY item-obj_type = zif_abapgit_data_config=>c_data_type-tabu. "todo IF sy-subrc = 0. rv_result = abap_true. ENDIF. ENDMETHOD. METHOD read_settings. DATA: li_package TYPE REF TO zif_abapgit_sap_package. li_package = zcl_abapgit_factory=>get_sap_package( mo_repo->get_package( ) ). " Get settings from DB ms_settings = mo_repo->get_local_settings( ). CREATE OBJECT ro_form_data. " Local Settings ro_form_data->set( iv_key = c_id-display_name iv_val = ms_settings-display_name ). IF li_package->are_changes_recorded_in_tr_req( ) = abap_true. ro_form_data->set( iv_key = c_id-transport_request iv_val = ms_settings-transport_request ). ENDIF. IF is_customizing_included( ) = abap_true. ro_form_data->set( iv_key = c_id-customizing_request iv_val = ms_settings-customizing_request ). ENDIF. ro_form_data->set( iv_key = c_id-labels iv_val = ms_settings-labels ). ro_form_data->set( iv_key = c_id-ignore_subpackages iv_val = boolc( ms_settings-ignore_subpackages = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-main_language_only iv_val = boolc( ms_settings-main_language_only = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-flow iv_val = boolc( ms_settings-flow = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-write_protected iv_val = boolc( ms_settings-write_protected = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-only_local_objects iv_val = boolc( ms_settings-only_local_objects = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-code_inspector_check_variant iv_val = |{ ms_settings-code_inspector_check_variant }| ). ro_form_data->set( iv_key = c_id-block_commit iv_val = boolc( ms_settings-block_commit = abap_true ) ) ##TYPE. ENDMETHOD. METHOD save_settings. ms_settings-display_name = mo_form_data->get( c_id-display_name ). ms_settings-transport_request = mo_form_data->get( c_id-transport_request ). ms_settings-customizing_request = mo_form_data->get( c_id-customizing_request ). ms_settings-labels = zcl_abapgit_repo_labels=>normalize( mo_form_data->get( c_id-labels ) ). ms_settings-ignore_subpackages = mo_form_data->get( c_id-ignore_subpackages ). ms_settings-main_language_only = mo_form_data->get( c_id-main_language_only ). ms_settings-flow = mo_form_data->get( c_id-flow ). ms_settings-write_protected = mo_form_data->get( c_id-write_protected ). ms_settings-only_local_objects = mo_form_data->get( c_id-only_local_objects ). ms_settings-code_inspector_check_variant = mo_form_data->get( c_id-code_inspector_check_variant ). ms_settings-block_commit = mo_form_data->get( c_id-block_commit ). mo_repo->set_local_settings( ms_settings ). COMMIT WORK AND WAIT. MESSAGE 'Settings successfully saved' TYPE 'S'. mo_form_data = read_settings( ). ENDMETHOD. METHOD validate_form. DATA: lx_error TYPE REF TO zcx_abapgit_exception, lv_transport_request TYPE trkorr, lv_customizing_request TYPE trkorr, lv_check_variant TYPE sci_chkv. ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). lv_transport_request = io_form_data->get( c_id-transport_request ). IF lv_transport_request IS NOT INITIAL. TRY. zcl_abapgit_factory=>get_cts_api( )->validate_transport_request( lv_transport_request ). CATCH zcx_abapgit_exception INTO lx_error. ro_validation_log->set( iv_key = c_id-transport_request iv_val = lx_error->get_text( ) ). ENDTRY. ENDIF. lv_customizing_request = io_form_data->get( c_id-customizing_request ). IF lv_customizing_request IS NOT INITIAL. TRY. zcl_abapgit_factory=>get_cts_api( )->validate_transport_request( lv_customizing_request ). CATCH zcx_abapgit_exception INTO lx_error. ro_validation_log->set( iv_key = c_id-customizing_request iv_val = lx_error->get_text( ) ). ENDTRY. ENDIF. lv_check_variant = to_upper( io_form_data->get( c_id-code_inspector_check_variant ) ). IF lv_check_variant IS NOT INITIAL. TRY. zcl_abapgit_factory=>get_code_inspector( mo_repo->get_package( ) )->validate_check_variant( lv_check_variant ). CATCH zcx_abapgit_exception INTO lx_error. ro_validation_log->set( iv_key = c_id-code_inspector_check_variant iv_val = lx_error->get_text( ) ). ENDTRY. ENDIF. IF io_form_data->get( c_id-block_commit ) = abap_true AND lv_check_variant IS INITIAL. ro_validation_log->set( iv_key = c_id-block_commit iv_val = |If block commit is active, a check variant has to be maintained| ). ENDIF. TRY. zcl_abapgit_repo_labels=>validate( io_form_data->get( c_id-labels ) ). CATCH zcx_abapgit_exception INTO lx_error. ro_validation_log->set( iv_key = c_id-labels iv_val = lx_error->get_text( ) ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-go_back. rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( io_form_data = mo_form_data io_compare_with = read_settings( ) ). WHEN c_event-choose_transport_request. choose_transport_request( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_event-choose_customizing_request. choose_customizing_request( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_event-choose_labels. choose_labels( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_event-choose_check_variant. choose_check_variant( ). WHEN c_event-save. " Validate form entries before saving mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. save_settings( ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. IF mo_popup_picklist IS BOUND. " Uniform popup state handling " This should happen only for a new popup because " on the first re-render main component event handling is blocked " and not called again until the popup destruction IF mo_popup_picklist->is_in_page( ) = abap_true. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. rs_handled-page = zcl_abapgit_gui_page_hoc=>create( ii_child_component = mo_popup_picklist iv_show_as_modal = abap_true ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. handle_picklist_state( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( `
` ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false iv_interactive_branch = abap_true ) ). ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( `
` ). IF mo_popup_picklist IS NOT BOUND OR mo_popup_picklist->is_in_page( ) = abap_false. register_handlers( ). ELSEIF mo_popup_picklist->is_in_page( ) = abap_true. " Block usual page events if the popup is an in-page popup ri_html->add( zcl_abapgit_gui_in_page_modal=>create( mo_popup_picklist ) ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_info IMPLEMENTATION. METHOD constructor. super->constructor( ). CREATE OBJECT mo_form_data. mo_repo = io_repo. mo_form = get_form_schema( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_info. CREATE OBJECT lo_component EXPORTING io_repo = io_repo. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Repository Stats' io_page_menu = zcl_abapgit_gui_menus=>repo_settings( iv_key = io_repo->get_key( ) iv_act = zif_abapgit_definitions=>c_action-repo_infos ) ii_child_component = lo_component ). ENDMETHOD. METHOD format_size. DATA: lv_size TYPE p LENGTH 16 DECIMALS 2. IF iv_size > 1024 * 1024 * 1024. lv_size = iv_size / 1024 / 1024 / 1024. rv_size = |{ lv_size } GB|. ELSEIF iv_size > 1024 * 1024. lv_size = iv_size / 1024 / 1024. rv_size = |{ lv_size } MB|. ELSEIF iv_size > 1024. lv_size = iv_size / 1024. rv_size = |{ lv_size } KB|. ELSE. rv_size = |{ iv_size } Bytes|. ENDIF. ENDMETHOD. METHOD format_timestamp. DATA lv_short TYPE timestamp. IF iv_timestamp IS INITIAL. rv_timestamp = 'n/a'. RETURN. ENDIF. cl_abap_tstmp=>move( EXPORTING tstmp_src = iv_timestamp IMPORTING tstmp_tgt = lv_short ). rv_timestamp = |{ lv_short TIMESTAMP = ISO }|. ENDMETHOD. METHOD format_user. DATA lv_title TYPE string. IF iv_username IS INITIAL. rv_user = 'n/a'. RETURN. ENDIF. IF iv_username <> zcl_abapgit_objects_super=>c_user_unknown. lv_title = zcl_abapgit_user_record=>get_title( iv_username ). ENDIF. rv_user = iv_username. IF lv_title IS NOT INITIAL. rv_user = |{ rv_user } ({ lv_title })|. ENDIF. ENDMETHOD. METHOD get_form_schema. DATA lv_label TYPE string. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'repo-infos-form' iv_help_page = 'https://docs.abapgit.org/settings-stats.html' ). IF mo_repo->is_offline( ) = abap_true. lv_label = 'ZIP File'. ELSE. lv_label = 'Remote'. ENDIF. ro_form->start_group( iv_name = c_id-info iv_label = 'Stats' )->text( iv_name = c_id-created_by iv_label = 'Created By' iv_readonly = abap_true )->text( iv_name = c_id-created_at iv_label = 'Created At' iv_readonly = abap_true )->text( iv_name = c_id-deserialized_by iv_label = 'Last Deserialized By' iv_readonly = abap_true )->text( iv_name = c_id-deserialized_at iv_label = 'Last Deserialized At' iv_readonly = abap_true )->table( iv_name = c_id-stats_table iv_label = 'Statistics' )->column( iv_label = 'Measure' iv_width = '50%' iv_readonly = abap_true )->column( iv_label = 'Local' iv_width = '25%' iv_readonly = abap_true )->column( iv_label = lv_label iv_width = '25%' iv_readonly = abap_true )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD read_settings. DATA: ls_repo TYPE zif_abapgit_persistence=>ty_repo, ls_stats TYPE ty_stats, lv_row TYPE i, lv_int TYPE i, lv_val TYPE string. " Get infos from DB TRY. ls_repo = zcl_abapgit_persist_factory=>get_repo( )->read( mo_repo->get_key( ) ). CATCH zcx_abapgit_not_found. zcx_abapgit_exception=>raise( |Repo not found, key { mo_repo->get_key( ) }| ). ENDTRY. read_stats( ). " Infos mo_form_data->set( iv_key = c_id-created_by iv_val = format_user( ls_repo-created_by ) ). mo_form_data->set( iv_key = c_id-created_at iv_val = format_timestamp( ls_repo-created_at ) ). mo_form_data->set( iv_key = c_id-deserialized_by iv_val = format_user( ls_repo-deserialized_by ) ). mo_form_data->set( iv_key = c_id-deserialized_at iv_val = format_timestamp( ls_repo-deserialized_at ) ). LOOP AT mt_stats INTO ls_stats. lv_row = sy-tabix. DO 3 TIMES. CASE sy-index. WHEN 1. lv_val = ls_stats-measure. WHEN 2. lv_val = ls_stats-local. WHEN 3. lv_val = ls_stats-remote. ENDCASE. IF ls_stats-measure CS 'Size' AND sy-index BETWEEN 2 AND 3. lv_int = lv_val. lv_val = format_size( lv_int ). ENDIF. mo_form_data->set( iv_key = |{ c_id-stats_table }-{ lv_row }-{ sy-index }| iv_val = lv_val ). ENDDO. ENDLOOP. mo_form_data->set( iv_key = |{ c_id-stats_table }-{ zif_abapgit_html_form=>c_rows }| iv_val = |{ lv_row }| ). ENDMETHOD. METHOD read_stats. DATA: lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt, lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt, lt_local_items TYPE zif_abapgit_definitions=>ty_items_tt, lt_remote_items TYPE zif_abapgit_definitions=>ty_items_tt. CLEAR mt_stats. read_stats_files( IMPORTING et_local = lt_local et_remote = lt_remote ). read_stats_state( ). read_stats_size_lines_sloc( EXPORTING it_local = lt_local it_remote = lt_remote IMPORTING et_local_items = lt_local_items et_remote_items = lt_remote_items ). read_stats_objects( CHANGING ct_local_items = lt_local_items ct_remote_items = lt_remote_items ). ENDMETHOD. METHOD read_stats_file. TYPES ty_char255 TYPE c LENGTH 255. DATA: lv_code TYPE string, lt_code TYPE STANDARD TABLE OF ty_char255 WITH DEFAULT KEY. FIELD-SYMBOLS: LIKE LINE OF lt_code. rs_info-size = xstrlen( is_file-data ). IF is_file-filename CP '*.abap'. TRY. lv_code = zcl_abapgit_convert=>xstring_to_string_utf8( is_file-data ). CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. SPLIT lv_code AT cl_abap_char_utilities=>newline INTO TABLE lt_code. rs_info-line = lines( lt_code ). LOOP AT lt_code ASSIGNING WHERE table_line IS NOT INITIAL AND table_line(1) <> '*'. SHIFT LEFT DELETING LEADING space. IF (1) <> '"'. rs_info-sloc = rs_info-sloc + 1. ENDIF. ENDLOOP. ENDIF. ENDMETHOD. METHOD read_stats_files. DATA ls_stats TYPE ty_stats. DATA lt_remote_wo_ignored TYPE zif_abapgit_git_definitions=>ty_files_tt. et_local = mo_repo->get_files_local( ). ls_stats-measure = 'Number of Files'. ls_stats-local = lines( et_local ). IF mo_repo->has_remote_source( ) = abap_true. et_remote = mo_repo->get_files_remote( ). ls_stats-remote = lines( et_remote ). lt_remote_wo_ignored = mo_repo->get_files_remote( iv_ignore_files = abap_true ). ENDIF. APPEND ls_stats TO mt_stats. IF et_remote IS NOT INITIAL. CLEAR ls_stats. ls_stats-measure = 'Number of Ignored Files'. ls_stats-remote = lines( et_remote ) - lines( lt_remote_wo_ignored ). APPEND ls_stats TO mt_stats. ENDIF. ENDMETHOD. METHOD read_stats_objects. DATA: ls_stats TYPE ty_stats, ls_item TYPE zif_abapgit_definitions=>ty_item, lt_supported_types TYPE zcl_abapgit_objects=>ty_types_tt. ls_stats-measure = 'Number of Objects'. DELETE ct_local_items WHERE obj_type IS INITIAL OR obj_name IS INITIAL. ls_stats-local = lines( ct_local_items ). DELETE ct_remote_items WHERE obj_type IS INITIAL OR obj_name IS INITIAL. ls_stats-remote = lines( ct_remote_items ). APPEND ls_stats TO mt_stats. CLEAR ls_stats. ls_stats-measure = 'Number of Unsupported Objects'. ls_stats-local = lines( mo_repo->get_unsupported_objects_local( ) ). lt_supported_types = zcl_abapgit_objects=>supported_list( ). LOOP AT ct_remote_items INTO ls_item. READ TABLE lt_supported_types WITH KEY table_line = ls_item-obj_type TRANSPORTING NO FIELDS. IF sy-subrc <> 0. ls_stats-remote = ls_stats-remote + 1. ENDIF. ENDLOOP. APPEND ls_stats TO mt_stats. ENDMETHOD. METHOD read_stats_size_lines_sloc. DATA: ls_stats TYPE ty_stats, lv_ignored TYPE abap_bool, ls_info_file TYPE ty_infos, ls_info_local TYPE ty_infos, ls_info_remote TYPE ty_infos, ls_item TYPE zif_abapgit_definitions=>ty_item. FIELD-SYMBOLS: LIKE LINE OF it_local, LIKE LINE OF it_remote. LOOP AT it_local ASSIGNING . ls_info_file = read_stats_file( -file ). ls_info_local-size = ls_info_local-size + ls_info_file-size. ls_info_local-line = ls_info_local-line + ls_info_file-line. ls_info_local-sloc = ls_info_local-sloc + ls_info_file-sloc. COLLECT -item INTO et_local_items. ENDLOOP. IF mo_repo->has_remote_source( ) = abap_true. LOOP AT it_remote ASSIGNING WHERE filename IS NOT INITIAL. lv_ignored = mo_repo->get_dot_abapgit( )->is_ignored( iv_filename = -filename iv_path = -path ). IF lv_ignored = abap_false. ls_info_file = read_stats_file( ). ls_info_remote-size = ls_info_remote-size + ls_info_file-size. ls_info_remote-line = ls_info_remote-line + ls_info_file-line. ls_info_remote-sloc = ls_info_remote-sloc + ls_info_file-sloc. TRY. zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = -filename iv_path = -path iv_devclass = mo_repo->get_package( ) io_dot = mo_repo->get_dot_abapgit( ) IMPORTING es_item = ls_item ). COLLECT ls_item INTO et_remote_items. CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. ENDIF. ENDLOOP. ENDIF. ls_stats-measure = 'Size of Files'. ls_stats-local = ls_info_local-size. ls_stats-remote = ls_info_remote-size. APPEND ls_stats TO mt_stats. ls_stats-measure = 'Lines in ABAP Files'. ls_stats-local = ls_info_local-line. ls_stats-remote = ls_info_remote-line. APPEND ls_stats TO mt_stats. ls_stats-measure = 'Lines of Code in ABAP Files'. ls_stats-local = ls_info_local-sloc. ls_stats-remote = ls_info_remote-sloc. APPEND ls_stats TO mt_stats. ENDMETHOD. METHOD read_stats_state. DATA: lt_results TYPE zif_abapgit_definitions=>ty_results_tt, lv_state TYPE c LENGTH 1, ls_stats TYPE ty_stats. FIELD-SYMBOLS: LIKE LINE OF lt_results. lt_results = zcl_abapgit_repo_status=>calculate( mo_repo ). DO 3 TIMES. CLEAR ls_stats. CASE sy-index. WHEN 1. ls_stats-measure = 'Number of Modified Files'. lv_state = zif_abapgit_definitions=>c_state-modified. WHEN 2. ls_stats-measure = 'Number of Added Files'. lv_state = zif_abapgit_definitions=>c_state-added. WHEN 3. ls_stats-measure = 'Number of Deleted Files'. lv_state = zif_abapgit_definitions=>c_state-deleted. ENDCASE. LOOP AT lt_results ASSIGNING . IF -lstate = lv_state. ls_stats-local = ls_stats-local + 1. ENDIF. IF -rstate = lv_state AND mo_repo->has_remote_source( ) = abap_true. ls_stats-remote = ls_stats-remote + 1. ENDIF. ENDLOOP. APPEND ls_stats TO mt_stats. ENDDO. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. IF ii_event->mv_action = zif_abapgit_definitions=>c_action-go_back. rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). read_settings( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( `
` ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false iv_interactive_branch = abap_true ) ). ri_html->add( mo_form->render( mo_form_data ) ). ri_html->add( `
` ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_glob IMPLEMENTATION. METHOD constructor. super->constructor( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_form = get_form_schema( ). mo_form_data = read_settings( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_glob. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Global Settings' io_page_menu = zcl_abapgit_gui_menus=>settings( zif_abapgit_definitions=>c_action-go_settings ) ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. CONSTANTS lc_commitmsg_comment_min_len TYPE i VALUE 1. CONSTANTS lc_commitmsg_comment_max_len TYPE i VALUE 255. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'global-setting-form' iv_help_page = 'https://docs.abapgit.org/guide-settings-global.html' ). ro_form->start_group( iv_name = c_id-proxy_settings iv_label = 'Proxy Settings' )->text( iv_name = c_id-proxy_url iv_label = 'Proxy Host' iv_hint = 'Hostname or IP of proxy required to access the Internet (do not enter http://)' iv_placeholder = 'Hostname or IP without http://' )->number( iv_name = c_id-proxy_port iv_label = 'Proxy Port' iv_hint = 'Port of proxy required to access the Internet' iv_min = 0 iv_max = 65535 )->checkbox( iv_name = c_id-proxy_auth iv_label = 'Proxy Authentication' iv_hint = 'Check, if proxy requires you to login' )->textarea( iv_name = c_id-proxy_bypass iv_label = 'Proxy Bypass' iv_hint = 'List of hosts/domains for which to bypass using proxy' )->start_group( iv_name = c_id-commit_settings iv_label = 'Commit Message Settings' )->number( iv_name = c_id-commitmsg_comment_length iv_required = abap_true iv_label = 'Maximum Length of Comment' iv_hint = |At most { lc_commitmsg_comment_max_len } characters| iv_min = lc_commitmsg_comment_min_len iv_max = lc_commitmsg_comment_max_len )->text( iv_name = c_id-commitmsg_comment_deflt iv_label = 'Default Text For Comment' iv_hint = 'You can use $OBJECT or $FILE to include the number of objects/files' )->number( iv_name = c_id-commitmsg_body_size iv_required = abap_true iv_label = 'Maximum Line Size of Body' iv_hint = |Wrap body message at { zcl_abapgit_settings=>c_commitmsg_body_size_dft } characters per line| iv_min = zcl_abapgit_settings=>c_commitmsg_body_size_dft )->checkbox( iv_name = c_id-commitmsg_hide_author iv_label = 'Hide Author Fields' ). IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. ro_form->start_group( iv_name = c_id-devint_settings iv_label = 'Development Internal Settings' )->checkbox( iv_name = c_id-run_critical_tests iv_label = 'Enable Critical Unit Tests' )->text( iv_name = c_id-experimental_features iv_label = 'Experimental Features' iv_hint = 'Set to "X" to enable all features or add feature values as a comma-separated list' ). ENDIF. ro_form->command( iv_label = 'Save Settings' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-save )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD read_proxy_bypass. DATA: lt_proxy_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url, ls_proxy_bypass LIKE LINE OF lt_proxy_bypass, lv_val TYPE string. lt_proxy_bypass = io_settings->get_proxy_bypass( ). LOOP AT lt_proxy_bypass INTO ls_proxy_bypass. lv_val = lv_val && ls_proxy_bypass-low && cl_abap_char_utilities=>newline. ENDLOOP. io_form_data->set( iv_key = c_id-proxy_bypass iv_val = lv_val ). ENDMETHOD. METHOD read_settings. " Get settings from DB mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). CREATE OBJECT ro_form_data. " Proxy ro_form_data->set( iv_key = c_id-proxy_url iv_val = mo_settings->get_proxy_url( ) ). ro_form_data->set( iv_key = c_id-proxy_port iv_val = mo_settings->get_proxy_port( ) ). ro_form_data->set( iv_key = c_id-proxy_auth iv_val = boolc( mo_settings->get_proxy_authentication( ) = abap_true ) ) ##TYPE. read_proxy_bypass( io_settings = mo_settings io_form_data = ro_form_data ). " Commit Message ro_form_data->set( iv_key = c_id-commitmsg_comment_length iv_val = |{ mo_settings->get_commitmsg_comment_length( ) }| ). ro_form_data->set( iv_key = c_id-commitmsg_comment_deflt iv_val = mo_settings->get_commitmsg_comment_default( ) ). ro_form_data->set( iv_key = c_id-commitmsg_body_size iv_val = |{ mo_settings->get_commitmsg_body_size( ) }| ). ro_form_data->set( iv_key = c_id-commitmsg_hide_author iv_val = boolc( mo_settings->get_commitmsg_hide_author( ) = abap_true ) ) ##TYPE. " Dev Internal IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. ro_form_data->set( iv_key = c_id-run_critical_tests iv_val = boolc( mo_settings->get_run_critical_tests( ) = abap_true ) ) ##TYPE. ro_form_data->set( iv_key = c_id-experimental_features iv_val = mo_settings->get_experimental_features( ) ). ENDIF. ENDMETHOD. METHOD save_proxy_bypass. DATA: lt_textarea TYPE TABLE OF string, lt_proxy_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url, ls_proxy_bypass LIKE LINE OF lt_proxy_bypass. lt_textarea = zcl_abapgit_convert=>split_string( mo_form_data->get( c_id-proxy_bypass ) ). ls_proxy_bypass-sign = 'I'. LOOP AT lt_textarea INTO ls_proxy_bypass-low WHERE table_line IS NOT INITIAL. IF ls_proxy_bypass-low CA '*+'. ls_proxy_bypass-option = 'CP'. ELSE. ls_proxy_bypass-option = 'EQ'. ENDIF. APPEND ls_proxy_bypass TO lt_proxy_bypass. ENDLOOP. mo_settings->set_proxy_bypass( lt_proxy_bypass ). ENDMETHOD. METHOD save_settings. DATA: li_persistence TYPE REF TO zif_abapgit_persist_settings, lv_value TYPE i. " Proxy mo_settings->set_proxy_url( mo_form_data->get( c_id-proxy_url ) ). mo_settings->set_proxy_port( mo_form_data->get( c_id-proxy_port ) ). mo_settings->set_proxy_authentication( boolc( mo_form_data->get( c_id-proxy_auth ) = abap_true ) ). save_proxy_bypass( ). " Commit Message lv_value = mo_form_data->get( c_id-commitmsg_comment_length ). mo_settings->set_commitmsg_comment_length( lv_value ). mo_settings->set_commitmsg_comment_default( mo_form_data->get( c_id-commitmsg_comment_deflt ) ). lv_value = mo_form_data->get( c_id-commitmsg_body_size ). mo_settings->set_commitmsg_body_size( lv_value ). mo_settings->set_commitmsg_hide_author( boolc( mo_form_data->get( c_id-commitmsg_hide_author ) = abap_true ) ). " Dev Internal IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. mo_settings->set_run_critical_tests( boolc( mo_form_data->get( c_id-run_critical_tests ) = abap_true ) ). mo_settings->set_experimental_features( mo_form_data->get( c_id-experimental_features ) ). ENDIF. " Store in DB li_persistence = zcl_abapgit_persist_factory=>get_settings( ). li_persistence->modify( mo_settings ). COMMIT WORK AND WAIT. MESSAGE 'Settings successfully saved' TYPE 'S'. mo_form_data = read_settings( ). ENDMETHOD. METHOD validate_form. ro_validation_log = zcl_abapgit_html_form_utils=>create( mo_form )->validate( io_form_data ). IF io_form_data->get( c_id-proxy_url ) IS NOT INITIAL AND io_form_data->get( c_id-proxy_port ) IS INITIAL OR io_form_data->get( c_id-proxy_url ) IS INITIAL AND io_form_data->get( c_id-proxy_port ) IS NOT INITIAL. ro_validation_log->set( iv_key = c_id-proxy_url iv_val = |If you specify a proxy, you have to specify host and port| ). ENDIF. IF ( io_form_data->get( c_id-proxy_url ) IS INITIAL OR io_form_data->get( c_id-proxy_port ) IS INITIAL ) AND io_form_data->get( c_id-proxy_auth ) = abap_true. ro_validation_log->set( iv_key = c_id-proxy_auth iv_val = |To turn on authentication, you have to specify host and port| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-go_back. rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( io_form_data = mo_form_data io_compare_with = read_settings( ) ). WHEN c_event-save. " Validate form entries before saving mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. save_settings( ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_sett_bckg IMPLEMENTATION. METHOD constructor. super->constructor( ). CREATE OBJECT mo_form_data. mo_repo = io_repo. mo_form = get_form_schema( ). mo_form_data = read_settings( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_bckg. CREATE OBJECT lo_component EXPORTING io_repo = io_repo. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Background Mode' io_page_menu = zcl_abapgit_gui_menus=>repo_settings( iv_key = io_repo->get_key( ) iv_act = zif_abapgit_definitions=>c_action-repo_background ) ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. DATA: lt_methods TYPE zcl_abapgit_background=>ty_methods, ls_method LIKE LINE OF lt_methods, lv_hint TYPE string. lt_methods = zcl_abapgit_background=>list_methods( ). ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'repo-background-form' iv_help_page = 'https://docs.abapgit.org/settings-background-mode.html' ). ro_form->start_group( iv_name = c_id-mode_selection iv_label = 'Mode' )->radio( iv_name = c_id-method iv_default_value = '' iv_label = 'Selection' iv_hint = 'Define the action that will be executed in background mode' )->option( iv_label = 'Do Nothing' iv_value = '' ). LOOP AT lt_methods INTO ls_method. ro_form->option( iv_label = ls_method-description iv_value = ls_method-class ). ENDLOOP. ro_form->table( iv_name = c_id-settings iv_hint = 'Settings required for selected background action' iv_label = 'Additional Settings' )->column( iv_label = 'Key' iv_width = '50%' iv_readonly = abap_true )->column( iv_label = 'Value' iv_width = '50%' ). lv_hint = 'Password will be saved in clear text!'. ro_form->start_group( iv_name = c_id-authentication iv_label = 'HTTP Authentication (Optional)' iv_hint = lv_hint )->text( iv_name = c_id-username iv_label = 'Username' iv_hint = lv_hint )->text( iv_name = c_id-password iv_label = 'Password' iv_hint = lv_hint iv_placeholder = lv_hint ). ro_form->command( iv_label = 'Save Settings' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-save )->command( iv_label = 'Run Background Logic' iv_action = zif_abapgit_definitions=>c_action-go_background_run )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD read_persist. DATA lo_per TYPE REF TO zcl_abapgit_persist_background. CREATE OBJECT lo_per. TRY. rs_persist = lo_per->get_by_key( mo_repo->get_key( ) ). CATCH zcx_abapgit_not_found. CLEAR rs_persist. ENDTRY. ENDMETHOD. METHOD read_settings. DATA: ls_per TYPE zcl_abapgit_persist_background=>ty_background, lv_row TYPE i, lv_val TYPE string, lt_settings LIKE ls_per-settings, ls_settings LIKE LINE OF ls_per-settings. ls_per = read_persist( ). CREATE OBJECT ro_form_data. " Mode Selection ro_form_data->set( iv_key = c_id-method iv_val = ls_per-method ). " Mode Settings IF ls_per-method IS NOT INITIAL. lt_settings = ls_per-settings. " skip invalid values, from old background logic IF ls_per-method <> 'push' AND ls_per-method <> 'pull' AND ls_per-method <> 'nothing'. CALL METHOD (ls_per-method)=>zif_abapgit_background~get_settings CHANGING ct_settings = lt_settings. ENDIF. LOOP AT lt_settings INTO ls_settings. lv_row = lv_row + 1. DO 3 TIMES. CASE sy-index. WHEN 1. lv_val = ls_settings-key. WHEN 2. lv_val = ls_settings-value. ENDCASE. ro_form_data->set( iv_key = |{ c_id-settings }-{ lv_row }-{ sy-index }| iv_val = lv_val ). ENDDO. ENDLOOP. ENDIF. mv_settings_count = lv_row. ro_form_data->set( iv_key = |{ c_id-settings }-{ zif_abapgit_html_form=>c_rows }| iv_val = |{ mv_settings_count }| ). " Authentication ro_form_data->set( iv_key = c_id-username iv_val = ls_per-username ). ro_form_data->set( iv_key = c_id-password iv_val = ls_per-password ). ENDMETHOD. METHOD save_settings. DATA: lo_persistence TYPE REF TO zcl_abapgit_persist_background, ls_per TYPE zcl_abapgit_persist_background=>ty_background, lt_settings LIKE ls_per-settings. FIELD-SYMBOLS: LIKE LINE OF ls_per-settings. ls_per-key = mo_repo->get_key( ). " Mode Selection ls_per-method = mo_form_data->get( c_id-method ). " Mode Settings IF ls_per-method IS NOT INITIAL. lt_settings = ls_per-settings. " skip invalid values, from old background logic IF ls_per-method <> 'push' AND ls_per-method <> 'pull' AND ls_per-method <> 'nothing'. CALL METHOD (ls_per-method)=>zif_abapgit_background~get_settings CHANGING ct_settings = lt_settings. ENDIF. LOOP AT lt_settings ASSIGNING . -value = mo_form_data->get( |{ c_id-settings }-{ sy-tabix }-2| ). ENDLOOP. ls_per-settings = lt_settings. ENDIF. " Authentication ls_per-username = mo_form_data->get( c_id-username ). ls_per-password = mo_form_data->get( c_id-password ). CREATE OBJECT lo_persistence. IF ls_per-method IS INITIAL. lo_persistence->delete( ls_per-key ). ELSE. lo_persistence->modify( ls_per ). ENDIF. COMMIT WORK AND WAIT. MESSAGE 'Settings successfully saved' TYPE 'S'. mo_form_data = read_settings( ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. mo_form_data->merge( zcl_abapgit_html_form_utils=>create( mo_form )->normalize( ii_event->form_data( ) ) ). CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-go_back. rs_handled-state = zcl_abapgit_html_form_utils=>create( mo_form )->exit( io_form_data = mo_form_data io_compare_with = read_settings( ) ). WHEN c_event-save. save_settings( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( `
` ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false iv_interactive_branch = abap_true ) ). ri_html->add( mo_form->render( iv_form_class = 'w800px' io_values = mo_form_data ) ). ri_html->add( `
` ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_addonline IMPLEMENTATION. METHOD choose_labels. DATA: lv_old_labels TYPE string, lv_new_labels TYPE string. lv_old_labels = mo_form_data->get( c_id-labels ). lv_new_labels = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_labels( lv_old_labels ). mo_form_data->set( iv_key = c_id-labels iv_val = lv_new_labels ). ENDMETHOD. METHOD constructor. super->constructor( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_form = get_form_schema( ). mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_addonline. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'New Online Repository' ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'add-repo-online-form' iv_help_page = 'https://docs.abapgit.org/guide-online-install.html' ). ro_form->text( iv_name = c_id-url iv_required = abap_true iv_condense = abap_true iv_label = 'Git Repository URL' iv_hint = 'HTTPS address of the repository' iv_placeholder = 'https://github.com/...git' )->text( iv_name = c_id-package iv_side_action = c_event-choose_package iv_required = abap_true iv_upper_case = abap_true iv_label = 'Package' iv_hint = 'SAP package for repository (should be a dedicated one)' iv_placeholder = 'Z... / $...' iv_max = 30 )->text( iv_name = c_id-branch_name iv_side_action = c_event-choose_branch iv_label = 'Branch' iv_hint = 'Switch to a specific branch (default: autodetect)' iv_placeholder = 'Autodetect default branch' )->radio( iv_name = c_id-folder_logic iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix iv_label = 'Folder Logic' iv_hint = 'Define how package folders are named in repository' )->option( iv_label = 'Prefix' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix )->option( iv_label = 'Full' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-full )->option( iv_label = 'Mixed' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-mixed )->text( iv_name = c_id-display_name iv_label = 'Display Name' iv_hint = 'Name to show instead of original repository name (optional)' )->text( iv_name = c_id-labels iv_side_action = c_event-choose_labels iv_label = |Labels (comma-separated, allowed chars: "{ zcl_abapgit_repo_labels=>c_allowed_chars }")| iv_hint = 'Comma-separated labels for grouping and repo organization (optional)' )->checkbox( iv_name = c_id-ignore_subpackages iv_label = 'Ignore Subpackages' iv_hint = 'Synchronize root package only' )->checkbox( iv_name = c_id-main_lang_only iv_label = 'Serialize Main Language Only' iv_hint = 'Ignore translations, serialize just main language' ). IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. ro_form->radio( iv_name = c_id-abap_lang_vers iv_default_value = '' iv_label = 'ABAP Language Version' iv_hint = 'Define the ABAP language version for objects in the repository' )->option( iv_label = 'Any' iv_value = '' )->option( iv_label = 'Ignore' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-ignore )->option( iv_label = 'Standard' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-standard )->option( iv_label = 'For Key Users' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user )->option( iv_label = 'For Cloud Development' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development ). ENDIF. ro_form->command( iv_label = 'Create Online Repo' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-add_online_repo )->command( iv_label = 'Create Package' iv_action = c_event-create_package )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD validate_form. DATA: lv_url TYPE string, lo_url TYPE REF TO zcl_abapgit_git_url, lx_err TYPE REF TO zcx_abapgit_exception. ro_validation_log = mo_form_util->validate( io_form_data ). lv_url = io_form_data->get( c_id-url ). IF lv_url IS NOT INITIAL. TRY. zcl_abapgit_repo_srv=>get_instance( )->validate_url( lv_url ). " Provider-specific URL check CREATE OBJECT lo_url. lo_url->validate_url( lv_url ). CATCH zcx_abapgit_exception INTO lx_err. ro_validation_log->set( iv_key = c_id-url iv_val = lx_err->get_text( ) ). ENDTRY. zcl_abapgit_http=>check_connection( lv_url ). ENDIF. IF io_form_data->get( c_id-package ) IS NOT INITIAL. TRY. zcl_abapgit_repo_srv=>get_instance( )->validate_package( iv_package = |{ io_form_data->get( c_id-package ) }| iv_ign_subpkg = |{ io_form_data->get( c_id-ignore_subpackages ) }| ). CATCH zcx_abapgit_exception INTO lx_err. ro_validation_log->set( iv_key = c_id-package iv_val = lx_err->get_text( ) ). ENDTRY. ENDIF. IF io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-prefix AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-full AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-mixed. ro_validation_log->set( iv_key = c_id-folder_logic iv_val = |Invalid folder logic { io_form_data->get( c_id-folder_logic ) }| ). ENDIF. TRY. zcl_abapgit_repo_labels=>validate( io_form_data->get( c_id-labels ) ). CATCH zcx_abapgit_exception INTO lx_err. ro_validation_log->set( iv_key = c_id-labels iv_val = lx_err->get_text( ) ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA: ls_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params, lo_new_online_repo TYPE REF TO zcl_abapgit_repo_online. mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). CASE ii_event->mv_action. WHEN c_event-create_package. mo_form_data->set( iv_key = c_id-package iv_val = zcl_abapgit_services_repo=>create_package( iv_prefill_package = |{ mo_form_data->get( c_id-package ) }| ) ). IF mo_form_data->get( c_id-package ) IS NOT INITIAL. mo_validation_log = validate_form( mo_form_data ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. WHEN c_event-choose_package. mo_form_data->set( iv_key = c_id-package iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ). IF mo_form_data->get( c_id-package ) IS NOT INITIAL. mo_validation_log = validate_form( mo_form_data ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. WHEN c_event-choose_branch. mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->has( c_id-url ) = abap_true. mo_validation_log->set( iv_key = c_id-branch_name iv_val = 'Check URL issues' ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. " Display errors RETURN. ENDIF. mo_form_data->set( iv_key = c_id-branch_name iv_val = zcl_abapgit_ui_factory=>get_popups( )->branch_list_popup( mo_form_data->get( c_id-url ) )-name ). IF mo_form_data->get( c_id-branch_name ) IS INITIAL. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ELSE. mo_form_data->set( iv_key = c_id-branch_name iv_val = replace( " strip technical val = mo_form_data->get( c_id-branch_name ) sub = zif_abapgit_git_definitions=>c_git_branch-heads_prefix with = '' ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. WHEN c_event-choose_labels. choose_labels( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_event-add_online_repo. mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. mo_form_data->to_abap( CHANGING cs_container = ls_repo_params ). lo_new_online_repo = zcl_abapgit_services_repo=>new_online( ls_repo_params ). rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( lo_new_online_repo->get_key( ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. " Display errors ENDIF. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_addofflin IMPLEMENTATION. METHOD choose_labels. DATA: lv_old_labels TYPE string, lv_new_labels TYPE string. lv_old_labels = mo_form_data->get( c_id-labels ). lv_new_labels = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_labels( lv_old_labels ). mo_form_data->set( iv_key = c_id-labels iv_val = lv_new_labels ). ENDMETHOD. METHOD constructor. super->constructor( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_form = get_form_schema( ). mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_addofflin. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'New Offline Repository' ii_child_component = lo_component ). ENDMETHOD. METHOD get_form_schema. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'add-repo-offline-form' iv_help_page = 'https://docs.abapgit.org/guide-offline-install.html' ). ro_form->text( iv_name = c_id-name iv_required = abap_true iv_label = 'Name' iv_hint = 'Unique name for repository' )->text( iv_name = c_id-package iv_side_action = c_event-choose_package iv_required = abap_true iv_upper_case = abap_true iv_label = 'Package' iv_hint = 'SAP package for repository (should be a dedicated one)' iv_placeholder = 'Z... / $...' iv_max = 30 )->radio( iv_name = c_id-folder_logic iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix iv_label = 'Folder Logic' iv_hint = 'Define how package folders are named in repository' )->option( iv_label = 'Prefix' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix )->option( iv_label = 'Full' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-full )->option( iv_label = 'Mixed' iv_value = zif_abapgit_dot_abapgit=>c_folder_logic-mixed )->text( iv_name = c_id-labels iv_side_action = c_event-choose_labels iv_label = |Labels (comma-separated, allowed chars: "{ zcl_abapgit_repo_labels=>c_allowed_chars }")| iv_hint = 'Comma-separated labels for grouping and repo organization (optional)' )->checkbox( iv_name = c_id-ignore_subpackages iv_label = 'Ignore Subpackages' iv_hint = 'Synchronize root package only' )->checkbox( iv_name = c_id-main_lang_only iv_label = 'Serialize Main Language Only' iv_hint = 'Ignore translations, serialize just main language' ). IF zcl_abapgit_feature=>is_enabled( zcl_abapgit_abap_language_vers=>c_feature_flag ) = abap_true. ro_form->radio( iv_name = c_id-abap_lang_vers iv_default_value = '' iv_label = 'ABAP Language Version' iv_hint = 'Define the ABAP language version for objects in the repository' )->option( iv_label = 'Any' iv_value = '' )->option( iv_label = 'Ignore' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-ignore )->option( iv_label = 'Standard' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-standard )->option( iv_label = 'For Key Users' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user )->option( iv_label = 'For Cloud Development' iv_value = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development ). ENDIF. ro_form->command( iv_label = 'Create Offline Repo' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-add_offline_repo )->command( iv_label = 'Create Package' iv_action = c_event-create_package )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD validate_form. DATA lx_err TYPE REF TO zcx_abapgit_exception. ro_validation_log = mo_form_util->validate( io_form_data ). IF io_form_data->get( c_id-package ) IS NOT INITIAL. TRY. zcl_abapgit_repo_srv=>get_instance( )->validate_package( iv_package = |{ io_form_data->get( c_id-package ) }| iv_ign_subpkg = |{ io_form_data->get( c_id-ignore_subpackages ) }| ). CATCH zcx_abapgit_exception INTO lx_err. ro_validation_log->set( iv_key = c_id-package iv_val = lx_err->get_text( ) ). ENDTRY. ENDIF. IF io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-prefix AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-full AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-mixed. ro_validation_log->set( iv_key = c_id-folder_logic iv_val = |Invalid folder logic { io_form_data->get( c_id-folder_logic ) }| ). ENDIF. TRY. zcl_abapgit_repo_labels=>validate( io_form_data->get( c_id-labels ) ). CATCH zcx_abapgit_exception INTO lx_err. ro_validation_log->set( iv_key = c_id-labels iv_val = lx_err->get_text( ) ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA: ls_repo_params TYPE zif_abapgit_services_repo=>ty_repo_params, lo_new_offline_repo TYPE REF TO zcl_abapgit_repo_offline. mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). CASE ii_event->mv_action. WHEN c_event-create_package. mo_form_data->set( iv_key = c_id-package iv_val = zcl_abapgit_services_repo=>create_package( iv_prefill_package = |{ mo_form_data->get( c_id-package ) }| ) ). IF mo_form_data->get( c_id-package ) IS NOT INITIAL. mo_validation_log = validate_form( mo_form_data ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. WHEN c_event-choose_package. mo_form_data->set( iv_key = c_id-package iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ). IF mo_form_data->get( c_id-package ) IS NOT INITIAL. mo_validation_log = validate_form( mo_form_data ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. WHEN c_event-choose_labels. choose_labels( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_event-add_offline_repo. mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. mo_form_data->to_abap( CHANGING cs_container = ls_repo_params ). lo_new_offline_repo = zcl_abapgit_services_repo=>new_offline( ls_repo_params ). rs_handled-page = zcl_abapgit_gui_page_repo_view=>create( lo_new_offline_repo->get_key( ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. " Display errors ENDIF. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_db_entry IMPLEMENTATION. METHOD build_toolbar. CREATE OBJECT ro_toolbar. IF mv_edit_mode = abap_true. ro_toolbar->add( iv_act = |submitFormById('{ c_edit_form_id }');| iv_txt = 'Save' iv_typ = zif_abapgit_html=>c_action_type-onclick iv_opt = zif_abapgit_html=>c_html_opt-strong ). ELSE. ro_toolbar->add( iv_act = |{ c_action-switch_mode }| iv_txt = 'Edit' ). ENDIF. ro_toolbar->add( iv_act = zif_abapgit_definitions=>c_action-go_back iv_txt = 'Back' ). ENDMETHOD. METHOD constructor. super->constructor( ). register_stylesheet( ). mv_edit_mode = iv_edit_mode. ms_key = is_key. ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_db_entry. CREATE OBJECT lo_component EXPORTING iv_edit_mode = iv_edit_mode is_key = is_key. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_extra_css_url = c_css_url ii_page_title_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD dbcontent_decode. rs_content-type = io_form_data->get( 'TYPE' ). rs_content-value = io_form_data->get( 'VALUE' ). rs_content-data_str = io_form_data->get( 'XMLDATA' ). IF rs_content-data_str(1) <> '<' AND rs_content-data_str+1(1) = '<'. " Hmmm ??? rs_content-data_str = rs_content-data_str+1. ENDIF. ENDMETHOD. METHOD do_update. ASSERT is_content-type IS NOT INITIAL. zcl_abapgit_persistence_db=>get_instance( )->update( iv_type = is_content-type iv_value = is_content-value iv_data = is_content-data_str ). COMMIT WORK. ENDMETHOD. METHOD register_stylesheet. DATA lo_buf TYPE REF TO zcl_abapgit_string_buffer. CREATE OBJECT lo_buf. **************************************************** * abapmerge Pragma [include] - ZABAPGIT_CSS_PAGE_DB_ENTRY.W3MI.DATA.CSS **************************************************** lo_buf->add( '/*' ). lo_buf->add( ' * PAGE DB ENTRY CSS' ). lo_buf->add( ' */' ). lo_buf->add( '' ). lo_buf->add( '/* LAYOUT */' ). lo_buf->add( '' ). lo_buf->add( '.db-entry {' ). lo_buf->add( ' padding: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry pre {' ). lo_buf->add( ' display: block;' ). lo_buf->add( ' font-size: 10pt;' ). lo_buf->add( ' overflow: hidden;' ). lo_buf->add( ' word-wrap:break-word;' ). lo_buf->add( ' white-space: pre-wrap;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' padding: 0.5em;' ). lo_buf->add( ' margin: 0.5em 0em;' ). lo_buf->add( ' width: 98%;' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry textarea {' ). lo_buf->add( ' margin: 0.5em 0em;' ). lo_buf->add( ' width: 98%;' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry .toolbar {' ). lo_buf->add( ' padding-left: 0.5em;' ). lo_buf->add( ' padding-right: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry dl.entry-tag div {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' border: 1px solid;' ). lo_buf->add( ' border-radius: 3px;' ). lo_buf->add( ' margin-right: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry dl.entry-tag div:last-child {' ). lo_buf->add( ' margin-right: 0px;' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry dt, .db-entry dd {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' margin-left: 0px;' ). lo_buf->add( ' padding: 2px 5px;' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry dt::after { content: ":" }' ). lo_buf->add( '' ). lo_buf->add( '/* COLORS */' ). lo_buf->add( '' ). lo_buf->add( '.db-entry {' ). lo_buf->add( ' background-color: var(--theme-container-background-color);' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry pre, .db-entry textarea {' ). lo_buf->add( ' background-color: var(--theme-table-background-color);' ). lo_buf->add( ' border-color: var(--theme-container-border-color);' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry dl.entry-tag div {' ). lo_buf->add( ' border-color: hsl(206, 20%, 75%);' ). lo_buf->add( ' background-color: hsl(206, 20%, 90%);' ). lo_buf->add( '}' ). lo_buf->add( '.db-entry dt {' ). lo_buf->add( ' background-color: hsl(206, 20%, 75%);' ). lo_buf->add( '}' ). gui_services( )->register_page_asset( iv_url = c_css_url iv_type = 'text/css' iv_mime_name = 'ZABAPGIT_CSS_PAGE_DB_ENTRY' iv_inline = lo_buf->join_w_newline_and_flush( ) ). ENDMETHOD. METHOD render_edit. DATA lv_formatted TYPE string. lv_formatted = escape( val = zcl_abapgit_xml_pretty=>print( iv_raw_db_value ) format = cl_abap_format=>e_html_attr ). " Form ii_html->add( |
| ). ii_html->add( || ). ii_html->add( || ). ii_html->add( || ). ii_html->add( '
' ). ENDMETHOD. METHOD render_entry_tag. rv_html = ||. ENDMETHOD. METHOD render_header. ii_html->add( '
' ). ii_html->add( io_toolbar->render( iv_right = abap_true ) ). ii_html->add( render_entry_tag( ms_key ) ). ii_html->add( '
' ). ENDMETHOD. METHOD render_view. DATA lo_highlighter TYPE REF TO zcl_abapgit_syntax_highlighter. DATA lv_formatted TYPE string. " Create syntax highlighter lo_highlighter = zcl_abapgit_syntax_factory=>create( '*.xml' ). lv_formatted = lo_highlighter->process_line( zcl_abapgit_xml_pretty=>print( iv_raw_db_value ) ). ii_html->add( |
{ lv_formatted }
| ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. CASE ii_event->mv_action. WHEN c_action-switch_mode. mv_edit_mode = boolc( mv_edit_mode = abap_false ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_action-update. do_update( dbcontent_decode( ii_event->form_data( ) ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_page_title~get_page_title. IF mv_edit_mode = abap_true. rv_title = 'Config Edit'. ELSE. rv_title = 'Config Display'. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA lv_raw_db_value TYPE zif_abapgit_persistence=>ty_content-data_str. register_handlers( ). TRY. lv_raw_db_value = zcl_abapgit_persistence_db=>get_instance( )->read( iv_type = ms_key-type iv_value = ms_key-value ). CATCH zcx_abapgit_not_found ##NO_HANDLER. ENDTRY. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). render_header( ii_html = ri_html io_toolbar = build_toolbar( ) ). IF mv_edit_mode = abap_true. zcl_abapgit_persistence_db=>get_instance( )->lock( iv_type = ms_key-type iv_value = ms_key-value ). render_edit( iv_raw_db_value = lv_raw_db_value ii_html = ri_html ). ELSE. render_view( iv_raw_db_value = lv_raw_db_value ii_html = ri_html ). ENDIF. ri_html->add( '
' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_db IMPLEMENTATION. METHOD constructor. super->constructor( ). register_stylesheet( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_db. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Database Utility' iv_extra_css_url = c_css_url ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD do_backup_db. DATA: lt_data TYPE zif_abapgit_persistence=>ty_contents, lv_text TYPE string, lt_toc TYPE string_table, lo_zip TYPE REF TO cl_abap_zip, lv_zip TYPE xstring, lv_path TYPE string, lv_filename TYPE string, li_fe_serv TYPE REF TO zif_abapgit_frontend_services. FIELD-SYMBOLS: LIKE LINE OF lt_data. lt_data = zcl_abapgit_persistence_db=>get_instance( )->list( ). lv_text = |Table of Content\n|. INSERT lv_text INTO TABLE lt_toc. lv_text = |================\n|. INSERT lv_text INTO TABLE lt_toc. lv_text = |\n|. INSERT lv_text INTO TABLE lt_toc. CREATE OBJECT lo_zip. LOOP AT lt_data ASSIGNING . IF -type = zcl_abapgit_persistence_db=>c_type_repo_csum. CONCATENATE -type '_' -value '.txt' INTO lv_filename. ELSE. CONCATENATE -type '_' -value '.xml' INTO lv_filename. ENDIF. lo_zip->add( name = lv_filename content = zcl_abapgit_convert=>string_to_xstring_utf8( -data_str ) ). lv_text = explain_content( ). REPLACE '' IN lv_text WITH ''. REPLACE '' IN lv_text WITH ''. lv_text = |{ -type },{ -value },{ lv_text }\n|. INSERT lv_text INTO TABLE lt_toc. ENDLOOP. lo_zip->add( name = c_toc_filename content = zcl_abapgit_convert=>string_to_xstring_utf8( concat_lines_of( lt_toc ) ) ). lv_zip = lo_zip->save( ). CONCATENATE 'abapGit_Backup_' sy-datlo '_' sy-timlo '.zip' INTO lv_filename. li_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). lv_path = li_fe_serv->show_file_save_dialog( iv_title = 'abapGit Backup' iv_extension = 'zip' iv_default_filename = lv_filename ). li_fe_serv->file_download( iv_path = lv_path iv_xstr = lv_zip ). MESSAGE 'abapGit Backup successfully saved' TYPE 'S'. ENDMETHOD. METHOD do_delete_entry. DATA lv_answer TYPE c LENGTH 1. ASSERT is_key-type IS NOT INITIAL. lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = 'Warning' iv_text_question = |Are you sure you want to delete entry { is_key-type } { is_key-value }?| iv_text_button_1 = 'Yes' iv_icon_button_1 = 'ICON_DELETE' iv_text_button_2 = 'No' iv_icon_button_2 = 'ICON_CANCEL' iv_default_button = '2' iv_display_cancel_button = abap_false ). IF lv_answer = '2'. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. zcl_abapgit_persistence_db=>get_instance( )->delete( iv_type = is_key-type iv_value = is_key-value ). " If deleting repo, also delete corresponding checksums " Other way around is ok, since checksums are automatically recreated IF is_key-type = zcl_abapgit_persistence_db=>c_type_repo. zcl_abapgit_persistence_db=>get_instance( )->delete( iv_type = zcl_abapgit_persistence_db=>c_type_repo_csum iv_value = is_key-value ). " Initialize repo list zcl_abapgit_repo_srv=>get_instance( )->init( ). " TODO: think how to remove this code, " maybe implement subscription in persistence_db, " so that repo_srv receive a notification on add/delete ENDIF. COMMIT WORK. ENDMETHOD. METHOD do_restore_db. DATA: lv_answer TYPE c LENGTH 1, lo_zip TYPE REF TO cl_abap_zip, lv_zip TYPE xstring, lv_path TYPE string, lv_filename TYPE string, lv_data TYPE xstring, ls_data TYPE zif_abapgit_persistence=>ty_content, lt_data TYPE zif_abapgit_persistence=>ty_contents, lt_data_old TYPE zif_abapgit_persistence=>ty_contents, li_fe_serv TYPE REF TO zif_abapgit_frontend_services. FIELD-SYMBOLS: LIKE LINE OF lo_zip->files. li_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). lv_path = li_fe_serv->show_file_open_dialog( iv_title = 'Restore abapGit Backup' iv_extension = 'zip' iv_default_filename = 'abapGit_Backup_*.zip' ). lv_zip = li_fe_serv->file_upload( lv_path ). CREATE OBJECT lo_zip. lo_zip->load( EXPORTING zip = lv_zip EXCEPTIONS zip_parse_error = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error loading ZIP file' ). ENDIF. LOOP AT lo_zip->files ASSIGNING WHERE name <> c_toc_filename. CLEAR ls_data. lv_filename = -name. REPLACE '.xml' IN lv_filename WITH ''. REPLACE '.txt' IN lv_filename WITH ''. IF lv_filename CP 'REPO_CS*'. ls_data-type = lv_filename(7). ls_data-value = lv_filename+8(*). ELSE. SPLIT lv_filename AT '_' INTO ls_data-type ls_data-value. ENDIF. " Validate DB key TRY. zcl_abapgit_persistence_db=>validate_entry_type( ls_data-type ). CATCH zcx_abapgit_exception. zcx_abapgit_exception=>raise( |Invalid DB entry type. This is not an abapGit Backup| ). ENDTRY. lo_zip->get( EXPORTING name = -name IMPORTING content = lv_data EXCEPTIONS zip_index_error = 1 zip_decompression_error = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error getting file { -name } from ZIP| ). ENDIF. ls_data-data_str = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). INSERT ls_data INTO TABLE lt_data. ENDLOOP. lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = 'Warning' iv_text_question = 'All existing repositories and settings will be deleted and overwritten! Continue?' iv_text_button_1 = 'Restore' iv_icon_button_1 = 'ICON_IMPORT' iv_text_button_2 = 'Cancel' iv_icon_button_2 = 'ICON_CANCEL' iv_default_button = '2' iv_display_cancel_button = abap_false ). IF lv_answer <> '1'. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. lt_data_old = zcl_abapgit_persistence_db=>get_instance( )->list( ). LOOP AT lt_data_old INTO ls_data. zcl_abapgit_persistence_db=>get_instance( )->delete( iv_type = ls_data-type iv_value = ls_data-value ). ENDLOOP. COMMIT WORK AND WAIT. LOOP AT lt_data INTO ls_data. zcl_abapgit_persistence_db=>get_instance( )->add( iv_type = ls_data-type iv_value = ls_data-value iv_data = ls_data-data_str ). ENDLOOP. COMMIT WORK AND WAIT. MESSAGE 'abapGit Backup successfully restored' TYPE 'S'. ENDMETHOD. METHOD explain_content. DATA lv_descr TYPE string. DATA ls_explanation TYPE ty_explanation. CASE is_data-type. WHEN zcl_abapgit_persistence_db=>c_type_repo. lv_descr = 'Repo Settings'. ls_explanation = explain_content_repo( is_data ). WHEN zcl_abapgit_persistence_db=>c_type_background. lv_descr = 'Background Settings'. ls_explanation = explain_content_background( is_data ). WHEN zcl_abapgit_persistence_db=>c_type_user. lv_descr = 'Personal Settings'. ls_explanation-value = zcl_abapgit_user_record=>get_instance( is_data-value )->get_name( ). WHEN zcl_abapgit_persistence_db=>c_type_settings. lv_descr = 'Global Settings'. WHEN zcl_abapgit_persistence_db=>c_type_packages. lv_descr = 'Local Package Details'. WHEN zcl_abapgit_persistence_db=>c_type_repo_csum. lv_descr = 'Repo Checksums'. ls_explanation = explain_content_repo_cs( is_data ). WHEN OTHERS. IF strlen( is_data-data_str ) >= 250. ls_explanation-value = is_data-data_str(250). ELSE. ls_explanation-value = is_data-data_str. ENDIF. ls_explanation-value = escape( val = ls_explanation-value format = cl_abap_format=>e_html_attr ). ls_explanation-value = |
{ ls_explanation-value }
|. ENDCASE. IF ls_explanation-value IS NOT INITIAL. lv_descr = |{ lv_descr }: |. ENDIF. IF ls_explanation-extra IS NOT INITIAL. ls_explanation-extra = | ({ ls_explanation-extra })|. ENDIF. rv_text = |{ lv_descr }{ ls_explanation-value }{ ls_explanation-extra }|. IF strlen( rv_text ) >= 250. rv_text = rv_text(250) && '...'. ENDIF. ENDMETHOD. METHOD explain_content_background. DATA: ls_result TYPE match_result, ls_match TYPE submatch_result, lv_class TYPE string, ls_method LIKE LINE OF mt_methods. rs_expl-value = |{ zcl_abapgit_repo_srv=>get_instance( )->get( is_data-value )->get_name( ) }|. FIND FIRST OCCURRENCE OF REGEX '(.*)' IN is_data-data_str IGNORING CASE RESULTS ls_result. READ TABLE ls_result-submatches INTO ls_match INDEX 1. IF sy-subrc = 0. lv_class = is_data-data_str+ls_match-offset(ls_match-length). ENDIF. IF mt_methods IS INITIAL. mt_methods = zcl_abapgit_background=>list_methods( ). ENDIF. READ TABLE mt_methods INTO ls_method WITH TABLE KEY class = lv_class. IF sy-subrc = 0. rs_expl-extra = ls_method-description. ELSE. rs_expl-extra = lv_class. ENDIF. ENDMETHOD. METHOD explain_content_repo. DATA: ls_result TYPE match_result, ls_match TYPE submatch_result, lv_cnt TYPE i. FIND FIRST OCCURRENCE OF REGEX '' IN is_data-data_str IGNORING CASE MATCH COUNT lv_cnt. IF lv_cnt > 0. rs_expl-extra = 'Online'. ELSE. rs_expl-extra = 'Offline'. ENDIF. FIND FIRST OCCURRENCE OF REGEX '(.*)' IN is_data-data_str IGNORING CASE RESULTS ls_result. READ TABLE ls_result-submatches INTO ls_match INDEX 1. IF sy-subrc = 0. rs_expl-value = is_data-data_str+ls_match-offset(ls_match-length). ELSE. FIND FIRST OCCURRENCE OF REGEX '(.*)' IN is_data-data_str IGNORING CASE RESULTS ls_result. READ TABLE ls_result-submatches INTO ls_match INDEX 1. IF sy-subrc = 0. rs_expl-value = is_data-data_str+ls_match-offset(ls_match-length). ENDIF. ENDIF. IF rs_expl-value IS INITIAL. FIND FIRST OCCURRENCE OF REGEX '(.*)' IN is_data-data_str IGNORING CASE RESULTS ls_result. READ TABLE ls_result-submatches INTO ls_match INDEX 1. IF sy-subrc = 0. rs_expl-value = is_data-data_str+ls_match-offset(ls_match-length). IF lv_cnt > 0. rs_expl-value = zcl_abapgit_url=>name( rs_expl-value ). ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD explain_content_repo_cs. DATA lt_lines TYPE string_table. IF strlen( is_data-data_str ) > 0. SPLIT is_data-data_str AT cl_abap_char_utilities=>newline INTO TABLE lt_lines. rs_expl-extra = |{ lines( lt_lines ) } lines|. READ TABLE lt_lines INDEX 1 INTO rs_expl-value. IF sy-subrc = 0. REPLACE '#repo_name#' IN rs_expl-value WITH ''. rs_expl-value = escape( val = rs_expl-value format = cl_abap_format=>e_html_attr ). ENDIF. ENDIF. ENDMETHOD. METHOD register_stylesheet. DATA lo_buf TYPE REF TO zcl_abapgit_string_buffer. CREATE OBJECT lo_buf. **************************************************** * abapmerge Pragma [include] - ZABAPGIT_CSS_PAGE_DB.W3MI.DATA.CSS **************************************************** lo_buf->add( '/*' ). lo_buf->add( ' * PAGE DB CSS' ). lo_buf->add( ' */' ). lo_buf->add( '' ). lo_buf->add( '/* LAYOUT */' ). lo_buf->add( '' ). lo_buf->add( '.db-list {' ). lo_buf->add( ' padding: 0.5em;' ). lo_buf->add( ' overflow-x: auto;' ). lo_buf->add( '}' ). lo_buf->add( '.db-list table { table-layout: fixed; }' ). lo_buf->add( '.db-list table pre {' ). lo_buf->add( ' display: inline-block;' ). lo_buf->add( ' overflow: hidden;' ). lo_buf->add( ' word-wrap:break-word;' ). lo_buf->add( ' white-space: pre-wrap;' ). lo_buf->add( ' margin: 0px;' ). lo_buf->add( ' width: 30em;' ). lo_buf->add( '}' ). lo_buf->add( '.db-list table th {' ). lo_buf->add( ' text-align: left;' ). lo_buf->add( ' padding: 0.5em;' ). lo_buf->add( '}' ). lo_buf->add( '.db-list table thead tr { border-bottom: 1px solid; }' ). lo_buf->add( '.db-list table td {' ). lo_buf->add( ' padding: 4px 0.5em;' ). lo_buf->add( ' vertical-align: middle;' ). lo_buf->add( ' word-break: break-all;' ). lo_buf->add( '}' ). lo_buf->add( '.db-list table td.data { font-style: italic; }' ). lo_buf->add( '' ). lo_buf->add( '/* COLORS */' ). lo_buf->add( '' ). lo_buf->add( '.db-list { background-color: var(--theme-table-background-color); }' ). lo_buf->add( '.db-list table td { color: var(--theme-primary-font-color); }' ). lo_buf->add( '.db-list table td.data { color: var(--theme-greyscale-dark); }' ). lo_buf->add( '.db-list table tbody tr:hover td { background-color: rgba(0, 0, 0, 0.075); }' ). lo_buf->add( '.db-list table tbody tr:active td { background-color: #f4f4f4; } /* Needed? */' ). lo_buf->add( '.db-list table th { color: var(--theme-link-color); }' ). lo_buf->add( '.db-list table thead tr { border-color: var(--theme-table-border-color); }' ). gui_services( )->register_page_asset( iv_url = c_css_url iv_type = 'text/css' iv_mime_name = 'ZABAPGIT_CSS_PAGE_DB' iv_inline = lo_buf->join_w_newline_and_flush( ) ). ENDMETHOD. METHOD render_stats. DATA: lv_cnt TYPE i, lv_online TYPE i, lv_offline TYPE i, lv_users TYPE i. FIELD-SYMBOLS LIKE LINE OF it_db_entries. LOOP AT it_db_entries ASSIGNING . IF -type = zcl_abapgit_persistence_db=>c_type_repo. FIND FIRST OCCURRENCE OF REGEX '' IN -data_str IGNORING CASE MATCH COUNT lv_cnt. IF lv_cnt > 0. lv_online = lv_online + 1. ELSE. lv_offline = lv_offline + 1. ENDIF. ELSEIF -type = zcl_abapgit_persistence_db=>c_type_user. lv_users = lv_users + 1. ENDIF. ENDLOOP. ri_html = zcl_abapgit_html=>create( ). ri_html->add( |Repositories: { lv_online + lv_offline } ({ lv_online } online, { lv_offline } offline),| ). ri_html->add( |Users: { lv_users }| ). ENDMETHOD. METHOD render_table. ri_html = zcl_abapgit_html_table=>create( me )->define_column( iv_column_id = 'type' iv_column_title = 'Type' )->define_column( iv_column_id = 'value' iv_column_title = 'Key' )->define_column( iv_column_id = 'expl' iv_column_title = 'Data' )->define_column( 'cmd' )->render( it_db_entries ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA ls_db TYPE zif_abapgit_persistence=>ty_content. DATA lo_query TYPE REF TO zcl_abapgit_string_map. lo_query = ii_event->query( ). CASE ii_event->mv_action. WHEN c_action-delete. lo_query->to_abap( CHANGING cs_container = ls_db ). do_delete_entry( ls_db ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_action-backup. do_backup_db( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_action-restore. do_restore_db( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar. ro_toolbar->add( iv_txt = 'Backup' iv_act = c_action-backup ). ro_toolbar->add( iv_txt = 'Restore' iv_act = c_action-restore ). ro_toolbar->add( iv_txt = 'Back' iv_act = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA lt_db_entries TYPE zif_abapgit_persistence=>ty_contents. register_handlers( ). lt_db_entries = zcl_abapgit_persistence_db=>get_instance( )->list( ). ri_html = zcl_abapgit_html=>create( ). ri_html->add( '
' ). ri_html->add( render_stats( lt_db_entries ) ). ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( render_table( lt_db_entries ) ). ri_html->add( '
' ). ENDMETHOD. METHOD zif_abapgit_html_table~get_row_attrs. ENDMETHOD. METHOD zif_abapgit_html_table~render_cell. DATA lv_action TYPE string. DATA lo_toolbar TYPE REF TO zcl_abapgit_html_toolbar. CASE iv_column_id. WHEN 'type' OR 'value'. rs_render-content = |{ iv_value }|. WHEN 'expl'. rs_render-content = explain_content( is_row ). rs_render-css_class = 'data'. WHEN 'cmd'. lv_action = zcl_abapgit_html_action_utils=>dbkey_encode( is_row ). lo_toolbar = zcl_abapgit_html_toolbar=>create( )->add( iv_txt = 'Display' iv_act = |{ zif_abapgit_definitions=>c_action-db_display }?{ lv_action }| )->add( iv_txt = 'Edit' iv_act = |{ zif_abapgit_definitions=>c_action-db_edit }?{ lv_action }| )->add( iv_txt = 'Delete' iv_act = |{ c_action-delete }?{ lv_action }| ). rs_render-html = lo_toolbar->render( ). ENDCASE. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_WHEREUSED IMPLEMENTATION. METHOD constructor. super->constructor( ). IF ii_repo IS BOUND. mv_package = ii_repo->get_package( ). mv_ignore_subpackages = ii_repo->get_local_settings( )-ignore_subpackages. ELSE. mv_package = iv_package. ENDIF. IF mv_package IS INITIAL OR zcl_abapgit_factory=>get_sap_package( mv_package )->exists( ) = abap_false. zcx_abapgit_exception=>raise( |Package { mv_package } does not exist| ). ENDIF. run_where_used( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_whereused. CREATE OBJECT lo_component EXPORTING ii_repo = ii_repo iv_package = iv_package. ri_page = zcl_abapgit_gui_page_hoc=>create( lo_component ). ENDMETHOD. METHOD init_table_component. DATA ls_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state. IF mi_table IS BOUND. RETURN. ENDIF. IF ls_sorting_state-column_id IS INITIAL. ls_sorting_state-column_id = 'package'. ENDIF. mi_table = zcl_abapgit_html_table=>create( ii_renderer = me is_initial_sorting_state = ls_sorting_state ). mi_table->define_column_group( iv_group_title = 'Repo object' iv_group_id = '' " No need )->define_column( iv_column_id = 'dep_package' iv_column_title = 'Package' )->define_column( iv_column_id = 'dep_obj_type' iv_column_title = 'Type' )->define_column( iv_column_id = 'dep_obj_name' iv_column_title = 'Name' ). mi_table->define_column_group( iv_group_title = 'Used in' iv_group_id = 'where' " Needed for CSS )->define_column( iv_column_id = 'package' iv_column_title = 'Package' )->define_column( iv_column_id = 'obj_type' iv_column_title = 'Type' )->define_column( iv_column_id = 'obj_name' iv_column_title = 'Name' ). ENDMETHOD. METHOD render_filter_help_hint. DATA li_html TYPE REF TO zif_abapgit_html. li_html = zcl_abapgit_html=>create( )->add( `

This tool cycles through all objects in the repo ` )->add( `and runs the standard where-used function against it. ` )->add( `The result is displayed here less the usages ` )->add( `inside the repo itself.

` )->add( `

The tool can be used to detect ` )->add( `potential regressions in the code which uses the repo ` )->add( `and external to it (e.g. when deploying updates ` )->add( `to a library-like repo).

` ). rv_html = zcl_abapgit_gui_chunk_lib=>render_help_hint( li_html->render( iv_no_line_breaks = abap_true ) ). ENDMETHOD. METHOD render_header. DATA lv_sub_hint TYPE string. IF mv_ignore_subpackages = abap_false. lv_sub_hint = ' and its subpackages'. ENDIF. ii_html->div( iv_class = 'wu-header' iv_content = |Where used for package { zcl_abapgit_gui_chunk_lib=>render_package_name( mv_package )->render( iv_no_line_breaks = abap_true ) }{ lv_sub_hint } in other packages. { render_filter_help_hint( ) }| ). ENDMETHOD. METHOD run_where_used. mt_where_used = zcl_abapgit_where_used_tools=>new( )->select_external_usages( iv_ignore_subpackages = mv_ignore_subpackages iv_package = mv_package ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. IF mi_table->process_sorting_request( ii_event->mv_action ) = abap_true. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. RETURN. ENDIF. CASE ii_event->mv_action. WHEN c_action-refresh. run_where_used( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN c_action-show_used_obj. mv_show_used_obj = boolc( mv_show_used_obj = abap_false ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. rt_hotkey_actions = zif_abapgit_gui_menu_provider~get_menu( )->get_hotkeys( c_title ). ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. DATA lv_show_used_txt TYPE string. IF mv_show_used_obj = abap_true. lv_show_used_txt = 'Hide Used Type'. ELSE. lv_show_used_txt = 'Show Used Type'. ENDIF. ro_toolbar = zcl_abapgit_html_toolbar=>create( )->add( iv_txt = lv_show_used_txt iv_title = 'Show/Hide used type or object (when available)' iv_act = c_action-show_used_obj iv_hotkey = 'u' )->add( iv_txt = 'Refresh' iv_act = c_action-refresh iv_hotkey = 'r' ). ENDMETHOD. METHOD zif_abapgit_gui_page_title~get_page_title. rv_title = c_title. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). init_table_component( ). ri_html = zcl_abapgit_html=>create( ). render_header( ri_html ). IF mt_where_used IS INITIAL. ri_html->add( zcl_abapgit_gui_chunk_lib=>render_success( 'No usages found' ) ). ELSE. ri_html->div( iv_class = 'wu' ii_content = mi_table->render( iv_wrap_in_div = 'default-table-container' iv_css_class = 'default-table' iv_with_cids = abap_true it_data = mt_where_used ) ). ENDIF. ENDMETHOD. METHOD zif_abapgit_html_table~get_row_attrs. ENDMETHOD. METHOD zif_abapgit_html_table~render_cell. FIELD-SYMBOLS TYPE zcl_abapgit_where_used_tools=>ty_dependency. ASSIGN is_row TO . CASE iv_column_id. WHEN 'dep_obj_name'. rs_render-content = -dep_obj_name. IF mv_show_used_obj = abap_true. rs_render-content = rs_render-content && |{ -dep_used_obj }|. ENDIF. WHEN 'obj_type'. IF -obj_prog_type IS INITIAL. rs_render-content = -obj_type. ELSE. rs_render-content = -obj_type && ':' && -obj_prog_type. ENDIF. WHEN 'obj_name'. rs_render-content = zcl_abapgit_gui_chunk_lib=>get_item_link( iv_obj_type = -obj_type iv_obj_name = -obj_name ). WHEN OTHERS. rs_render-content = iv_value. ENDCASE. " TODO maybe add title for object cls ? ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_SYNTAX IMPLEMENTATION. METHOD constructor. super->constructor( ). mo_repo = io_repo. run_syntax_check( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_syntax. CREATE OBJECT lo_component EXPORTING io_repo = io_repo. ri_page = zcl_abapgit_gui_page_hoc=>create( lo_component ). ENDMETHOD. METHOD run_syntax_check. DATA: li_syntax_check TYPE REF TO zif_abapgit_code_inspector. li_syntax_check = zcl_abapgit_factory=>get_code_inspector( mo_repo->get_package( ) ). TRY. mt_result = li_syntax_check->run( c_variant ). CATCH zcx_abapgit_exception. " Variant SYNTAX_CHECK does not exist in 702 mt_result = li_syntax_check->run( 'VERI_' && c_variant ). ENDTRY. mv_summary = li_syntax_check->get_summary( ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. CASE ii_event->mv_action. WHEN c_actions-rerun. run_syntax_check( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN OTHERS. rs_handled = on_event( ii_event ). ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. ls_hotkey_action-ui_component = 'Syntax Check'. ls_hotkey_action-description = |Re-Run|. ls_hotkey_action-action = c_actions-rerun. ls_hotkey_action-hotkey = |r|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. ro_toolbar = build_base_menu( ). ro_toolbar->add( iv_txt = 'Back' iv_act = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD zif_abapgit_gui_page_title~get_page_title. rv_title = 'Syntax Check'. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->div( iv_class = 'repo' ii_content = zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false ) ). render_ci_report( ii_html = ri_html iv_variant = c_variant iv_success_msg = 'No syntax errors' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page_runit IMPLEMENTATION. METHOD build_tadir. DATA lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. DATA ls_tadir LIKE LINE OF lt_tadir. DATA ls_row LIKE LINE OF rt_tadir. lt_tadir = mo_repo->get_tadir_objects( ). LOOP AT lt_tadir INTO ls_tadir. CLEAR ls_row. ls_row-obj_type = ls_tadir-object. ls_row-obj_name = ls_tadir-obj_name. APPEND ls_row TO rt_tadir. ENDLOOP. ENDMETHOD. METHOD constructor. super->constructor( ). mo_repo = io_repo. TRY. CALL METHOD ('\PROGRAM=SAPLSAUCV_GUI_RUNNER\CLASS=PASSPORT')=>get. CATCH cx_root. zcx_abapgit_exception=>raise( |Not supported in your NW release| ). ENDTRY. ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_runit. TRY. CREATE OBJECT lo_component EXPORTING io_repo = io_repo. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = |Unit Tests| ii_page_menu_provider = lo_component ii_child_component = lo_component ). CATCH zcx_abapgit_exception. " Fallback as either SAPLSAUCV_GUI_RUNNER is not available in old releases " or passport=>get is private in newer releases NW >= 756 ri_page = zcl_abapgit_gui_page_code_insp=>create( io_repo = io_repo iv_check_variant = 'SWF_ABAP_UNIT' ). ENDTRY. ENDMETHOD. METHOD get_text_for_method. DATA lv_params TYPE string. DATA lv_runtime TYPE timestampl. DATA lv_msec TYPE string. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE string_table. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE timestampl. FIELD-SYMBOLS TYPE timestampl. READ TABLE it_indices WITH KEY ('PROGRAM_NDX') = iv_program_ndx ('CLASS_NDX') = iv_class_ndx ('METHOD_NDX') = iv_method_ndx ASSIGNING . IF sy-subrc = 0. ASSIGN COMPONENT 'ALERTS' OF STRUCTURE TO . LOOP AT ASSIGNING . ASSIGN COMPONENT 'HEADER-PARAMS' OF STRUCTURE TO . LOOP AT INTO lv_params. rv_text = lv_params. ENDLOOP. ENDLOOP. ENDIF. CLEAR: lv_msec, lv_runtime. ASSIGN COMPONENT 'INFO-START_ON' OF STRUCTURE is_method TO . IF sy-subrc = 0. ASSIGN COMPONENT 'INFO-END_ON' OF STRUCTURE is_method TO . IF sy-subrc = 0. TRY. lv_runtime = cl_abap_tstmp=>subtract( tstmp1 = tstmp2 = ) * 1000. lv_msec = |{ lv_runtime DECIMALS = 0 } ms|. CATCH cx_parameter_invalid ##NO_HANDLER. "ignore ENDTRY. ENDIF. ENDIF. IF rv_text IS INITIAL. rv_text = |PASSED|. IF lv_runtime > 100. rv_text = rv_text && | { lv_msec }|. ELSE. rv_text = rv_text && | { lv_msec }|. ENDIF. ELSE. rv_text = |{ rv_text }|. ENDIF. ASSIGN COMPONENT 'INFO-NAME' OF STRUCTURE is_method TO . rv_text = |        { }{ rv_text }|. ENDMETHOD. METHOD run. DATA lo_passport TYPE REF TO object. DATA lo_runner TYPE REF TO object. DATA lo_timer TYPE REF TO zcl_abapgit_timer. DATA lt_keys TYPE ty_keys_tt. DATA li_result TYPE REF TO data. FIELD-SYMBOLS TYPE any. lt_keys = build_tadir( ). lo_timer = zcl_abapgit_timer=>create( iv_count = lines( lt_keys ) )->start( ). TRY. CALL METHOD ('\PROGRAM=SAPLSAUCV_GUI_RUNNER\CLASS=PASSPORT')=>get RECEIVING result = lo_passport. CALL METHOD ('CL_AUCV_TEST_RUNNER_STANDARD')=>create EXPORTING i_passport = lo_passport RECEIVING result = lo_runner. CATCH cx_root. zcx_abapgit_exception=>raise( |Not supported in your NW release| ). ENDTRY. CREATE DATA li_result TYPE REF TO ('IF_SAUNIT_INTERNAL_RESULT'). ASSIGN li_result->* TO . CALL METHOD lo_runner->('RUN_FOR_PROGRAM_KEYS') EXPORTING i_limit_on_duration_category = '36' " long i_limit_on_risk_level = '33' " critical i_program_keys = lt_keys IMPORTING e_aunit_result = . mv_summary = lo_timer->end( ). ro_result = . ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. CASE ii_event->mv_action. WHEN c_actions-rerun. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN OTHERS. ASSERT 1 = 1. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar. ro_toolbar->add( iv_txt = 'Re-Run' iv_act = c_actions-rerun iv_cur = abap_false ). ro_toolbar->add( iv_txt = 'Back' iv_act = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA lo_result TYPE REF TO object. DATA lv_program_ndx TYPE i. DATA lv_class_ndx TYPE i. DATA lv_text TYPE string. DATA lv_count TYPE i. DATA lv_params TYPE string. DATA ls_item TYPE zif_abapgit_definitions=>ty_repo_item. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE string_table. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false ) ). lo_result = run( ). ASSIGN lo_result->('F_TASK_DATA') TO . ASSIGN COMPONENT 'ALERTS_BY_INDICIES' OF STRUCTURE TO . ASSIGN COMPONENT 'PROGRAMS' OF STRUCTURE TO . IF IS INITIAL. ri_html->add( '
' ). ri_html->add( 'No unit tests found' ). ri_html->add( '
' ). RETURN. ENDIF. ri_html->add( || ). LOOP AT ASSIGNING . ASSIGN COMPONENT 'ALERTS' OF STRUCTURE TO . LOOP AT ASSIGNING WHERE ('KIND = ''F'' OR KIND = ''S'' OR KIND = ''E'' OR KIND = ''W'''). CLEAR lv_text. ASSIGN COMPONENT 'HEADER-PARAMS' OF STRUCTURE TO . LOOP AT INTO lv_params. lv_text = lv_text && lv_params. ENDLOOP. ASSIGN COMPONENT 'TEXT_INFOS' OF STRUCTURE TO . LOOP AT ASSIGNING . ASSIGN COMPONENT 'PARAMS' OF STRUCTURE TO . LOOP AT INTO lv_params. lv_text = lv_text && lv_params. ENDLOOP. ENDLOOP. IF lv_text NP '*SAUNIT_NO_TEST_CLASS*'. ri_html->add( || ). lv_count = lv_count + 1. ENDIF. ENDLOOP. ENDLOOP. ri_html->add( '
{ lv_text }
' ). ri_html->add( '
' ). ri_html->add( |Unit tests completed with { lv_count } errors ({ mv_summary })| ). ri_html->add( '
' ). ri_html->add( |
| ). LOOP AT ASSIGNING . CLEAR ls_item. lv_program_ndx = sy-tabix. ASSIGN COMPONENT 'INFO-KEY-OBJ_TYPE' OF STRUCTURE TO . IF sy-subrc = 0. ls_item-obj_type = . ASSIGN COMPONENT 'INFO-KEY-OBJ_NAME' OF STRUCTURE TO . ls_item-obj_name = . ri_html->add( || ). ELSE. " KEY field does not exist in 750 ASSIGN COMPONENT 'INFO-NAME' OF STRUCTURE TO . ri_html->add( || ). ENDIF. ASSIGN COMPONENT 'CLASSES' OF STRUCTURE TO . LOOP AT ASSIGNING . lv_class_ndx = sy-tabix. ASSIGN COMPONENT 'INFO-NAME' OF STRUCTURE TO . ri_html->add( || ). ASSIGN COMPONENT 'METHODS' OF STRUCTURE TO . LOOP AT ASSIGNING . ri_html->add( get_text_for_method( is_method = it_indices = iv_program_ndx = lv_program_ndx iv_class_ndx = lv_class_ndx iv_method_ndx = sy-tabix ) ). ENDLOOP. ENDLOOP. ENDLOOP. ri_html->add( '
{ zcl_abapgit_gui_chunk_lib=>get_item_icon( ls_item ) } { ls_item-obj_type }| && | { zcl_abapgit_gui_chunk_lib=>get_item_link( ls_item ) }
{ }
    { }
' ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_CODI_BASE IMPLEMENTATION. METHOD apply_filter_kind. CASE mv_filter_kind. WHEN 'error'. DELETE ct_view WHERE kind <> 'E'. WHEN 'warn'. DELETE ct_view WHERE kind <> 'W'. WHEN 'info'. DELETE ct_view WHERE NOT ( kind = 'E' OR kind = 'W' ). WHEN OTHERS. RETURN. ENDCASE. ENDMETHOD. METHOD apply_sorting. DATA lv_field TYPE abap_compname. CASE ms_sorting_state-column_id. WHEN 'kind' OR 'obj_type' OR 'location' OR 'text'. lv_field = to_upper( ms_sorting_state-column_id ). WHEN OTHERS. RETURN. ENDCASE. IF ms_sorting_state-descending = abap_true. SORT ct_view BY (lv_field) DESCENDING. ELSE. SORT ct_view BY (lv_field) ASCENDING. ENDIF. ENDMETHOD. METHOD build_base_menu. ro_menu = zcl_abapgit_html_toolbar=>create( )->add( iv_txt = 'Re-Run' iv_act = c_actions-rerun ). ENDMETHOD. METHOD build_nav_link. rv_link = |{ c_ci_sig }| && |{ is_result-objtype }{ is_result-objname }| && |{ c_object_separator }{ is_result-sobjtype }{ is_result-sobjname }| && |{ c_object_separator }{ is_result-line }|. ENDMETHOD. METHOD convert_result_to_view. FIELD-SYMBOLS LIKE LINE OF it_result. FIELD-SYMBOLS LIKE LINE OF rt_view. DATA lv_line TYPE i. LOOP AT it_result ASSIGNING . APPEND INITIAL LINE TO rt_view ASSIGNING . -kind = -kind. -obj_type = -objtype. -nav = build_nav_link( ). -text = -text. IF -sobjname IS INITIAL OR ( -sobjname = -objname AND -sobjtype = -objtype ). -location = to_lower( -objname ). ELSEIF -objtype = 'CLAS' OR ( -objtype = 'PROG' AND NOT -sobjname+30(*) IS INITIAL ). -location = explain_include( ). ENDIF. IF -location IS INITIAL. " Fallback to a reasonable default -location = to_lower( |{ -objname } > { -sobjtype } { -sobjname }| ). ENDIF. lv_line = -line. " convert from numc to integer -location = |{ -location } @{ lv_line }|. ENDLOOP. ENDMETHOD. METHOD explain_include. DATA ls_mtdkey TYPE seocpdkey. TRY. CASE is_result-sobjname+30(*). WHEN 'CCDEF'. rv_txt = |{ to_lower( is_result-objname ) }: Local Definitions|. WHEN 'CCIMP'. rv_txt = |{ to_lower( is_result-objname ) }: Local Implementations|. WHEN 'CCMAC'. rv_txt = |{ to_lower( is_result-objname ) }: Macros|. WHEN 'CCAU'. rv_txt = |{ to_lower( is_result-objname ) }: Test Classes|. WHEN 'CU'. rv_txt = |{ to_lower( is_result-objname ) }: Public Section|. WHEN 'CO'. rv_txt = |{ to_lower( is_result-objname ) }: Protected Section|. WHEN 'CI'. rv_txt = |{ to_lower( is_result-objname ) }: Private Section|. WHEN OTHERS. cl_oo_classname_service=>get_method_by_include( EXPORTING incname = is_result-sobjname RECEIVING mtdkey = ls_mtdkey EXCEPTIONS class_not_existing = 1 method_not_existing = 2 OTHERS = 3 ). IF sy-subrc = 0. rv_txt = to_lower( |{ ls_mtdkey-clsname }->{ ls_mtdkey-cpdname }| ). ELSE. rv_txt = to_lower( |{ is_result-sobjname }| ). ENDIF. ENDCASE. CATCH cx_root. " leave empty, fallback to default, defined elsewhere ENDTRY. ENDMETHOD. METHOD handle_navigation. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, ls_sub_item TYPE zif_abapgit_definitions=>ty_item, lv_main_object TYPE string, lv_sub_object TYPE string, lv_line_number_s TYPE string, lv_line_number TYPE i. SPLIT iv_link AT c_object_separator INTO lv_main_object lv_sub_object lv_line_number_s. ls_item-obj_type = to_upper( lv_main_object(4) ). ls_item-obj_name = to_upper( lv_main_object+4(*) ). IF lv_sub_object IS NOT INITIAL. ls_sub_item-obj_type = to_upper( lv_sub_object(4) ). ls_sub_item-obj_name = to_upper( lv_sub_object+4(*) ). ENDIF. lv_line_number = lv_line_number_s. jump( is_item = ls_item is_sub_item = ls_sub_item iv_line_number = lv_line_number ). ENDMETHOD. METHOD jump. DATA: lo_test TYPE REF TO cl_ci_test_root, ls_info TYPE scir_rest, lo_result TYPE REF TO cl_ci_result_root, lv_adt_jump_enabled TYPE abap_bool, lv_line_number TYPE i, ls_item TYPE zif_abapgit_definitions=>ty_item, ls_sub_item TYPE zif_abapgit_definitions=>ty_item. FIELD-SYMBOLS: LIKE LINE OF mt_result. IF is_sub_item IS NOT INITIAL. READ TABLE mt_result WITH KEY objtype = is_item-obj_type objname = is_item-obj_name sobjtype = is_sub_item-obj_type sobjname = is_sub_item-obj_name line = iv_line_number ASSIGNING . ELSE. READ TABLE mt_result WITH KEY objtype = is_item-obj_type objname = is_item-obj_name line = iv_line_number ASSIGNING . ENDIF. ASSERT IS ASSIGNED. ls_item-obj_name = -objname. ls_item-obj_type = -objtype. ls_sub_item-obj_name = -sobjname. ls_sub_item-obj_type = -sobjtype. " see SCI_LCL_DYNP_530 / HANDLE_DOUBLE_CLICK lv_adt_jump_enabled = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_adt_jump_enabled( ). TRY. IF lv_adt_jump_enabled = abap_true. lv_line_number = -line. zcl_abapgit_objects=>jump( is_item = ls_item is_sub_item = ls_sub_item iv_line_number = lv_line_number ). RETURN. ENDIF. CATCH zcx_abapgit_exception. ENDTRY. TRY. CALL METHOD ('CL_CI_TESTS')=>('GET_TEST_REF') EXPORTING p_test = -test RECEIVING p_result = lo_test. CATCH cx_root. zcx_abapgit_exception=>raise( |Jump to object not supported in your NW release| ). ENDTRY. lo_result = lo_test->get_result_node( -kind ). MOVE-CORRESPONDING TO ls_info. lo_result->set_info( ls_info ). lo_result->if_ci_test~navigate( ). ENDMETHOD. METHOD on_event. DATA lv_temp TYPE string. DATA ls_sorting_req TYPE zif_abapgit_html_table=>ty_sorting_state. lv_temp = replace( val = ii_event->mv_action regex = |^{ c_ci_sig }| with = `` ). IF lv_temp <> ii_event->mv_action. " CI navigation request detected handle_navigation( lv_temp ). rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. ls_sorting_req = zcl_abapgit_html_table=>detect_sorting_request( ii_event->mv_action ). IF ls_sorting_req IS NOT INITIAL. ms_sorting_state = ls_sorting_req. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. IF ii_event->mv_action = c_actions-filter_kind. mv_filter_kind = ii_event->query( )->get( 'kind' ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. ENDMETHOD. METHOD render_ci_report. ii_html->add( '
' ). render_head( ii_html = ii_html iv_variant = iv_variant iv_summary = mv_summary ). IF lines( mt_result ) = 0. render_success( ii_html = ii_html iv_message = iv_success_msg ). ELSE. render_stats( ii_html = ii_html it_result = mt_result ). render_detail( ii_html = ii_html it_result = mt_result ). ENDIF. ii_html->add( '
' ). ENDMETHOD. METHOD render_detail. DATA li_table TYPE REF TO zcl_abapgit_html_table. DATA lt_view TYPE ty_view_tab. li_table = zcl_abapgit_html_table=>create( )->define_column( iv_column_id = 'kind' iv_column_title = zcl_abapgit_html=>icon( 'exclamation-circle' ) )->define_column( iv_column_id = 'obj_type' iv_column_title = 'Type' )->define_column( iv_column_id = 'location' iv_column_title = 'Obj. name / location' )->define_column( iv_column_id = 'text' iv_column_title = 'Text' ). lt_view = convert_result_to_view( it_result ). IF ms_sorting_state-column_id IS INITIAL. ms_sorting_state-column_id = 'kind'. ENDIF. apply_sorting( CHANGING ct_view = lt_view ). apply_filter_kind( CHANGING ct_view = lt_view ). ii_html->div( iv_class = 'ci-detail' ii_content = li_table->render( ii_renderer = me is_sorting_state = ms_sorting_state iv_wrap_in_div = 'default-table-container' iv_css_class = 'default-table' iv_with_cids = abap_true it_data = lt_view ) ). IF lines( it_result ) > c_limit. render_limit_warning( ii_html ). ENDIF. ENDMETHOD. METHOD render_head. ii_html->div( iv_class = 'ci-msg' iv_content = |Code inspector check variant { iv_variant } completed ({ iv_summary })| ). ENDMETHOD. METHOD render_limit_warning. ii_html->add( '
' ). ii_html->add( ii_html->icon( 'exclamation-triangle' ) ). ii_html->add( |Only first { c_limit } findings shown in list!| ). ii_html->add( '
' ). ENDMETHOD. METHOD render_stat. DATA lv_txt TYPE string. lv_txt = |{ iv_count } { iv_title }|. IF iv_type <> mv_filter_kind. lv_txt = ii_html->a( iv_txt = lv_txt iv_act = |{ c_actions-filter_kind }?kind={ iv_type }| iv_typ = zif_abapgit_html=>c_action_type-sapevent ). ENDIF. ii_html->add( |{ lv_txt }| ). ENDMETHOD. METHOD render_stats. FIELD-SYMBOLS LIKE LINE OF it_result. DATA lv_errors TYPE i. DATA lv_warnings TYPE i. DATA lv_infos TYPE i. IF mv_filter_kind IS INITIAL. mv_filter_kind = 'all'. ENDIF. LOOP AT it_result ASSIGNING . CASE -kind. WHEN 'E'. lv_errors = lv_errors + 1. WHEN 'W'. lv_warnings = lv_warnings + 1. WHEN OTHERS. lv_infos = lv_infos + 1. ENDCASE. ENDLOOP. ii_html->add( '
' ). IF lv_errors > 0. render_stat( ii_html = ii_html iv_count = lv_errors iv_type = 'error' iv_title = 'errors' ). ENDIF. IF lv_warnings > 0. render_stat( ii_html = ii_html iv_count = lv_warnings iv_type = 'warn' iv_title = 'warnings' ). ENDIF. IF lv_infos > 0. render_stat( ii_html = ii_html iv_count = lv_infos iv_type = 'info' iv_title = 'infos' ). ENDIF. render_stat( ii_html = ii_html iv_count = lv_infos + lv_errors + lv_warnings iv_type = 'all' iv_title = 'all' ). ii_html->add( '
' ). ENDMETHOD. METHOD render_success. ii_html->add( '
' ). ii_html->add( ii_html->icon( 'check' ) ). ii_html->add( iv_message ). ii_html->add( '
' ). ENDMETHOD. METHOD zif_abapgit_html_table~get_row_attrs. FIELD-SYMBOLS TYPE ty_result_view. ASSIGN is_row TO . rs_attrs-data-name = 'kind'. CASE -kind. WHEN 'E'. rs_attrs-data-value = 'error'. WHEN 'W'. rs_attrs-data-value = 'warning'. WHEN OTHERS. rs_attrs-data-value = 'info'. ENDCASE. ENDMETHOD. METHOD zif_abapgit_html_table~render_cell. FIELD-SYMBOLS TYPE ty_result_view. ASSIGN is_row TO . CASE iv_column_id. WHEN 'kind'. rs_render-content = |{ -kind }|. WHEN 'obj_type'. rs_render-content = -obj_type. WHEN 'location'. rs_render-content = zcl_abapgit_html=>create( )->a( iv_txt = -location iv_act = -nav iv_typ = zif_abapgit_html=>c_action_type-sapevent ). WHEN 'text'. rs_render-content = escape( val = -text format = cl_abap_format=>e_html_attr ). ENDCASE. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_CODE_INSP IMPLEMENTATION. METHOD ask_user_for_check_variant. rv_check_variant = zcl_abapgit_ui_factory=>get_popups( )->choose_code_insp_check_variant( ). IF rv_check_variant IS INITIAL. zcx_abapgit_exception=>raise( |Please select a check variant.| ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( ). mo_repo = io_repo. mo_stage = io_stage. mv_check_variant = iv_check_variant. determine_check_variant( ). run_code_inspector( ). IF mt_result IS INITIAL AND iv_raise_when_no_results = abap_true. zcx_abapgit_exception=>raise( 'No results' ). ENDIF. ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_code_insp. CREATE OBJECT lo_component EXPORTING io_repo = io_repo io_stage = io_stage iv_check_variant = iv_check_variant iv_raise_when_no_results = iv_raise_when_no_results. ri_page = zcl_abapgit_gui_page_hoc=>create( lo_component ). ENDMETHOD. METHOD determine_check_variant. IF mv_check_variant IS NOT INITIAL. RETURN. ENDIF. mv_check_variant = mo_repo->get_local_settings( )-code_inspector_check_variant. IF mv_check_variant IS INITIAL. mv_check_variant = ask_user_for_check_variant( ). ENDIF. ENDMETHOD. METHOD has_inspection_errors. READ TABLE mt_result TRANSPORTING NO FIELDS WITH KEY kind = 'E'. rv_has_inspection_errors = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD is_stage_allowed. rv_is_stage_allowed = boolc( NOT ( mo_repo->get_local_settings( )-block_commit = abap_true AND has_inspection_errors( ) = abap_true ) ). ENDMETHOD. METHOD run_code_inspector. DATA li_code_inspector TYPE REF TO zif_abapgit_code_inspector. li_code_inspector = zcl_abapgit_factory=>get_code_inspector( mo_repo->get_package( ) ). mt_result = li_code_inspector->run( iv_variant = |{ mv_check_variant }| iv_save = abap_true ). mv_summary = li_code_inspector->get_summary( ). DELETE mt_result WHERE kind = 'N'. ENDMETHOD. METHOD status. READ TABLE mt_result TRANSPORTING NO FIELDS WITH KEY kind = 'E'. IF sy-subrc = 0. rv_status = zif_abapgit_definitions=>c_sci_result-failed. ELSE. READ TABLE mt_result TRANSPORTING NO FIELDS WITH KEY kind = 'W'. IF sy-subrc = 0. rv_status = zif_abapgit_definitions=>c_sci_result-warning. ELSE. rv_status = zif_abapgit_definitions=>c_sci_result-passed. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA lo_repo_online TYPE REF TO zcl_abapgit_repo_online. CASE ii_event->mv_action. WHEN c_actions-stage. lo_repo_online ?= mo_repo. IF is_stage_allowed( ) = abap_true. rs_handled-page = zcl_abapgit_gui_page_stage=>create( io_repo = lo_repo_online iv_sci_result = status( ) ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. WHEN c_actions-commit. lo_repo_online ?= mo_repo. IF is_stage_allowed( ) = abap_true. rs_handled-page = zcl_abapgit_gui_page_commit=>create( io_repo = lo_repo_online io_stage = mo_stage ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. WHEN c_actions-rerun. run_code_inspector( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN OTHERS. rs_handled = on_event( ii_event ). ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. ls_hotkey_action-ui_component = 'Code Inspector'. ls_hotkey_action-description = |Stage|. ls_hotkey_action-action = c_actions-stage. ls_hotkey_action-hotkey = |s|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ls_hotkey_action-description = |Re-Run|. ls_hotkey_action-action = c_actions-rerun. ls_hotkey_action-hotkey = |r|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. DATA: lv_opt TYPE c LENGTH 1. ro_toolbar = build_base_menu( ). IF is_stage_allowed( ) = abap_false. lv_opt = zif_abapgit_html=>c_html_opt-crossout. ENDIF. IF mo_repo->is_offline( ) = abap_true. RETURN. ENDIF. IF mo_stage IS BOUND. " Staging info already available, we can directly " offer to commit ro_toolbar->add( iv_txt = 'Commit' iv_act = c_actions-commit iv_opt = lv_opt ). ELSE. ro_toolbar->add( iv_txt = 'Stage' iv_act = c_actions-stage iv_opt = lv_opt ). ENDIF. ro_toolbar->add( iv_txt = 'Back' iv_act = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD zif_abapgit_gui_page_title~get_page_title. rv_title = 'Code Inspector'. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->div( iv_class = 'repo' ii_content = zcl_abapgit_gui_chunk_lib=>render_repo_top( io_repo = mo_repo iv_show_commit = abap_false ) ). IF mv_check_variant IS INITIAL. ri_html->add( zcl_abapgit_gui_chunk_lib=>render_error( iv_error = 'No check variant supplied.' ) ). RETURN. ENDIF. render_ci_report( ii_html = ri_html iv_variant = mv_check_variant iv_success_msg = 'No code inspector findings' ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_LOG_VIEWER IMPLEMENTATION. METHOD calculate_cell_type. FIELD-SYMBOLS: LIKE LINE OF gt_log. DATA: ls_cell_type LIKE LINE OF -cell_type. LOOP AT gt_log ASSIGNING . IF -longtext IS NOT INITIAL. ls_cell_type-columnname = `LONGTEXT`. ls_cell_type-value = if_salv_c_cell_type=>hotspot. INSERT ls_cell_type INTO TABLE -cell_type. ENDIF. IF -t100 IS NOT INITIAL. ls_cell_type-columnname = `T100`. ls_cell_type-value = if_salv_c_cell_type=>hotspot. INSERT ls_cell_type INTO TABLE -cell_type. ENDIF. IF -source IS NOT INITIAL. ls_cell_type-columnname = `SOURCE`. ls_cell_type-value = if_salv_c_cell_type=>hotspot. INSERT ls_cell_type INTO TABLE -cell_type. ENDIF. IF -callstack IS NOT INITIAL. ls_cell_type-columnname = `CALLSTACK`. ls_cell_type-value = if_salv_c_cell_type=>hotspot. INSERT ls_cell_type INTO TABLE -cell_type. ENDIF. ENDLOOP. ENDMETHOD. METHOD dispatch. CASE iv_column. WHEN `LONGTEXT`. show_longtext( is_log ). WHEN `T100`. goto_t100_message( is_log ). WHEN `SOURCE`. goto_source( is_log ). WHEN `CALLSTACK`. goto_callstack( is_log ). ENDCASE. ENDMETHOD. METHOD get_exception_viewer. DATA: lx_abapgit TYPE REF TO zcx_abapgit_exception. ASSERT is_log-exception IS BOUND. lx_abapgit ?= is_log-exception. CREATE OBJECT ro_exception_viewer EXPORTING ix_error = lx_abapgit. ENDMETHOD. METHOD goto_callstack. get_exception_viewer( is_log )->show_callstack( ). ENDMETHOD. METHOD goto_source. get_exception_viewer( is_log )->goto_source( ). ENDMETHOD. METHOD goto_t100_message. get_exception_viewer( is_log )->goto_message( ). ENDMETHOD. METHOD on_link_click. DATA: lx_error TYPE REF TO zcx_abapgit_exception. FIELD-SYMBOLS: TYPE ty_log_out. IF row IS INITIAL OR column IS INITIAL. RETURN. ENDIF. READ TABLE gt_log ASSIGNING INDEX row. ASSERT sy-subrc = 0. TRY. dispatch( is_log = iv_column = column ). CATCH zcx_abapgit_exception INTO lx_error. MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. ENDMETHOD. METHOD prepare_log_for_display. DATA: lt_message TYPE zif_abapgit_log=>ty_log_outs, lr_message TYPE REF TO zif_abapgit_log=>ty_log_out, ls_log TYPE ty_log_out, li_t100_message TYPE REF TO if_t100_message, lx_abapgit TYPE REF TO zcx_abapgit_exception. lt_message = ii_log->get_messages( ). LOOP AT lt_message REFERENCE INTO lr_message. CLEAR: ls_log. ls_log-msg = lr_message->text. ls_log-exception = lr_message->exception. CASE lr_message->type. WHEN 'E' OR 'A' OR 'X'. ls_log-type = icon_led_red. WHEN 'W'. ls_log-type = icon_led_yellow. WHEN 'I' OR 'S'. ls_log-type = icon_led_green. WHEN OTHERS. ls_log-type = icon_led_inactive. ENDCASE. IF lr_message->exception IS BOUND. TRY. li_t100_message ?= lr_message->exception. IF li_t100_message->t100key IS NOT INITIAL. ls_log-t100 = icon_message_information. ENDIF. CATCH cx_sy_move_cast_error ##NO_HANDLER. ENDTRY. TRY. lx_abapgit ?= lr_message->exception. IF lx_abapgit->mt_callstack IS NOT INITIAL. ls_log-longtext = icon_system_help. ls_log-callstack = icon_stack. ls_log-source = icon_abap. ENDIF. CATCH cx_sy_move_cast_error ##NO_HANDLER. ENDTRY. ENDIF. ls_log-obj_type = lr_message->obj_type. ls_log-obj_name = lr_message->obj_name. INSERT ls_log INTO TABLE rt_log_out. ENDLOOP. ENDMETHOD. METHOD show_log. DATA: lr_log TYPE REF TO ty_log_out, lo_alv TYPE REF TO cl_salv_table, lx_error TYPE REF TO cx_salv_error, lo_form_header TYPE REF TO cl_salv_form_header_info, lo_columns TYPE REF TO cl_salv_columns_table, lo_column TYPE REF TO cl_salv_column, lo_functions TYPE REF TO cl_salv_functions_list, ls_position TYPE zif_abapgit_popups=>ty_popup_position, lv_add_obj_col TYPE abap_bool, lo_event TYPE REF TO cl_salv_events_table. gt_log = prepare_log_for_display( ii_log ). "check if log contains any object info LOOP AT gt_log REFERENCE INTO lr_log. IF lr_log->obj_type IS NOT INITIAL OR lr_log->obj_name IS NOT INITIAL. lv_add_obj_col = abap_true. ENDIF. ENDLOOP. TRY. cl_salv_table=>factory( IMPORTING r_salv_table = lo_alv CHANGING t_table = gt_log ). lo_functions = lo_alv->get_functions( ). lo_functions->set_all( ). lo_alv->get_display_settings( )->set_list_header( |abapGit Log Viewer| ). lo_columns = lo_alv->get_columns( ). lo_columns->set_optimize( ). lo_columns->set_cell_type_column( |CELL_TYPE| ). calculate_cell_type( ). lo_column = lo_columns->get_column( |TYPE| ). lo_column->set_medium_text( |Type| ). lo_column = lo_columns->get_column( |MSG| ). lo_column->set_medium_text( |Message| ). lo_column = lo_columns->get_column( |LONGTEXT| ). lo_column->set_medium_text( |Longtext| ). lo_column = lo_columns->get_column( |T100| ). lo_column->set_medium_text( |Goto message| ). lo_column = lo_columns->get_column( |SOURCE| ). lo_column->set_medium_text( |Goto source| ). lo_column = lo_columns->get_column( |CALLSTACK| ). lo_column->set_medium_text( |Show callstack| ). IF lv_add_obj_col = abap_true. lo_column = lo_columns->get_column( |OBJ_TYPE| ). lo_column->set_medium_text( |Object Type| ). lo_column = lo_columns->get_column( |OBJ_NAME| ). lo_column->set_medium_text( |Object Name| ). ELSE. "hide object columns lo_column = lo_columns->get_column( |OBJ_TYPE| ). lo_column->set_technical( abap_true ). lo_column = lo_columns->get_column( |OBJ_NAME| ). lo_column->set_technical( abap_true ). ENDIF. "hide empty columns LOOP AT gt_log TRANSPORTING NO FIELDS WHERE t100 IS NOT INITIAL. EXIT. ENDLOOP. IF sy-subrc <> 0. lo_column = lo_columns->get_column( |T100| ). lo_column->set_technical( abap_true ). ENDIF. LOOP AT gt_log TRANSPORTING NO FIELDS WHERE source IS NOT INITIAL. EXIT. ENDLOOP. IF sy-subrc <> 0. lo_column = lo_columns->get_column( |SOURCE| ). lo_column->set_technical( abap_true ). ENDIF. LOOP AT gt_log TRANSPORTING NO FIELDS WHERE longtext IS NOT INITIAL. EXIT. ENDLOOP. IF sy-subrc <> 0. lo_column = lo_columns->get_column( |LONGTEXT| ). lo_column->set_technical( abap_true ). ENDIF. LOOP AT gt_log TRANSPORTING NO FIELDS WHERE callstack IS NOT INITIAL. EXIT. ENDLOOP. IF sy-subrc <> 0. lo_column = lo_columns->get_column( |CALLSTACK| ). lo_column->set_technical( abap_true ). ENDIF. ls_position = zcl_abapgit_popups=>center( iv_width = 125 iv_height = 20 ). lo_alv->set_screen_popup( start_column = ls_position-start_column end_column = ls_position-end_column start_line = ls_position-start_row end_line = ls_position-end_row ). CREATE OBJECT lo_form_header EXPORTING text = ii_log->get_title( ). lo_alv->set_top_of_list( lo_form_header ). lo_event = lo_alv->get_event( ). SET HANDLER on_link_click FOR lo_event. lo_alv->display( ). CATCH cx_salv_error INTO lx_error. MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. ENDMETHOD. METHOD show_longtext. DATA: lx_abapgit TYPE REF TO zcx_abapgit_exception. DATA: lv_docu_object TYPE dokhl-object, lt_dummy1 TYPE TABLE OF dselc, lt_dummy2 TYPE TABLE OF dval, ls_help_info TYPE help_info. IF is_log-exception IS NOT BOUND. RETURN. ENDIF. TRY. lx_abapgit ?= is_log-exception. CATCH cx_sy_move_cast_error. RETURN. ENDTRY. lv_docu_object = lx_abapgit->if_t100_message~t100key-msgid. lv_docu_object+2 = lx_abapgit->if_t100_message~t100key-msgno. ls_help_info-call = 'D'. ls_help_info-spras = sy-langu. ls_help_info-messageid = lx_abapgit->if_t100_message~t100key-msgid. ls_help_info-messagenr = lx_abapgit->if_t100_message~t100key-msgno. ls_help_info-message = is_log-msg. ls_help_info-title = 'Longtext'. ls_help_info-docuid = 'NA'. ls_help_info-docuobject = lv_docu_object. ls_help_info-msgv1 = lx_abapgit->msgv1. ls_help_info-msgv2 = lx_abapgit->msgv2. ls_help_info-msgv3 = lx_abapgit->msgv3. ls_help_info-msgv4 = lx_abapgit->msgv4. CALL FUNCTION 'HELP_START' EXPORTING help_infos = ls_help_info TABLES dynpselect = lt_dummy1 dynpvaluetab = lt_dummy2 EXCEPTIONS OTHERS = 1. IF sy-subrc IS NOT INITIAL. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD to_html. DATA: lt_message TYPE zif_abapgit_log=>ty_log_outs, lr_message TYPE REF TO zif_abapgit_log=>ty_log_out, lv_class TYPE string, lv_icon TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF ii_log->count( ) = 0. RETURN. ENDIF. lt_message = ii_log->get_messages( ). LOOP AT lt_message REFERENCE INTO lr_message. CASE lr_message->type. WHEN 'W'. lv_icon = 'attention'. lv_class = 'warning'. WHEN 'E'. lv_icon = 'error'. lv_class = 'error'. WHEN OTHERS. " ??? unexpected lv_icon = 'error'. lv_class = 'error'. ENDCASE. ri_html->add( || ). ri_html->add_icon( lv_icon ). ri_html->add( lr_message->text ). ri_html->add( '' ). ENDLOOP. ENDMETHOD. METHOD write_log. DATA: lt_message TYPE zif_abapgit_log=>ty_log_outs, lr_message TYPE REF TO zif_abapgit_log=>ty_log_out, lv_text TYPE string. lt_message = ii_log->get_messages( ). LOOP AT lt_message REFERENCE INTO lr_message. IF lr_message->obj_name IS NOT INITIAL AND lr_message->obj_type IS NOT INITIAL. lv_text = |{ lr_message->type }: { lr_message->text } ({ lr_message->obj_type }/{ lr_message->obj_name })|. ELSE. lv_text = |{ lr_message->type }: { lr_message->text }|. ENDIF. WRITE: / lv_text. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_HTML_TOOLBAR IMPLEMENTATION. METHOD add. DATA ls_item TYPE ty_item. ASSERT iv_typ = zif_abapgit_html=>c_action_type-separator " sep doesn't have action OR iv_typ = zif_abapgit_html=>c_action_type-onclick " click may have no action (assigned in JS) OR iv_typ = zif_abapgit_html=>c_action_type-dummy " dummy may have no action OR iv_act IS INITIAL AND io_sub IS NOT INITIAL OR iv_act IS NOT INITIAL AND io_sub IS INITIAL. " Only one supplied ASSERT NOT ( iv_chk <> abap_undefined AND io_sub IS NOT INITIAL ). ASSERT iv_hotkey IS INITIAL OR strlen( iv_hotkey ) = 1. ls_item-txt = iv_txt. ls_item-act = iv_act. ls_item-ico = iv_ico. ls_item-sub = io_sub. ls_item-opt = iv_opt. ls_item-typ = iv_typ. ls_item-cur = iv_cur. ls_item-chk = iv_chk. ls_item-aux = iv_aux. ls_item-id = iv_id. ls_item-title = iv_title. ls_item-class = iv_class. ls_item-li_class = iv_li_class. ls_item-hotkey = to_lower( iv_hotkey ). APPEND ls_item TO mt_items. ro_self = me. ENDMETHOD. METHOD constructor. mv_id = iv_id. ENDMETHOD. METHOD count_items. rv_count = lines( mt_items ). ENDMETHOD. METHOD create. CREATE OBJECT ro_instance EXPORTING iv_id = iv_id. ENDMETHOD. METHOD get_hotkeys. DATA ls_hotkey_action LIKE LINE OF rt_hotkeys. FIELD-SYMBOLS LIKE LINE OF mt_items. ls_hotkey_action-ui_component = iv_component_name. LOOP AT mt_items ASSIGNING WHERE hotkey IS NOT INITIAL. ls_hotkey_action-description = -txt. ls_hotkey_action-action = -act. ls_hotkey_action-hotkey = -hotkey. INSERT ls_hotkey_action INTO TABLE rt_hotkeys. ENDLOOP. ENDMETHOD. METHOD render. DATA: lv_class TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. lv_class = 'nav-container'. IF iv_right = abap_true. lv_class = lv_class && ' float-right'. ENDIF. ri_html->add( |
| ). ri_html->add( render_items( iv_sort = iv_sort ) ). ri_html->add( '
' ). ENDMETHOD. METHOD render_as_droplist. DATA: lv_class TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. lv_class = 'nav-container'. IF iv_right = abap_true. lv_class = lv_class && ' float-right'. ENDIF. IF iv_corner = abap_true. lv_class = lv_class && ' corner'. ENDIF. ri_html->add( |
| ). ri_html->add( '
  • ' ). ri_html->add_a( iv_txt = iv_label iv_typ = zif_abapgit_html=>c_action_type-sapevent iv_act = iv_action ). ri_html->add( '
    ' ). ri_html->add( render_items( iv_sort = iv_sort ) ). ri_html->add( '
' ). ri_html->add( '
' ). ENDMETHOD. METHOD render_items. DATA: lv_class TYPE string, lv_class_value TYPE string, lv_icon TYPE string, lv_id TYPE string, lv_check TYPE string, lv_aux TYPE string, lv_txt TYPE string, lv_hkidx TYPE i, lv_has_icons TYPE abap_bool. FIELD-SYMBOLS LIKE LINE OF mt_items. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF iv_sort = abap_true. SORT mt_items BY txt ASCENDING AS TEXT. ENDIF. " Check has icons or check boxes LOOP AT mt_items ASSIGNING WHERE ico IS NOT INITIAL OR chk <> abap_undefined. lv_has_icons = abap_true. lv_class = ' class="with-icons"'. EXIT. ENDLOOP. IF mv_id IS NOT INITIAL. lv_id = | id="{ mv_id }"|. ENDIF. ri_html->add( || ). " Render items LOOP AT mt_items ASSIGNING . CLEAR: lv_class, lv_class_value, lv_icon. lv_txt = -txt. IF -hotkey IS NOT INITIAL. ASSERT strlen( -hotkey ) = 1. lv_hkidx = find( val = lv_txt sub = to_upper( -hotkey ) ). IF lv_hkidx < 0. lv_hkidx = find( val = lv_txt sub = -hotkey ). ENDIF. IF lv_hkidx >= 0. lv_txt = replace( val = lv_txt off = lv_hkidx len = 1 with = |{ lv_txt+lv_hkidx(1) }| ). ENDIF. ENDIF. IF -typ = zif_abapgit_html=>c_action_type-separator. ri_html->add( |
  • { lv_txt }
  • | ). CONTINUE. ENDIF. IF lv_has_icons = abap_true. IF -chk = abap_true. lv_icon = ri_html->icon( 'check/blue' ). lv_check = ' data-check="X"'. ELSEIF -chk = abap_false. lv_icon = ri_html->icon( 'check/grey' ). lv_check = ' data-check=""'. ELSE. " abap_undefined -> not a check box lv_icon = ri_html->icon( -ico ). ENDIF. ENDIF. IF -cur = abap_true. IF -li_class IS INITIAL. lv_class_value = 'current-menu-item'. ELSE. lv_class_value = |current-menu-item { -li_class }|. ENDIF. ELSE. lv_class_value = -li_class. ENDIF. IF lv_class_value IS NOT INITIAL. lv_class = | class="{ lv_class_value }"|. ENDIF. IF -aux IS NOT INITIAL. lv_aux = | data-aux="{ -aux }"|. ENDIF. ri_html->add( || ). IF -sub IS INITIAL. ri_html->add_a( iv_txt = lv_icon && lv_txt iv_typ = -typ iv_act = -act iv_id = -id iv_opt = -opt iv_title = -title iv_class = -class ). ELSE. ri_html->add_a( iv_txt = lv_icon && lv_txt iv_typ = zif_abapgit_html=>c_action_type-dummy iv_act = '' iv_id = -id iv_opt = -opt iv_title = -title iv_class = -class ). ri_html->add( -sub->render_items( iv_sort ) ). ENDIF. ri_html->add( '' ). ENDLOOP. ri_html->add( '' ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. METHOD apply_sorting. DATA lv_field TYPE abap_compname. DATA ls_col LIKE LINE OF mt_columns. IF ms_sorting_state-column_id IS INITIAL. RETURN. ENDIF. READ TABLE mt_columns INTO ls_col WITH KEY column_id = ms_sorting_state-column_id. IF sy-subrc <> 0. RETURN. " ??? but let's not throw errors here ENDIF. IF ls_col-from_field IS NOT INITIAL. lv_field = to_upper( ls_col-from_field ). ELSE. lv_field = to_upper( ms_sorting_state-column_id ). ENDIF. " What to do if column_id is not a table field ? " Well ... then it is a complex case for an external sorting, don't use the simple one IF ms_sorting_state-descending = abap_true. SORT ct_data BY (lv_field) DESCENDING. ELSE. SORT ct_data BY (lv_field) ASCENDING. ENDIF. ENDMETHOD. METHOD cid_attr. rs_data_attr-name = 'cid'. rs_data_attr-value = iv_column_id. ENDMETHOD. METHOD create. CREATE OBJECT ro_instance. ro_instance->mi_renderer = ii_renderer. ro_instance->ms_sorting_state = is_initial_sorting_state. ENDMETHOD. METHOD define_column. FIELD-SYMBOLS LIKE LINE OF mt_columns. ASSERT iv_column_id IS NOT INITIAL. ro_self = me. APPEND INITIAL LINE TO mt_columns ASSIGNING . -column_id = iv_column_id. -column_title = iv_column_title. -from_field = to_upper( iv_from_field ). -sortable = iv_sortable. IF mr_last_grp IS NOT INITIAL. mr_last_grp->group_span = mr_last_grp->group_span + 1. ENDIF. ENDMETHOD. METHOD define_column_group. IF lines( mt_columns ) > 0 AND mr_last_grp IS INITIAL. " Groups should cover all columns " you can create a group with empty title if groups start later VISUALLY zcx_abapgit_exception=>raise( 'Start groups from the beginning' ). ENDIF. ro_self = me. APPEND INITIAL LINE TO mt_columns REFERENCE INTO mr_last_grp. mr_last_grp->is_group = abap_true. mr_last_grp->column_id = iv_group_id. mr_last_grp->column_title = iv_group_title. ENDMETHOD. METHOD detect_sorting_request. DATA lv_req TYPE string. IF find( val = iv_event regex = c_sort_by_event_regex ) = 0. lv_req = replace( val = iv_event sub = c_sort_by_event_prefix with = '' ). SPLIT lv_req AT ':' INTO rs_sorting_request-column_id lv_req. rs_sorting_request-descending = boolc( lv_req = 'dsc' ). ENDIF. ENDMETHOD. METHOD gid_attr. rs_data_attr-name = 'gid'. rs_data_attr-value = iv_column_id. ENDMETHOD. METHOD process_sorting_request. DATA ls_sorting_req LIKE ms_sorting_state. ls_sorting_req = detect_sorting_request( iv_event ). IF ls_sorting_req IS NOT INITIAL. ms_sorting_state = ls_sorting_req. rv_processed = abap_true. ENDIF. ENDMETHOD. METHOD render. DATA lv_attrs TYPE string. DATA lr_data_copy TYPE REF TO data. FIELD-SYMBOLS TYPE ANY TABLE. IF ii_renderer IS BOUND. mi_renderer = ii_renderer. ENDIF. ASSERT mi_renderer IS BOUND. mv_with_cids = iv_with_cids. mv_table_id = iv_id. ASSIGN it_data TO . IF is_sorting_state IS NOT INITIAL. ms_sorting_state = is_sorting_state. ELSEIF ms_sorting_state IS NOT INITIAL. " If sorting state is not passed, " but there is non empty sort state then suppose simple sorting mode " so that table sorts the data itself before rendering " TODO not efficient, maybe bind changing data from outside CREATE DATA lr_data_copy LIKE it_data. ASSIGN lr_data_copy->* TO . = it_data. apply_sorting( CHANGING ct_data = ). ENDIF. IF iv_id IS NOT INITIAL. lv_attrs = lv_attrs && | id="{ iv_id }"|. ENDIF. IF iv_css_class IS NOT INITIAL. lv_attrs = lv_attrs && | class="{ iv_css_class }"|. ENDIF. CREATE OBJECT mi_html TYPE zcl_abapgit_html. ri_html = mi_html. IF iv_wrap_in_div IS NOT INITIAL. mi_html->add( |
    | ). ENDIF. mi_html->add( || ). render_thead( ). render_tbody( ). mi_html->add( '' ). IF iv_wrap_in_div IS NOT INITIAL. mi_html->add( '
    ' ). ENDIF. ENDMETHOD. METHOD render_column_title. DATA lv_direction TYPE string. DATA lv_arrow TYPE string. DATA lv_sort_active TYPE string. IF is_col-sortable = abap_true AND ms_sorting_state IS NOT INITIAL. IF is_col-column_id = ms_sorting_state-column_id AND ms_sorting_state-descending = abap_false. lv_direction = 'dsc'. ELSE. lv_direction = 'asc'. ENDIF. IF is_col-column_id = ms_sorting_state-column_id AND ms_sorting_state-descending = abap_true. lv_arrow = '▴'. " arrow up ELSE. lv_arrow = '▾'. " arrow down ENDIF. IF is_col-column_id = ms_sorting_state-column_id. lv_sort_active = | { mv_sort_active_class }|. ENDIF. rv_text = mi_html->a( iv_txt = is_col-column_title iv_act = |{ c_sort_by_event_prefix }{ is_col-column_id }:{ lv_direction }| ). rv_text = rv_text && |{ lv_arrow }|. ELSE. rv_text = is_col-column_title. ENDIF. ENDMETHOD. METHOD render_row. DATA ls_render TYPE zif_abapgit_html_table=>ty_cell_render. DATA lv_dummy TYPE string. DATA lt_attrs TYPE zif_abapgit_html=>ty_data_attrs. FIELD-SYMBOLS LIKE LINE OF mt_columns. FIELD-SYMBOLS LIKE LINE OF mt_columns. FIELD-SYMBOLS TYPE any. LOOP AT mt_columns ASSIGNING . IF -is_group = abap_true. ASSIGN TO . CONTINUE. ENDIF. IF -from_field IS NOT INITIAL AND -from_field <> '-'. ASSIGN COMPONENT -from_field OF STRUCTURE is_row TO . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |html_table: cannot assign field [{ -from_field }]| ). ENDIF. ELSEIF -from_field <> '-'. -from_field = to_upper( -column_id ). " Try column_id ASSIGN COMPONENT -from_field OF STRUCTURE is_row TO . IF sy-subrc <> 0. -from_field = '-'. " Don't try assignments anymore ASSIGN lv_dummy TO . ENDIF. ELSE. ASSIGN lv_dummy TO . ENDIF. ls_render = mi_renderer->render_cell( iv_table_id = mv_table_id iv_row_index = iv_row_index is_row = is_row iv_column_id = -column_id iv_value = |{ }| ). IF mv_with_cids = abap_true. CLEAR lt_attrs. APPEND cid_attr( -column_id ) TO lt_attrs. IF IS ASSIGNED AND -column_id IS NOT INITIAL. APPEND gid_attr( -column_id ) TO lt_attrs. ENDIF. ENDIF. mi_html->td( iv_content = ls_render-content ii_content = ls_render-html it_data_attrs = lt_attrs iv_class = ls_render-css_class ). ENDLOOP. ENDMETHOD. METHOD render_tbody. DATA ls_row_attrs TYPE zif_abapgit_html_table=>ty_row_attrs. DATA lv_row_attrs TYPE string. DATA lv_index TYPE i. FIELD-SYMBOLS TYPE any. mi_html->add( '' ). LOOP AT it_data ASSIGNING . lv_index = sy-tabix. ls_row_attrs = mi_renderer->get_row_attrs( iv_table_id = mv_table_id iv_row_index = lv_index is_row = ). CLEAR lv_row_attrs. IF ls_row_attrs-css_class IS NOT INITIAL. lv_row_attrs = lv_row_attrs && | class="{ ls_row_attrs-css_class }"|. ENDIF. IF ls_row_attrs-data IS NOT INITIAL. lv_row_attrs = lv_row_attrs && | data-{ ls_row_attrs-data-name }="{ ls_row_attrs-data-value }"|. ENDIF. mi_html->add( || ). render_row( iv_row_index = lv_index is_row = ). mi_html->add( '' ). ENDLOOP. mi_html->add( '' ). ENDMETHOD. METHOD render_thead. FIELD-SYMBOLS LIKE LINE OF mt_columns. FIELD-SYMBOLS LIKE LINE OF mt_columns. DATA lt_attrs TYPE zif_abapgit_html=>ty_data_attrs. DATA ls_grp_span TYPE string. DATA lv_grp_data TYPE string. mi_html->add( '' ). " Group headers IF mr_last_grp IS NOT INITIAL. " Has groups mi_html->add( '' ). LOOP AT mt_columns ASSIGNING WHERE is_group = abap_true. IF mv_with_cids = abap_true AND -column_id IS NOT INITIAL. lv_grp_data = | data-gid="{ -column_id }"|. ELSE. CLEAR lv_grp_data. ENDIF. IF -group_span > 1. ls_grp_span = | colspan="{ -group_span }"|. ELSE. CLEAR ls_grp_span. ENDIF. mi_html->add( |{ -column_title }| ). ENDLOOP. mi_html->add( '' ). ENDIF. " Regular headers mi_html->add( '' ). LOOP AT mt_columns ASSIGNING . IF -is_group = abap_true. ASSIGN TO . CONTINUE. ENDIF. IF mv_with_cids = abap_true. CLEAR lt_attrs. APPEND cid_attr( -column_id ) TO lt_attrs. IF IS ASSIGNED AND -column_id IS NOT INITIAL. APPEND gid_attr( -column_id ) TO lt_attrs. ENDIF. ENDIF. mi_html->th( iv_content = render_column_title( ) it_data_attrs = lt_attrs ). ENDLOOP. mi_html->add( '' ). mi_html->add( '' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_html_form_utils IMPLEMENTATION. METHOD constructor. mo_form = io_form. ENDMETHOD. METHOD create. CREATE OBJECT ro_form_util EXPORTING io_form = io_form. ENDMETHOD. METHOD exit. DATA lv_answer TYPE c LENGTH 1. IF is_dirty( io_form_data = io_form_data io_compare_with = io_compare_with ) = abap_true. lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_display_cancel_button = abap_false iv_titlebar = 'abapGit - Unsaved Changes' iv_text_question = 'There are unsaved changes. Do you want to exit the form?' iv_default_button = '2' ). IF lv_answer = '1'. rv_state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark. ELSE. rv_state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDIF. ELSE. rv_state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark. ENDIF. ENDMETHOD. METHOD is_dirty. rv_dirty = boolc( io_form_data->mt_entries <> io_compare_with->mt_entries ). ENDMETHOD. METHOD is_empty. DATA: lt_fields TYPE zif_abapgit_html_form=>ty_fields, lv_value TYPE string, lv_rows TYPE i, lv_row TYPE i. FIELD-SYMBOLS LIKE LINE OF lt_fields. rv_empty = abap_true. lt_fields = mo_form->get_fields( ). LOOP AT lt_fields ASSIGNING WHERE type <> zif_abapgit_html_form=>c_field_type-field_group. lv_value = condense( val = io_form_data->get( -name ) del = ` ` ). IF -type = zif_abapgit_html_form=>c_field_type-number. rv_empty = boolc( lv_value IS INITIAL OR lv_value = '0' ). ELSEIF -type = zif_abapgit_html_form=>c_field_type-table. lv_rows = io_form_data->get( |{ -name }-{ zif_abapgit_html_form=>c_rows }| ). DO lv_rows TIMES. lv_row = sy-index. DO lines( -subitems ) TIMES. lv_value = io_form_data->get( |{ -name }-{ lv_row }-{ sy-index }| ). rv_empty = boolc( lv_value IS INITIAL ). IF rv_empty <> abap_true. RETURN. ENDIF. ENDDO. ENDDO. ELSEIF -type = zif_abapgit_html_form=>c_field_type-textarea. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_value WITH ''. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN lv_value WITH ''. rv_empty = boolc( lv_value IS INITIAL ). ELSE. rv_empty = boolc( lv_value IS INITIAL ). ENDIF. IF rv_empty <> abap_true. RETURN. ENDIF. ENDLOOP. ENDMETHOD. METHOD normalize. DATA: lt_fields TYPE zif_abapgit_html_form=>ty_fields, lv_value TYPE string, lv_rows TYPE i, lv_row TYPE i, lv_len TYPE i. FIELD-SYMBOLS LIKE LINE OF lt_fields. CREATE OBJECT ro_form_data. IF io_form_data->is_empty( ) = abap_true. RETURN. ENDIF. lt_fields = mo_form->get_fields( ). LOOP AT lt_fields ASSIGNING WHERE type <> zif_abapgit_html_form=>c_field_type-field_group AND type <> zif_abapgit_html_form=>c_field_type-hidden. CLEAR lv_value. lv_value = io_form_data->get( -name ). IF -condense = abap_true. lv_value = condense( val = lv_value del = ` ` ). ENDIF. IF -type = zif_abapgit_html_form=>c_field_type-checkbox. ro_form_data->set( iv_key = -name iv_val = boolc( lv_value = 'on' ) ) ##TYPE. ELSEIF ( -type = zif_abapgit_html_form=>c_field_type-text OR -type = zif_abapgit_html_form=>c_field_type-textarea ) AND -upper_case = abap_true. ro_form_data->set( iv_key = -name iv_val = to_upper( lv_value ) ). ELSEIF -type = zif_abapgit_html_form=>c_field_type-number. " Numeric value is checked in validation ro_form_data->set( iv_key = -name iv_val = condense( val = lv_value del = ` ` ) ). ELSEIF -type = zif_abapgit_html_form=>c_field_type-table. lv_rows = io_form_data->get( |{ -name }-{ zif_abapgit_html_form=>c_rows }| ). DO lv_rows TIMES. lv_row = sy-index. DO lines( -subitems ) TIMES. lv_value = io_form_data->get( |{ -name }-{ lv_row }-{ sy-index }| ). ro_form_data->set( iv_key = |{ -name }-{ lv_row }-{ sy-index }| iv_val = lv_value ). ENDDO. ENDDO. ro_form_data->set( iv_key = |{ -name }-{ zif_abapgit_html_form=>c_rows }| iv_val = |{ lv_rows }| ). ELSEIF -type = zif_abapgit_html_form=>c_field_type-textarea. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_value WITH cl_abap_char_utilities=>newline. " Remove last line if empty (ie 2x newline) lv_len = strlen( lv_value ) - 2. IF lv_len >= 0 AND lv_value+lv_len(1) = cl_abap_char_utilities=>newline. lv_len = lv_len + 1. lv_value = lv_value(lv_len). ENDIF. ro_form_data->set( iv_key = -name iv_val = lv_value ). ELSE. ro_form_data->set( iv_key = -name iv_val = lv_value ). ENDIF. ENDLOOP. ENDMETHOD. METHOD set_data. mo_form_data = io_form_data. ENDMETHOD. METHOD validate. DATA: lt_fields TYPE zif_abapgit_html_form=>ty_fields, lv_value TYPE string, lv_number TYPE p LENGTH 16 DECIMALS 0. FIELD-SYMBOLS LIKE LINE OF lt_fields. CREATE OBJECT ro_validation_log. lt_fields = mo_form->get_fields( ). LOOP AT lt_fields ASSIGNING . lv_value = io_form_data->get( -name ). IF -condense = abap_true. lv_value = condense( val = lv_value del = ` ` ). ENDIF. IF -required IS NOT INITIAL AND lv_value IS INITIAL. ro_validation_log->set( iv_key = -name iv_val = |{ -label } cannot be empty| ). ENDIF. CASE -type. WHEN zif_abapgit_html_form=>c_field_type-text. IF -min = -max AND strlen( lv_value ) <> -min. ro_validation_log->set( iv_key = -name iv_val = |{ -label } must be exactly { -min } characters long| ). ELSE. IF -min <> cl_abap_math=>min_int4 AND strlen( lv_value ) < -min. ro_validation_log->set( iv_key = -name iv_val = |{ -label } must not be shorter than { -min } characters| ). ENDIF. IF -max <> cl_abap_math=>max_int4 AND strlen( lv_value ) > -max. ro_validation_log->set( iv_key = -name iv_val = |{ -label } must not be longer than { -max } characters| ). ENDIF. ENDIF. WHEN zif_abapgit_html_form=>c_field_type-number. TRY. lv_number = lv_value. CATCH cx_root. ro_validation_log->set( iv_key = -name iv_val = |{ -label } is not numeric| ). CONTINUE. ENDTRY. IF -min <> cl_abap_math=>min_int4 AND lv_number < -min. ro_validation_log->set( iv_key = -name iv_val = |{ -label } must not be lower than { -min }| ). ENDIF. IF -max <> cl_abap_math=>max_int4 AND lv_number > -max. ro_validation_log->set( iv_key = -name iv_val = |{ -label } must not be higher than { -max }| ). ENDIF. ENDCASE. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_html_form IMPLEMENTATION. METHOD checkbox. DATA ls_field LIKE LINE OF mt_fields. ls_field-type = zif_abapgit_html_form=>c_field_type-checkbox. ls_field-name = iv_name. ls_field-label = iv_label. ls_field-hint = iv_hint. ls_field-readonly = iv_readonly. APPEND ls_field TO mt_fields. ro_self = me. ENDMETHOD. METHOD column. FIELD-SYMBOLS LIKE LINE OF mt_fields. DATA ls_column LIKE LINE OF -subitems. DATA lv_size TYPE i. lv_size = lines( mt_fields ). ASSERT lv_size > 0. " Exception ? Maybe add zcx_no_check ? READ TABLE mt_fields INDEX lv_size ASSIGNING . ASSERT sy-subrc = 0. ASSERT -type = zif_abapgit_html_form=>c_field_type-table. ls_column-label = iv_label. ls_column-value = iv_width. ls_column-readonly = iv_readonly. APPEND ls_column TO -subitems. ro_self = me. ENDMETHOD. METHOD command. DATA ls_cmd LIKE LINE OF mt_commands. ASSERT iv_cmd_type BETWEEN 1 AND 4. ls_cmd-label = iv_label. ls_cmd-action = iv_action. ls_cmd-cmd_type = iv_cmd_type. APPEND ls_cmd TO mt_commands. ro_self = me. ENDMETHOD. METHOD create. DATA lv_ts TYPE timestampl. CREATE OBJECT ro_form. ro_form->mv_form_id = iv_form_id. ro_form->mv_help_page = iv_help_page. IF ro_form->mv_form_id IS INITIAL. GET TIME STAMP FIELD lv_ts. ro_form->mv_form_id = |form_{ lv_ts }|. ENDIF. ro_form->mv_webgui = zcl_abapgit_ui_factory=>get_frontend_services( )->is_webgui( ). ENDMETHOD. METHOD get_fields. rt_fields = mt_fields. ENDMETHOD. METHOD hidden. DATA ls_field LIKE LINE OF mt_fields. ls_field-type = zif_abapgit_html_form=>c_field_type-hidden. ls_field-name = iv_name. APPEND ls_field TO mt_fields. ro_self = me. ENDMETHOD. METHOD number. DATA ls_field LIKE LINE OF mt_fields. ls_field-type = zif_abapgit_html_form=>c_field_type-number. ls_field-name = iv_name. ls_field-label = iv_label. ls_field-readonly = iv_readonly. ls_field-min = iv_min. ls_field-max = iv_max. ls_field-hint = iv_hint. ls_field-required = iv_required. APPEND ls_field TO mt_fields. ro_self = me. ENDMETHOD. METHOD option. FIELD-SYMBOLS LIKE LINE OF mt_fields. DATA ls_option LIKE LINE OF -subitems. DATA lv_size TYPE i. lv_size = lines( mt_fields ). ASSERT lv_size > 0. " Exception ? Maybe add zcx_no_check ? READ TABLE mt_fields INDEX lv_size ASSIGNING . ASSERT sy-subrc = 0. ASSERT -type = zif_abapgit_html_form=>c_field_type-radio. " Or dropdown - TODO in future ls_option-label = iv_label. ls_option-value = iv_value. APPEND ls_option TO -subitems. ro_self = me. ENDMETHOD. METHOD radio. DATA ls_field LIKE LINE OF mt_fields. ls_field-type = zif_abapgit_html_form=>c_field_type-radio. ls_field-name = iv_name. ls_field-label = iv_label. ls_field-default_value = iv_default_value. ls_field-hint = iv_hint. ls_field-click = iv_action. " put options into one column instead of side-by-side ls_field-condense = iv_condense. APPEND ls_field TO mt_fields. ro_self = me. ENDMETHOD. METHOD render. FIELD-SYMBOLS LIKE LINE OF mt_fields. FIELD-SYMBOLS LIKE LINE OF mt_commands. DATA lv_hint TYPE string. DATA ls_form_id TYPE string. DATA ls_form_action TYPE string. DATA lv_cur_group TYPE string. DATA lv_url TYPE string. DATA lv_autofocus TYPE abap_bool. IF mv_form_id IS NOT INITIAL. ls_form_id = | id="{ mv_form_id }"|. ENDIF. LOOP AT mt_commands ASSIGNING WHERE cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main. ls_form_action = | action="sapevent:{ -action }"|. EXIT. ENDLOOP. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( |
    | ). " to center use 'dialog-form-center' ri_html->add( |
    | ). " Add hidden button that triggers main command when pressing enter LOOP AT mt_commands ASSIGNING WHERE cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main. ri_html->add( || ). EXIT. ENDLOOP. lv_autofocus = abap_true. LOOP AT mt_fields ASSIGNING . AT FIRST. IF -type <> zif_abapgit_html_form=>c_field_type-field_group. ri_html->add( |
      | ). ENDIF. ENDAT. IF -type = zif_abapgit_html_form=>c_field_type-field_group. IF lv_cur_group IS NOT INITIAL AND lv_cur_group <> -name. ri_html->add( |
    | ). ri_html->add( || ). ENDIF. IF -hint IS NOT INITIAL. lv_hint = | title="{ -hint }"|. ELSE. lv_hint = ''. ENDIF. lv_cur_group = -name. ri_html->add( |
    | ). ri_html->add( |{ -label }| ). ri_html->add( |
      | ). CONTINUE. ENDIF. render_field( ii_html = ri_html io_values = io_values io_validation_log = io_validation_log is_field = iv_autofocus = lv_autofocus ). lv_autofocus = abap_false. AT LAST. ri_html->add( |
    | ). IF lv_cur_group IS NOT INITIAL. ri_html->add( |
    | ). ENDIF. ENDAT. ENDLOOP. ri_html->add( |
      | ). ri_html->add( |
    • | ). IF mv_help_page IS NOT INITIAL. lv_url = escape( val = mv_help_page format = cl_abap_format=>e_url ). ri_html->add_a( iv_txt = zcl_abapgit_gui_buttons=>help( ) iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ lv_url }| iv_class = 'dialog-help' iv_title = 'Help' ). ENDIF. LOOP AT mt_commands ASSIGNING . render_command( ii_html = ri_html is_cmd = ). ENDLOOP. ri_html->add( |
    • | ). ri_html->add( |
    | ). ri_html->add( || ). ri_html->add( |
    | ). register_handlers( ). ENDMETHOD. METHOD render_command. " HTML GUI supports only links for submitting forms IF mv_webgui = abap_true. render_command_link( is_cmd = is_cmd ii_html = ii_html ). RETURN. ENDIF. CASE is_cmd-cmd_type. WHEN zif_abapgit_html_form=>c_cmd_type-link. render_command_link( is_cmd = is_cmd ii_html = ii_html ). WHEN zif_abapgit_html_form=>c_cmd_type-button. ii_html->add( || ). WHEN zif_abapgit_html_form=>c_cmd_type-input. ii_html->add( || ). WHEN zif_abapgit_html_form=>c_cmd_type-input_main. ii_html->add( || ). WHEN OTHERS. ASSERT 0 = 1. ENDCASE. ENDMETHOD. METHOD render_command_link. DATA lv_class TYPE string VALUE 'dialog-commands'. IF is_cmd-cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main. lv_class = lv_class && ' main'. ENDIF. ii_html->add_a( iv_txt = is_cmd-label iv_act = is_cmd-action iv_class = lv_class ). ENDMETHOD. METHOD render_field. DATA: ls_attr TYPE ty_attr, lv_item_class TYPE string. " Get value and validation error ls_attr-value = io_values->get( is_field-name ). IF is_field-type <> zif_abapgit_html_form=>c_field_type-textarea. ls_attr-value = escape( val = ls_attr-value format = cl_abap_format=>e_html_attr ). ENDIF. IF io_validation_log IS BOUND. ls_attr-error = io_validation_log->get( is_field-name ). IF ls_attr-error IS NOT INITIAL. ls_attr-error = escape( val = ls_attr-error format = cl_abap_format=>e_html_text ). ls_attr-error = |{ ls_attr-error }|. ENDIF. ENDIF. " Prepare field attributes IF is_field-required = abap_true. ls_attr-required = ' *'. ENDIF. IF is_field-hint IS NOT INITIAL. ls_attr-hint = escape( val = is_field-hint format = cl_abap_format=>e_html_attr ). ls_attr-hint = | title="{ ls_attr-hint }"|. ENDIF. IF is_field-placeholder IS NOT INITIAL. ls_attr-placeholder = escape( val = is_field-placeholder format = cl_abap_format=>e_html_attr ). ls_attr-placeholder = | placeholder="{ ls_attr-placeholder }"|. ENDIF. IF is_field-readonly = abap_true. ls_attr-readonly = ' readonly'. ENDIF. IF iv_autofocus = abap_true. ls_attr-autofocus = ' autofocus'. ENDIF. " Prepare item class lv_item_class = is_field-item_class. IF ls_attr-error IS NOT INITIAL. lv_item_class = condense( lv_item_class && ' error' ). ENDIF. IF is_field-type = zif_abapgit_html_form=>c_field_type-text AND is_field-max BETWEEN 1 AND 20. " Reduced width for short fields lv_item_class = lv_item_class && ' w40'. ENDIF. IF is_field-type = zif_abapgit_html_form=>c_field_type-hidden. lv_item_class = lv_item_class && ' hidden'. ENDIF. IF lv_item_class IS NOT INITIAL. lv_item_class = | class="{ lv_item_class }"|. ENDIF. " Render field ii_html->add( || ). CASE is_field-type. WHEN zif_abapgit_html_form=>c_field_type-text OR zif_abapgit_html_form=>c_field_type-number. render_field_text( ii_html = ii_html is_field = is_field is_attr = ls_attr ). WHEN zif_abapgit_html_form=>c_field_type-textarea. render_field_textarea( ii_html = ii_html is_field = is_field is_attr = ls_attr ). WHEN zif_abapgit_html_form=>c_field_type-checkbox. render_field_checkbox( ii_html = ii_html is_field = is_field is_attr = ls_attr ). WHEN zif_abapgit_html_form=>c_field_type-radio. render_field_radio( ii_html = ii_html is_field = is_field is_attr = ls_attr ). WHEN zif_abapgit_html_form=>c_field_type-table. render_field_table( ii_html = ii_html is_field = is_field is_attr = ls_attr io_values = io_values ). WHEN zif_abapgit_html_form=>c_field_type-hidden. render_field_hidden( ii_html = ii_html is_field = is_field is_attr = ls_attr ). WHEN OTHERS. ASSERT 1 = 0. ENDCASE. ii_html->add( '' ). ENDMETHOD. METHOD render_field_checkbox. DATA lv_checked TYPE string. DATA lv_disabled TYPE string. IF is_attr-error IS NOT INITIAL. ii_html->add( is_attr-error ). ENDIF. IF is_attr-value = abap_true OR is_attr-value = 'on'. " boolc return ` ` which is not initial -> bug after 1st validation lv_checked = ' checked'. ENDIF. IF is_attr-readonly IS NOT INITIAL. lv_disabled = ' disabled'. ENDIF. ii_html->add( || ). ii_html->add( || ). ENDMETHOD. METHOD render_field_hidden. ii_html->add( || ). ENDMETHOD. METHOD render_field_radio. DATA: lv_checked TYPE string, lv_opt_id TYPE string, lv_opt_value TYPE string, lv_onclick TYPE string. FIELD-SYMBOLS LIKE LINE OF is_field-subitems. ii_html->add( |{ is_field-label }| ). IF is_attr-error IS NOT INITIAL. ii_html->add( is_attr-error ). ENDIF. ii_html->add( |
    | ). LOOP AT is_field-subitems ASSIGNING . lv_opt_id = |{ is_field-name }{ sy-tabix }|. lv_opt_value = escape( val = -value format = cl_abap_format=>e_html_attr ). CLEAR lv_checked. IF is_attr-value = lv_opt_value OR ( is_attr-value IS INITIAL AND lv_opt_value = is_field-default_value ). lv_checked = ' checked'. ENDIF. " With edge browser control radio buttons aren't checked automatically when " activated with link hints. Therefore we need to check them manually. IF is_field-click IS NOT INITIAL. lv_onclick = |onclick="| && |var form = document.getElementById('{ mv_form_id }');| && |document.getElementById('{ lv_opt_id }').checked = true;| && |form.action = 'sapevent:{ is_field-click }';| && |form.submit();"|. ELSE. lv_onclick = |onclick="document.getElementById('{ lv_opt_id }').checked = true;"|. ENDIF. IF is_field-condense = abap_true. ii_html->add( '
    ' ). ENDIF. ii_html->add( || ). ii_html->add( || ). IF is_field-condense = abap_true. ii_html->add( '
    ' ). ENDIF. ENDLOOP. ii_html->add( '
    ' ). ENDMETHOD. METHOD render_field_table. DATA: lv_value TYPE string, lv_readonly TYPE string, lv_rows TYPE i, lv_cell_id TYPE string. FIELD-SYMBOLS LIKE LINE OF is_field-subitems. ii_html->add( || ). IF is_attr-error IS NOT INITIAL. ii_html->add( is_attr-error ). ENDIF. lv_rows = io_values->get( |{ is_field-name }-{ zif_abapgit_html_form=>c_rows }| ). " Render table only if there are some data rows IF lv_rows > 0. ii_html->add( || ). ii_html->add( || ). ii_html->add( || ). LOOP AT is_field-subitems ASSIGNING . CLEAR lv_value. IF -value IS NOT INITIAL. lv_value = escape( val = -value format = cl_abap_format=>e_html_attr ). lv_value = | width="{ lv_value }"|. ENDIF. ii_html->add( |{ -label }| ). ENDLOOP. ii_html->add( || ). ii_html->add( || ). ii_html->add( || ). DO lv_rows TIMES. lv_rows = sy-index. ii_html->add( || ). LOOP AT is_field-subitems ASSIGNING . lv_cell_id = |{ is_field-name }-{ lv_rows }-{ sy-tabix }|. lv_value = escape( val = io_values->get( lv_cell_id ) format = cl_abap_format=>e_html_attr ). CLEAR lv_readonly. IF -readonly = abap_true. lv_readonly = | readonly|. ENDIF. ii_html->add( || ). ENDLOOP. ii_html->add( || ). ENDDO. ii_html->add( || ). ii_html->add( |
    | ). ELSE. ii_html->add( || ). ENDIF. " Hidden field with number of rows to simplify getting values from form lv_value = |{ is_field-name }-{ zif_abapgit_html_form=>c_rows }|. ii_html->add( || ). ENDMETHOD. METHOD render_field_text. DATA: lv_type TYPE string, lv_minlength TYPE string, lv_maxlength TYPE string. ii_html->add( || ). IF is_attr-error IS NOT INITIAL. ii_html->add( is_attr-error ). ENDIF. IF is_field-side_action IS NOT INITIAL. ii_html->add( '
    ' ). " Ugly :( ENDIF. IF is_field-type = zif_abapgit_html_form=>c_field_type-number. lv_type = 'number'. ELSEIF is_field-password = abap_true. lv_type = 'password'. ELSE. lv_type = 'text'. ENDIF. IF is_field-min > 0. lv_minlength = | minlength={ is_field-min }|. ENDIF. IF is_field-max > 0 AND is_field-max < cl_abap_math=>max_int4. lv_maxlength = | maxlength={ is_field-max }|. ENDIF. ii_html->add( || ). IF is_field-side_action IS NOT INITIAL. ii_html->add( '
    ' ). ii_html->add( '
    ' ). ii_html->add( || ). ii_html->add( '
    ' ). ENDIF. ENDMETHOD. METHOD render_field_textarea. DATA lv_rows TYPE string. DATA lv_cols TYPE string. DATA lv_html TYPE string. ii_html->add( || ). IF is_attr-error IS NOT INITIAL. ii_html->add( is_attr-error ). ENDIF. IF is_field-rows > 0. lv_rows = | rows="{ is_field-rows }"|. ELSEIF is_attr-value IS NOT INITIAL. lv_rows = | rows="{ lines( zcl_abapgit_convert=>split_string( is_attr-value ) ) + 1 }"|. ENDIF. IF is_field-cols > 0. lv_cols = | cols="{ is_field-cols }"|. ENDIF. " Avoid adding line-breaks inside textarea tag (except for the actual value) lv_html = ||. ii_html->add( lv_html ). ENDMETHOD. METHOD start_group. DATA ls_field LIKE LINE OF mt_fields. ls_field-type = zif_abapgit_html_form=>c_field_type-field_group. ls_field-label = iv_label. ls_field-name = iv_name. ls_field-hint = iv_hint. APPEND ls_field TO mt_fields. ro_self = me. ENDMETHOD. METHOD table. DATA ls_field LIKE LINE OF mt_fields. ls_field-type = zif_abapgit_html_form=>c_field_type-table. ls_field-name = iv_name. ls_field-label = iv_label. ls_field-hint = iv_hint. APPEND ls_field TO mt_fields. ro_self = me. ENDMETHOD. METHOD text. DATA ls_field LIKE LINE OF mt_fields. ls_field-type = zif_abapgit_html_form=>c_field_type-text. ls_field-name = iv_name. ls_field-label = iv_label. ls_field-upper_case = iv_upper_case. ls_field-readonly = iv_readonly. ls_field-min = iv_min. ls_field-max = iv_max. ls_field-password = iv_password. ls_field-condense = iv_condense. ls_field-hint = iv_hint. ls_field-required = iv_required. ls_field-placeholder = iv_placeholder. IF iv_side_action IS NOT INITIAL AND mv_form_id IS NOT INITIAL. ls_field-item_class = 'with-command'. ls_field-side_action = iv_side_action. ls_field-dblclick = | ondblclick="document.getElementById('{ mv_form_id }').action = 'sapevent:| && |{ iv_side_action }'; document.getElementById('{ mv_form_id }').submit()"|. ENDIF. APPEND ls_field TO mt_fields. ro_self = me. ENDMETHOD. METHOD textarea. DATA ls_field LIKE LINE OF mt_fields. ls_field-type = zif_abapgit_html_form=>c_field_type-textarea. ls_field-name = iv_name. ls_field-label = iv_label. ls_field-readonly = iv_readonly. ls_field-hint = iv_hint. ls_field-required = iv_required. ls_field-placeholder = iv_placeholder. ls_field-rows = iv_rows. ls_field-cols = iv_cols. ls_field-upper_case = iv_upper_case. APPEND ls_field TO mt_fields. ro_self = me. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA: ls_hotkey_action LIKE LINE OF rt_hotkey_actions. FIELD-SYMBOLS: TYPE zif_abapgit_html_form=>ty_command. ls_hotkey_action-ui_component = |Form-{ mv_form_id }|. READ TABLE mt_commands WITH KEY cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main ASSIGNING . IF sy-subrc = 0. ls_hotkey_action-description = -label. ls_hotkey_action-action = -action. ls_hotkey_action-hotkey = |Enter|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDIF. READ TABLE mt_commands WITH KEY action = zif_abapgit_definitions=>c_action-go_back ASSIGNING . IF sy-subrc = 0. ls_hotkey_action-description = -label. ls_hotkey_action-action = -action. ls_hotkey_action-hotkey = |F3|. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_html_action_utils IMPLEMENTATION. METHOD add_field. DATA ls_field LIKE LINE OF ct_field. FIELD-SYMBOLS TYPE any. ls_field-name = iv_name. CASE cl_abap_typedescr=>describe_by_data( ig_field )->kind. WHEN cl_abap_typedescr=>kind_elem. ls_field-value = ig_field. WHEN cl_abap_typedescr=>kind_struct. ASSIGN COMPONENT iv_name OF STRUCTURE ig_field TO . ASSERT IS ASSIGNED. ls_field-value = . WHEN OTHERS. ASSERT 0 = 1. ENDCASE. APPEND ls_field TO ct_field. ENDMETHOD. METHOD dbkey_encode. DATA lt_fields TYPE ty_name_value_tt. add_field( EXPORTING iv_name = 'TYPE' ig_field = is_key-type CHANGING ct_field = lt_fields ). add_field( EXPORTING iv_name = 'VALUE' ig_field = is_key-value CHANGING ct_field = lt_fields ). rv_string = fields_to_string( lt_fields ). ENDMETHOD. METHOD dir_encode. DATA lt_fields TYPE ty_name_value_tt. add_field( EXPORTING iv_name = 'PATH' ig_field = iv_path CHANGING ct_field = lt_fields ). rv_string = fields_to_string( lt_fields ). ENDMETHOD. METHOD fields_to_string. * There is no equivalent to cl_http_utility=>fields_to_string released in ABAP Cloud, * see cl_web_http_utility DATA lt_tab TYPE STANDARD TABLE OF string WITH DEFAULT KEY. DATA lv_str TYPE string. DATA ls_field LIKE LINE OF it_fields. LOOP AT it_fields INTO ls_field. ls_field-value = cl_http_utility=>escape_url( ls_field-value ). lv_str = ls_field-name && '=' && ls_field-value. APPEND lv_str TO lt_tab. ENDLOOP. rv_string = concat_lines_of( table = lt_tab sep = '&' ). ENDMETHOD. METHOD file_encode. DATA lt_fields TYPE ty_name_value_tt. add_field( EXPORTING iv_name = 'KEY' ig_field = iv_key CHANGING ct_field = lt_fields ). add_field( EXPORTING iv_name = 'PATH' ig_field = ig_file CHANGING ct_field = lt_fields ). add_field( EXPORTING iv_name = 'FILENAME' ig_field = ig_file CHANGING ct_field = lt_fields ). IF iv_extra IS SUPPLIED. add_field( EXPORTING iv_name = 'EXTRA' ig_field = iv_extra CHANGING ct_field = lt_fields ). ENDIF. rv_string = fields_to_string( lt_fields ). ENDMETHOD. METHOD jump_encode. DATA lt_fields TYPE ty_name_value_tt. add_field( EXPORTING iv_name = 'TYPE' ig_field = iv_obj_type CHANGING ct_field = lt_fields ). add_field( EXPORTING iv_name = 'NAME' ig_field = iv_obj_name CHANGING ct_field = lt_fields ). IF iv_filename IS NOT INITIAL. add_field( EXPORTING iv_name = 'FILE' ig_field = iv_filename CHANGING ct_field = lt_fields ). ENDIF. rv_string = fields_to_string( lt_fields ). ENDMETHOD. METHOD obj_encode. DATA lt_fields TYPE ty_name_value_tt. add_field( EXPORTING iv_name = 'KEY' ig_field = iv_key CHANGING ct_field = lt_fields ). add_field( EXPORTING iv_name = 'OBJ_TYPE' ig_field = ig_object CHANGING ct_field = lt_fields ). add_field( EXPORTING iv_name = 'OBJ_NAME' ig_field = ig_object CHANGING ct_field = lt_fields ). rv_string = fields_to_string( lt_fields ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_picklist IMPLEMENTATION. METHOD constructor. FIELD-SYMBOLS TYPE STANDARD TABLE. super->constructor( ). " copy contents of table to local scope CREATE DATA mr_list LIKE it_list. ASSIGN mr_list->* TO . APPEND LINES OF it_list TO . mv_attr_name = to_upper( iv_attr_name ). mi_item_renderer = ii_item_renderer. mv_in_page = iv_in_page. mv_id = iv_id. mv_title = iv_title. IF mi_item_renderer IS NOT BOUND AND mv_attr_name IS INITIAL. zcx_abapgit_exception=>raise( 'Renderer or attr name required' ). ENDIF. CREATE OBJECT mo_form_data. CREATE OBJECT mo_validation_log. mo_form = get_form_schema( ). mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). ENDMETHOD. METHOD get_form_schema. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. DATA lv_index TYPE i. DATA lv_label TYPE string. ro_form = zcl_abapgit_html_form=>create( ). ro_form->radio( iv_name = c_radio_name iv_label = mv_title ). ASSIGN mr_list->* TO . LOOP AT ASSIGNING . lv_index = sy-tabix. IF mv_attr_name IS NOT INITIAL. ASSIGN COMPONENT mv_attr_name OF STRUCTURE TO . ASSERT sy-subrc = 0. lv_label = . ELSEIF mi_item_renderer IS BOUND. lv_label = mi_item_renderer->render( iv_item = iv_index = lv_index )->render( ). ENDIF. ro_form->option( iv_label = lv_label iv_value = |{ lv_index }| ). ENDLOOP. ro_form->command( iv_label = 'Choose' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-choose )->command( iv_label = 'Back' iv_action = c_event-back ). ENDMETHOD. METHOD get_result_idx. rv_index = mv_selected. ENDMETHOD. METHOD get_result_item. FIELD-SYMBOLS TYPE STANDARD TABLE. CLEAR cs_selected. IF mv_selected > 0. ASSIGN mr_list->* TO . READ TABLE INDEX mv_selected INTO cs_selected. ASSERT sy-subrc = 0. ENDIF. ENDMETHOD. METHOD id. rv_id = mv_id. ENDMETHOD. METHOD is_fulfilled. rv_yes = mv_fulfilled. ENDMETHOD. METHOD is_in_page. rv_yes = mv_in_page. ENDMETHOD. METHOD return_state. IF mv_in_page = abap_true. rv_state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. rv_state = zcl_abapgit_gui=>c_event_state-go_back. ENDIF. ENDMETHOD. METHOD set_id. mv_id = iv_id. ro_me = me. ENDMETHOD. METHOD set_in_page. mv_in_page = iv_in_page. ro_me = me. ENDMETHOD. METHOD was_cancelled. rv_yes = mv_cancelled. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). mo_validation_log->clear( ). CASE ii_event->mv_action. WHEN c_event-back OR zif_abapgit_definitions=>c_action-go_back. " Handle go_back as a "graceful back" - implicit cancel by F3/ESC mv_fulfilled = abap_true. mv_cancelled = abap_true. rs_handled-state = return_state( ). WHEN c_event-choose. mv_selected = mo_form_data->get( c_radio_name ). IF mv_selected = 0. mo_validation_log->set( iv_key = c_radio_name iv_val = 'You have to select one item' ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ELSE. mv_fulfilled = abap_true. rs_handled-state = return_state( ). ENDIF. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_page_title~get_page_title. rv_title = mv_title. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. ri_html = zcl_abapgit_html=>create( mo_form->render( io_values = mo_form_data io_validation_log = mo_validation_log ) ). register_handlers( ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_HOC IMPLEMENTATION. METHOD constructor. super->constructor( ). mi_child = ii_child_component. ms_control = is_control. IF ms_control-show_as_modal = abap_false. ms_control-show_as_modal = detect_modal( ). ENDIF. IF ms_control-page_menu_provider IS NOT BOUND. ms_control-page_menu_provider = detect_menu_provider( ). ENDIF. IF ms_control-page_title_provider IS NOT BOUND. ms_control-page_title_provider = detect_title_provider( ). ENDIF. ENDMETHOD. METHOD create. DATA lo_page TYPE REF TO zcl_abapgit_gui_page_hoc. DATA ls_control TYPE zcl_abapgit_gui_page=>ty_control. ls_control-page_title = iv_page_title. ls_control-page_layout = iv_page_layout. ls_control-page_menu = io_page_menu. ls_control-page_menu_provider = ii_page_menu_provider. ls_control-page_title_provider = ii_page_title_provider. ls_control-extra_css_url = iv_extra_css_url. ls_control-extra_js_url = iv_extra_js_url. ls_control-show_as_modal = iv_show_as_modal. IF ls_control-page_menu_provider IS NOT BOUND. " try component itself TRY. ls_control-page_menu_provider ?= ii_child_component. CATCH cx_sy_move_cast_error. ENDTRY. ENDIF. IF ls_control-page_title_provider IS NOT BOUND. " try component itself TRY. ls_control-page_title_provider ?= ii_child_component. CATCH cx_sy_move_cast_error. ENDTRY. ENDIF. CREATE OBJECT lo_page EXPORTING ii_child_component = ii_child_component is_control = ls_control. ri_page_wrap = lo_page. ENDMETHOD. METHOD detect_menu_provider. TRY. ri_ref ?= mi_child. CATCH cx_sy_move_cast_error. ENDTRY. ENDMETHOD. METHOD detect_modal. DATA li_modal TYPE REF TO zif_abapgit_gui_modal. TRY. li_modal ?= mi_child. rv_is_modal = li_modal->is_modal( ). CATCH cx_sy_move_cast_error. ENDTRY. ENDMETHOD. METHOD detect_title_provider. TRY. ri_ref ?= mi_child. CATCH cx_sy_move_cast_error. ENDTRY. ENDMETHOD. METHOD get_child. ri_child = mi_child. ENDMETHOD. METHOD render_content. IF mi_child IS BOUND. ri_html = mi_child->render( ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_page IMPLEMENTATION. METHOD constructor. super->constructor( ). mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). ms_control-page_layout = c_page_layout-centered. ENDMETHOD. METHOD footer. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ENDMETHOD. METHOD get_version_details. DATA lo_frontend_serv TYPE REF TO zif_abapgit_frontend_services. rv_version = zif_abapgit_version=>c_abap_version. IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. rv_version = rv_version && ` - Standalone Version`. ELSE. rv_version = rv_version && ` - Developer Version`. ENDIF. lo_frontend_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). CASE abap_true. WHEN lo_frontend_serv->is_webgui( ). rv_version = rv_version && ` - Web`. WHEN lo_frontend_serv->is_sapgui_for_windows( ). rv_version = rv_version && ` - Win`. WHEN lo_frontend_serv->is_sapgui_for_java( ). rv_version = rv_version && ` - Java`. WHEN OTHERS. * eg. open-abap? rv_version = rv_version && ` - Unknown`. ENDCASE. " Will be filled by JS method displayBrowserControlFooter rv_version = rv_version && ''. ENDMETHOD. METHOD header_script_links. ii_html->add( '' ). IF ms_control-extra_js_url IS NOT INITIAL. ii_html->add( || ). ENDIF. ENDMETHOD. METHOD header_stylesheet_links. ii_html->add( '' ). ii_html->add( '' ). " Themes ii_html->add( '' ). " Theme basis CASE mo_settings->get_ui_theme( ). WHEN zcl_abapgit_settings=>c_ui_theme-dark. ii_html->add( '' ). WHEN zcl_abapgit_settings=>c_ui_theme-belize. ii_html->add( '' ). ENDCASE. " Page stylesheets IF ms_control-extra_css_url IS NOT INITIAL. ii_html->add( || ). ENDIF. ENDMETHOD. METHOD html_head. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( 'abapGit' ). header_stylesheet_links( ri_html ). header_script_links( ri_html ). " Overwrite the automatic icon scaling done in zcl_abapgit_html=>icon CASE mo_settings->get_icon_scaling( ). WHEN mo_settings->c_icon_scaling-large. ri_html->add( '' ). WHEN mo_settings->c_icon_scaling-small. ri_html->add( '' ). ENDCASE. ri_html->add( '' ). ENDMETHOD. METHOD is_edge_control_warning_needed. DATA: lv_gui_release TYPE zif_abapgit_frontend_services=>ty_gui_release, lv_gui_sp TYPE zif_abapgit_frontend_services=>ty_gui_sp, lv_gui_patch TYPE zif_abapgit_frontend_services=>ty_gui_patch, li_frontend_services TYPE REF TO zif_abapgit_frontend_services. " With SAP GUI 8.00 PL3 and 7.70 PL13 Edge browser control is basically working. " For lower releases we render the browser control warning " and toggle it via JS function toggleBrowserControlWarning. rv_result = abap_true. TRY. li_frontend_services = zcl_abapgit_ui_factory=>get_frontend_services( ). li_frontend_services->get_gui_version( IMPORTING ev_gui_release = lv_gui_release ev_gui_sp = lv_gui_sp ev_gui_patch = lv_gui_patch ). CATCH zcx_abapgit_exception. RETURN. ENDTRY. IF lv_gui_release >= '7700' AND lv_gui_sp >= '1' AND lv_gui_patch >= '13' OR lv_gui_release >= '8000' AND lv_gui_sp >= '1' AND lv_gui_patch >= '3'. rv_result = abap_false. ENDIF. ENDMETHOD. METHOD render_browser_control_warning. DATA li_documentation_link TYPE REF TO zif_abapgit_html. CREATE OBJECT li_documentation_link TYPE zcl_abapgit_html. li_documentation_link->add_a( iv_txt = 'Documentation' iv_typ = zif_abapgit_html=>c_action_type-url iv_act = 'https://docs.abapgit.org/guide-sapgui.html#sap-gui-for-windows' ). ii_html->add( '
    ' ). ii_html->add( zcl_abapgit_gui_chunk_lib=>render_warning_banner( |Attention: You use Edge browser control. | && |There are several known malfunctions. See | && li_documentation_link->render( ) ) ). ii_html->add( '
    ' ). ENDMETHOD. METHOD render_command_palettes. ii_html->add( 'var gCommandPalette = new CommandPalette(enumerateUiActions, {' ). ii_html->add( ' toggleKey: "F1",' ). ii_html->add( ' hotkeyDescription: "Command Palette"' ). ii_html->add( '});' ). ENDMETHOD. METHOD render_deferred_parts. DATA lt_parts TYPE zif_abapgit_html=>ty_table_of. DATA li_part LIKE LINE OF lt_parts. lt_parts = gui_services( )->get_html_parts( )->get_parts( iv_part_category ). LOOP AT lt_parts INTO li_part. ii_html->add( li_part ). ENDLOOP. ENDMETHOD. METHOD render_error_message_box. " You should remember that the we have to instantiate ro_html even " it's overwritten further down. Because ADD checks whether it's " bound. CREATE OBJECT ri_html TYPE zcl_abapgit_html. " You should remember that we render the message panel only " if we have an error. IF mx_error IS NOT BOUND. RETURN. ENDIF. ri_html = zcl_abapgit_gui_chunk_lib=>render_error_message_box( mx_error ). " You should remember that the exception viewer dispatches the events of " error message panel CREATE OBJECT mo_exception_viewer EXPORTING ix_error = mx_error. " You should remember that we render the message panel just once " for each exception/error text. CLEAR: mx_error. ENDMETHOD. METHOD render_hotkey_overview. DATA lo_hotkeys_component TYPE REF TO zif_abapgit_gui_renderable. lo_hotkeys_component ?= gui_services( )->get_hotkeys_ctl( ). " Mmmm ... ro_html = lo_hotkeys_component->render( ). ENDMETHOD. METHOD render_link_hints. DATA: lv_link_hint_key TYPE c LENGTH 1. lv_link_hint_key = mo_settings->get_link_hint_key( ). IF mo_settings->get_link_hints_enabled( ) = abap_true AND lv_link_hint_key IS NOT INITIAL. ii_html->add( |activateLinkHints("{ lv_link_hint_key }");| ). ii_html->add( |setInitialFocusWithQuerySelector('#header', false);| ). ii_html->add( |enableArrowListNavigation();| ). ENDIF. ENDMETHOD. METHOD scripts. CREATE OBJECT ri_html TYPE zcl_abapgit_html. render_deferred_parts( ii_html = ri_html iv_part_category = c_html_parts-scripts ). render_link_hints( ri_html ). render_command_palettes( ri_html ). ri_html->add( |toggleBrowserControlWarning();| ). ri_html->add( |displayBrowserControlFooter();| ). ENDMETHOD. METHOD title. DATA lo_page_menu LIKE ms_control-page_menu. DATA lv_page_title TYPE string. lo_page_menu = ms_control-page_menu. IF lo_page_menu IS NOT BOUND AND ms_control-page_menu_provider IS BOUND. lo_page_menu = ms_control-page_menu_provider->get_menu( ). ENDIF. lv_page_title = ms_control-page_title. IF ms_control-page_title_provider IS BOUND. lv_page_title = ms_control-page_title_provider->get_page_title( ). ENDIF. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ENDMETHOD. METHOD zif_abapgit_gui_error_handler~handle_error. mx_error = ix_error. rv_handled = abap_true. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. CASE ii_event->mv_action. WHEN zif_abapgit_definitions=>c_action-goto_source. IF mo_exception_viewer IS BOUND. mo_exception_viewer->goto_source( ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-show_callstack. IF mo_exception_viewer IS BOUND. mo_exception_viewer->show_callstack( ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. WHEN zif_abapgit_definitions=>c_action-goto_message. IF mo_exception_viewer IS BOUND. mo_exception_viewer->goto_message( ). ENDIF. rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_modal~is_modal. rv_yes = boolc( ms_control-show_as_modal = abap_true ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA: li_script TYPE REF TO zif_abapgit_html, lo_timer TYPE REF TO zcl_abapgit_timer. register_handlers( ). lo_timer = zcl_abapgit_timer=>create( )->start( ). " Real page CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( html_head( ) ). ri_html->add( || ). ri_html->add( title( ) ). ri_html->add( '
    ' ). ri_html->add( render_content( ) ). " TODO -> render child ri_html->add( render_hotkey_overview( ) ). ri_html->add( render_error_message_box( ) ). render_deferred_parts( ii_html = ri_html iv_part_category = c_html_parts-hidden_forms ). ri_html->add( footer( lo_timer->end( ) ) ). ri_html->add( '
    ' ). li_script = scripts( ). IF li_script IS BOUND AND li_script->is_empty( ) = abap_false. ri_html->add( '' ). ENDIF. ri_html->add( '' ). ri_html->add( '' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_menus IMPLEMENTATION. METHOD advanced. CREATE OBJECT ro_menu EXPORTING iv_id = 'toolbar-advanced'. ro_menu->add( iv_txt = 'Database Utility' iv_act = zif_abapgit_definitions=>c_action-go_db )->add( iv_txt = 'Package to ZIP' iv_act = zif_abapgit_definitions=>c_action-zip_package )->add( iv_txt = 'Transport to ZIP' iv_act = zif_abapgit_definitions=>c_action-zip_transport )->add( iv_txt = 'Object to Files' iv_act = zif_abapgit_definitions=>c_action-zip_object )->add( iv_txt = 'Debug Info' iv_act = zif_abapgit_definitions=>c_action-go_debuginfo ). IF zcl_abapgit_ui_factory=>get_frontend_services( )->is_sapgui_for_windows( ) = abap_true. ro_menu->add( iv_txt = 'Open IE DevTools' iv_act = zif_abapgit_definitions=>c_action-ie_devtools ). ENDIF. ENDMETHOD. METHOD back. CREATE OBJECT ro_menu EXPORTING iv_id = 'toolbar-back'. ro_menu->add( iv_txt = 'Back' iv_act = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD experimental. IF zcl_abapgit_persist_factory=>get_settings( )->read( )->get_experimental_features( ) IS NOT INITIAL. io_menu->add( iv_txt = zcl_abapgit_gui_buttons=>experimental( ) iv_act = zif_abapgit_definitions=>c_action-go_settings ). ENDIF. ENDMETHOD. METHOD help. CREATE OBJECT ro_menu EXPORTING iv_id = 'toolbar-help'. ro_menu->add( iv_txt = 'Tutorial' iv_act = zif_abapgit_definitions=>c_action-go_tutorial )->add( iv_txt = 'Documentation' iv_act = zif_abapgit_definitions=>c_action-documentation )->add( iv_txt = 'Explore' iv_act = zif_abapgit_definitions=>c_action-go_explore )->add( iv_txt = 'Changelog' iv_act = zif_abapgit_definitions=>c_action-changelog )->add( iv_txt = 'Hotkeys' iv_act = zif_abapgit_definitions=>c_action-show_hotkeys ). ENDMETHOD. METHOD repo_settings. CREATE OBJECT ro_menu EXPORTING iv_id = 'toolbar-repo-settings'. ro_menu->add( iv_txt = 'Repository' iv_act = |{ zif_abapgit_definitions=>c_action-repo_settings }?key={ iv_key }| iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_settings ) )->add( iv_txt = 'Local' iv_act = |{ zif_abapgit_definitions=>c_action-repo_local_settings }?key={ iv_key }| iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_local_settings ) )->add( iv_txt = 'Remote' iv_act = |{ zif_abapgit_definitions=>c_action-repo_remote_settings }?key={ iv_key }| iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_remote_settings ) )->add( iv_txt = 'Background' iv_act = |{ zif_abapgit_definitions=>c_action-repo_background }?key={ iv_key }| iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_background ) )->add( iv_txt = 'Stats' iv_act = |{ zif_abapgit_definitions=>c_action-repo_infos }?key={ iv_key }| iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-repo_infos ) ). zcl_abapgit_exit=>get_instance( )->enhance_repo_toolbar( io_menu = ro_menu iv_key = iv_key iv_act = iv_act ). ENDMETHOD. METHOD settings. CREATE OBJECT ro_menu EXPORTING iv_id = 'toolbar-settings'. ro_menu->add( iv_txt = 'Global' iv_act = zif_abapgit_definitions=>c_action-go_settings iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-go_settings ) )->add( iv_txt = 'Personal' iv_act = zif_abapgit_definitions=>c_action-go_settings_personal iv_cur = boolc( iv_act = zif_abapgit_definitions=>c_action-go_settings_personal ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_in_page_modal IMPLEMENTATION. METHOD constructor. ms_attrs-width = iv_width. ms_attrs-height = iv_height. mi_child = ii_child. ENDMETHOD. METHOD create. CREATE OBJECT ro_wrap EXPORTING ii_child = ii_child iv_width = iv_width iv_height = iv_height. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA lo_style TYPE REF TO zcl_abapgit_string_buffer. CREATE OBJECT ri_html TYPE zcl_abapgit_html. CREATE OBJECT lo_style. IF ms_attrs-width IS NOT INITIAL. lo_style->add( |width:{ ms_attrs-width }px;| ). ENDIF. IF ms_attrs-height IS NOT INITIAL. lo_style->add( |height:{ ms_attrs-height }px;| ). ENDIF. ri_html->add( || ). ri_html->add( || ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_COMPONENT IMPLEMENTATION. METHOD gui_services. IF mi_gui_services IS NOT BOUND. mi_gui_services = zcl_abapgit_ui_factory=>get_gui_services( ). ENDIF. ri_gui_services = mi_gui_services. ENDMETHOD. METHOD register_deferred_script. gui_services( )->get_html_parts( )->add_part( iv_collection = c_html_parts-scripts ii_part = ii_part ). ENDMETHOD. METHOD register_event_handler. DATA li_event_handler TYPE REF TO zif_abapgit_gui_event_handler. IF ii_event_handler IS BOUND. li_event_handler = ii_event_handler. ELSE. TRY. li_event_handler ?= me. CATCH cx_root. RETURN. ENDTRY. ENDIF. gui_services( )->register_event_handler( li_event_handler ). ENDMETHOD. METHOD register_handlers. register_event_handler( ). register_hotkeys( ). ENDMETHOD. METHOD register_hotkeys. DATA li_hotkey_provider TYPE REF TO zif_abapgit_gui_hotkeys. IF ii_hotkey_provider IS BOUND. li_hotkey_provider = ii_hotkey_provider. ELSE. TRY. li_hotkey_provider ?= me. CATCH cx_root. RETURN. ENDTRY. ENDIF. gui_services( )->get_hotkeys_ctl( )->register_hotkeys( li_hotkey_provider->get_hotkey_actions( ) ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_CHUNK_LIB IMPLEMENTATION. METHOD class_constructor. DATA lv_fm TYPE string. lv_fm = 'GET_SYSTEM_TIMEZONE'. TRY. CALL METHOD ('CL_ABAP_TSTMP')=>get_system_timezone RECEIVING system_timezone = gv_time_zone. CATCH cx_sy_dyn_call_illegal_method. CALL FUNCTION lv_fm IMPORTING timezone = gv_time_zone EXCEPTIONS customizing_missing = 1 OTHERS = 2. ENDTRY. ENDMETHOD. METHOD get_item_icon. CASE is_item-obj_type. WHEN 'PROG' OR 'CLAS' OR 'FUGR' OR 'INTF' OR 'TYPE'. rv_html = zcl_abapgit_html=>icon( iv_name = 'file-code/darkgrey' iv_hint = 'Code' ). WHEN 'W3MI' OR 'W3HT' OR 'SFPF'. rv_html = zcl_abapgit_html=>icon( iv_name = 'file-image/darkgrey' iv_hint = 'Binary' ). WHEN 'DEVC'. rv_html = zcl_abapgit_html=>icon( iv_name = 'box/darkgrey' iv_hint = 'Package' ). WHEN ''. rv_html = space. " no icon WHEN OTHERS. rv_html = zcl_abapgit_html=>icon( 'file-alt/darkgrey' ). ENDCASE. IF is_item-is_dir = abap_true. rv_html = zcl_abapgit_html=>icon( iv_name = 'folder/darkgrey' iv_hint = 'Folder' ). ENDIF. ENDMETHOD. METHOD get_item_link. DATA lv_encode TYPE string. DATA li_html TYPE REF TO zif_abapgit_html. DATA ls_item LIKE is_item. IF is_item IS INITIAL. ls_item-obj_type = iv_obj_type. ls_item-obj_name = iv_obj_name. ELSE. ls_item = is_item. ENDIF. CREATE OBJECT li_html TYPE zcl_abapgit_html. lv_encode = zcl_abapgit_html_action_utils=>jump_encode( iv_obj_type = ls_item-obj_type iv_obj_name = ls_item-obj_name ). rv_html = li_html->a( iv_txt = |{ ls_item-obj_name }| iv_act = |{ zif_abapgit_definitions=>c_action-jump }?{ lv_encode }| ). ENDMETHOD. METHOD get_t100_text. MESSAGE ID iv_msgid TYPE 'S' NUMBER iv_msgno WITH '&1' '&2' '&3' '&4' INTO rv_text. " Don't return any generic messages like `&1 &2 &3 &4` IF rv_text CO ' 0123456789&'. CLEAR rv_text. ENDIF. ENDMETHOD. METHOD normalize_program_name. rv_normalized_program_name = substring_before( val = iv_program_name regex = `(=+CP)?$` ). ENDMETHOD. METHOD render_branch_name. DATA: lv_key TYPE string, lv_branch TYPE string, lv_selected_commit TYPE string, lv_commit_short_sha TYPE string, lv_text TYPE string, lv_icon TYPE string, lv_hint TYPE string, lv_class TYPE string. IF iv_repo_key IS NOT INITIAL. lv_key = iv_repo_key. ELSEIF io_repo IS BOUND. lv_key = io_repo->get_key( ). ELSE. zcx_abapgit_exception=>raise( 'Either iv_repo_key or io_repo must be supplied' ). ENDIF. IF iv_branch IS NOT INITIAL. lv_branch = iv_branch. lv_text = zcl_abapgit_git_branch_list=>get_display_name( lv_branch ). ELSEIF io_repo IS BOUND. lv_selected_commit = io_repo->get_selected_commit( ). IF lv_selected_commit IS NOT INITIAL. "Convert to short commit. Example: (ae623b9...) lv_commit_short_sha = lv_selected_commit+0(7). lv_text = |({ lv_commit_short_sha }...)|. ELSE. lv_branch = io_repo->get_selected_branch( ). lv_text = zcl_abapgit_git_branch_list=>get_display_name( lv_branch ). ENDIF. ELSE. zcx_abapgit_exception=>raise( 'Either iv_branch or io_repo must be supplied' ). ENDIF. CASE zcl_abapgit_git_branch_list=>get_type( lv_branch ). WHEN zif_abapgit_git_definitions=>c_git_branch_type-branch. lv_class = 'branch branch_branch'. lv_icon = 'code-branch/grey70'. lv_hint = 'Current branch'. WHEN zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag OR zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. lv_class = 'branch'. lv_icon = 'tag-solid/grey70'. lv_hint = 'Current tag'. WHEN OTHERS. lv_class = 'branch branch_branch'. lv_icon = 'code-branch/grey70'. lv_hint = 'Current commit'. ENDCASE. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( || ). ri_html->add_icon( iv_name = lv_icon iv_hint = lv_hint ). IF iv_interactive = abap_true. ri_html->add_a( iv_act = |{ zif_abapgit_definitions=>c_action-git_branch_switch }?key={ lv_key }| iv_txt = lv_text ). ELSE. ri_html->add( lv_text ). ENDIF. ri_html->add( '' ). ENDMETHOD. METHOD render_error. DATA lv_error TYPE string. DATA lv_class TYPE string VALUE 'panel error center'. IF iv_extra_style IS NOT INITIAL. lv_class = lv_class && ` ` && iv_extra_style. ENDIF. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF ix_error IS BOUND. lv_error = ix_error->get_text( ). ELSE. lv_error = iv_error. ENDIF. ri_html->add( |
    | ). ri_html->add( |{ ri_html->icon( 'exclamation-circle/red' ) } { lv_error }| ). ri_html->add( '
    ' ). ENDMETHOD. METHOD render_error_message_box. DATA: lv_error_text TYPE string, lv_longtext TYPE string, lt_longtext_paragraphs TYPE string_table, lv_program_name TYPE sy-repid, lv_title TYPE string, lv_text TYPE string. FIELD-SYMBOLS: TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. lv_error_text = ix_error->get_text( ). lv_longtext = ix_error->if_message~get_longtext( abap_true ). IF lv_longtext IS NOT INITIAL. lv_error_text = |{ lv_error_text } More...|. REPLACE FIRST OCCURRENCE OF REGEX |({ zcx_abapgit_exception=>c_section_text-cause }{ cl_abap_char_utilities=>newline })| IN lv_longtext WITH |

    $1

    |. REPLACE FIRST OCCURRENCE OF REGEX |({ zcx_abapgit_exception=>c_section_text-system_response }{ cl_abap_char_utilities=>newline })| IN lv_longtext WITH |

    $1

    |. REPLACE FIRST OCCURRENCE OF REGEX |({ zcx_abapgit_exception=>c_section_text-what_to_do }{ cl_abap_char_utilities=>newline })| IN lv_longtext WITH |

    $1

    |. REPLACE FIRST OCCURRENCE OF REGEX |({ zcx_abapgit_exception=>c_section_text-sys_admin }{ cl_abap_char_utilities=>newline })| IN lv_longtext WITH |

    $1

    |. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_longtext WITH cl_abap_char_utilities=>newline. SPLIT lv_longtext AT cl_abap_char_utilities=>newline INTO TABLE lt_longtext_paragraphs. CLEAR lv_longtext. LOOP AT lt_longtext_paragraphs ASSIGNING . CONDENSE . IF IS INITIAL. CONTINUE. ENDIF. lv_longtext = |{ lv_longtext }

    { }

    { cl_abap_char_utilities=>newline }|. ENDLOOP. lv_longtext = |{ lv_longtext }
    |. ENDIF. ri_html->add( |
    | ). ri_html->add( |{ ri_html->icon( 'exclamation-circle/red' ) } { lv_error_text }| ). ri_html->add( |
    | ). ri_html->add_a( iv_txt = `❌` iv_act = `toggleDisplay('message')` iv_class = `close-btn` iv_typ = zif_abapgit_html=>c_action_type-onclick ). ri_html->add( |
    | ). ri_html->add( |
    | ). IF ix_error->if_t100_message~t100key-msgid IS NOT INITIAL. lv_title = get_t100_text( iv_msgid = ix_error->if_t100_message~t100key-msgid iv_msgno = ix_error->if_t100_message~t100key-msgno ). IF lv_title IS NOT INITIAL. lv_text = |Message E{ ix_error->if_t100_message~t100key-msgno }({ ix_error->if_t100_message~t100key-msgid })|. ri_html->add_a( iv_txt = lv_text iv_typ = zif_abapgit_html=>c_action_type-sapevent iv_act = zif_abapgit_definitions=>c_action-goto_message iv_title = lv_title iv_id = `a_goto_message` ). ENDIF. ENDIF. ix_error->get_source_position( IMPORTING program_name = lv_program_name ). lv_title = normalize_program_name( lv_program_name ). ri_html->add_a( iv_txt = `Goto source` iv_act = zif_abapgit_definitions=>c_action-goto_source iv_typ = zif_abapgit_html=>c_action_type-sapevent iv_title = lv_title iv_id = `a_goto_source` ). ri_html->add_a( iv_txt = `Callstack` iv_act = zif_abapgit_definitions=>c_action-show_callstack iv_typ = zif_abapgit_html=>c_action_type-sapevent iv_id = `a_callstack` ). ri_html->add( |
    | ). ri_html->add( |
    | ). ri_html->add( |{ lv_longtext }| ). ri_html->add( |
    | ). ri_html->add( |
    | ). ENDMETHOD. METHOD render_event_as_form. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( |
    | ). ENDMETHOD. METHOD render_help_hint. DATA li_html TYPE REF TO zif_abapgit_html. DATA lv_add_class TYPE string. li_html = zcl_abapgit_html=>create( ). IF iv_add_class IS NOT INITIAL. lv_add_class = ` ` && iv_add_class. ENDIF. li_html->add( |
    | ). li_html->add_icon( iv_name = 'question-circle-solid' iv_class = 'blue' ). li_html->add( `
    ` ). li_html->add( iv_text_to_wrap ). li_html->add( `
    ` ). li_html->add( `
    ` ). rv_html = li_html->render( iv_no_line_breaks = abap_true ). ENDMETHOD. METHOD render_infopanel. DATA lv_display TYPE string. DATA lv_class TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF iv_hide = abap_true. " Initially hide lv_display = 'display:none'. ENDIF. lv_class = 'info-panel'. IF iv_scrollable = abap_false. " Initially hide lv_class = lv_class && ' info-panel-fixed'. ENDIF. ri_html->add( |
    | ). ri_html->add( |
    { iv_title }| && '
    ' && ri_html->a( iv_txt = '❌' iv_typ = zif_abapgit_html=>c_action_type-onclick iv_act = |toggleDisplay('{ iv_div_id }')| iv_class = 'close-btn' ) && '
    ' ). IF iv_hint IS NOT INITIAL. ri_html->add( '
    ' && ri_html->icon( iv_name = 'exclamation-triangle' iv_class = 'pad-right' ) && iv_hint && '
    ' ). ENDIF. ri_html->add( |
    | ). ri_html->add( io_content ). ri_html->add( '
    ' ). ri_html->add( '
    ' ). ENDMETHOD. METHOD render_item_state. DATA: lv_system TYPE string. FIELD-SYMBOLS TYPE char1. rv_html = ''. DO 2 TIMES. CASE sy-index. WHEN 1. ASSIGN iv_lstate TO . lv_system = 'Local:'. WHEN 2. ASSIGN iv_rstate TO . lv_system = 'Remote:'. ENDCASE. CASE . WHEN zif_abapgit_definitions=>c_state-unchanged. "None or unchanged IF iv_lstate = zif_abapgit_definitions=>c_state-added OR iv_rstate = zif_abapgit_definitions=>c_state-added. rv_html = rv_html && |X|. ELSE. rv_html = rv_html && | |. ENDIF. WHEN zif_abapgit_definitions=>c_state-modified. "Changed rv_html = rv_html && |M|. WHEN zif_abapgit_definitions=>c_state-added. "Added new rv_html = rv_html && |A|. WHEN zif_abapgit_definitions=>c_state-mixed. "Multiple changes (multifile) rv_html = rv_html && ||. WHEN zif_abapgit_definitions=>c_state-deleted. "Deleted rv_html = rv_html && |D|. ENDCASE. ENDDO. rv_html = rv_html && ''. ENDMETHOD. METHOD render_js_error_banner. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
    ' ). ri_html->add( |{ ri_html->icon( 'exclamation-triangle/red' ) }| && ' If this does not disappear soon,' && ' then there is a JS init error, please log an issue' ). ri_html->add( '
    ' ). ENDMETHOD. METHOD render_label_list. DATA lt_fragments TYPE string_table. DATA lv_l TYPE string. DATA lv_class TYPE string. DATA lv_class_cmd TYPE string. DATA lv_style TYPE string. DATA ls_parsed_color TYPE zcl_abapgit_repo_labels=>ty_color. DATA li_html TYPE REF TO zif_abapgit_html. IF it_labels IS INITIAL. RETURN. ENDIF. lv_class_cmd = 'command'. IF iv_unlisted = abap_true. lv_class_cmd = lv_class_cmd && ' unlisted'. ENDIF. li_html = zcl_abapgit_html=>create( ). APPEND `
      ` TO lt_fragments. LOOP AT it_labels INTO lv_l WHERE table_line IS NOT INITIAL. CLEAR lv_class. CLEAR lv_style. ls_parsed_color = zcl_abapgit_repo_labels=>parse_color( io_label_colors->get( lv_l ) ). IF ls_parsed_color-cls IS NOT INITIAL. lv_class = | class="rl-{ ls_parsed_color-cls }"|. ELSEIF ls_parsed_color-fg IS NOT INITIAL OR ls_parsed_color-bg IS NOT INITIAL. lv_style = ` style="`. IF ls_parsed_color-fg IS NOT INITIAL. lv_style = lv_style && |color:#{ ls_parsed_color-fg };|. ENDIF. IF ls_parsed_color-bg IS NOT INITIAL. lv_style = lv_style && |background-color:#{ ls_parsed_color-bg };|. IF ls_parsed_color-border IS INITIAL. lv_style = lv_style && |border-color:#{ ls_parsed_color-bg };|. ELSE. lv_style = lv_style && |border-color:#{ ls_parsed_color-border };|. ENDIF. ENDIF. lv_style = lv_style && `"`. ENDIF. IF iv_clickable_action IS NOT INITIAL. lv_l = li_html->a( iv_txt = lv_l iv_act = |{ iv_clickable_action }| iv_class = lv_class_cmd iv_query = lv_l ). ENDIF. lv_l = |{ lv_l }|. APPEND lv_l TO lt_fragments. ENDLOOP. APPEND `
    ` TO lt_fragments. rv_html = concat_lines_of( lt_fragments ). ENDMETHOD. METHOD render_news. DATA: lv_text TYPE string, lv_hint TYPE string, lv_ul TYPE abap_bool, lt_log TYPE zcl_abapgit_repo_news=>ty_logs. FIELD-SYMBOLS: LIKE LINE OF lt_log. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF io_news IS NOT BOUND OR io_news->has_news( ) = abap_false. RETURN. ENDIF. lt_log = io_news->get_log( ). " Render news LOOP AT lt_log ASSIGNING . IF -is_header = abap_true. IF -pos_to_cur > 0. lv_text = -text && 'update'. ELSEIF -pos_to_cur = 0. lv_text = -text && 'current'. ELSE. " < 0 lv_text = -text. ENDIF. IF lv_ul = abap_true. ri_html->add( || ). ENDIF. ri_html->add( |

    { lv_text }

    | ). ri_html->add( |
      | ). lv_ul = abap_true. ELSE. -text = escape( val = -text format = cl_abap_format=>e_html_text ). ri_html->add( |
    • { -text }
    • | ). ENDIF. ENDLOOP. IF lv_ul = abap_true. ri_html->add( |
    | ). ENDIF. " Wrap IF io_news->has_important( ) = abap_true. lv_hint = 'Please note changes marked with "!"'. ENDIF. ri_html = render_infopanel( iv_div_id = 'news' iv_title = 'Announcement of the latest changes' iv_hint = lv_hint iv_hide = boolc( io_news->has_unseen( ) = abap_false ) io_content = ri_html ). ENDMETHOD. METHOD render_package_name. DATA: lv_obj_name TYPE tadir-obj_name, lv_jump TYPE string, lv_title TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF iv_package IS INITIAL. RETURN. ENDIF. IF iv_suppress_title = abap_false. lv_title = zcl_abapgit_factory=>get_sap_package( iv_package )->read_description( ). ENDIF. lv_obj_name = iv_package. lv_jump = zcl_abapgit_html_action_utils=>jump_encode( iv_obj_type = 'DEVC' iv_obj_name = lv_obj_name ). ri_html->add( || ). ri_html->add_icon( iv_name = 'box/grey70' iv_hint = 'SAP package' ). IF iv_interactive = abap_true. ri_html->add_a( iv_act = |{ zif_abapgit_definitions=>c_action-jump }?{ lv_jump }| iv_title = lv_title iv_txt = |{ iv_package }| ). ELSE. ri_html->add( iv_package ). ENDIF. ri_html->add( '' ). ENDMETHOD. METHOD render_path. DATA: lv_path TYPE string, lv_jump TYPE string, lv_folder TYPE string, lt_folders TYPE STANDARD TABLE OF string WITH DEFAULT KEY. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF iv_path IS INITIAL. RETURN. ENDIF. lv_jump = |{ zcl_abapgit_gui_page_repo_view=>c_actions-change_dir }?PATH=|. ri_html->add( || ). IF iv_interactive = abap_true. SPLIT iv_path AT '/' INTO TABLE lt_folders. LOOP AT lt_folders INTO lv_folder. IF lv_folder IS INITIAL. " root lv_path = '/'. ELSEIF sy-tabix < lines( lt_folders ). lv_path = lv_path && lv_folder && '/'. ri_html->add_a( iv_act = lv_jump && lv_path iv_txt = lv_folder ). ELSE. " no link for current folder ri_html->add( | { lv_folder } | ). ENDIF. ri_html->add( '/' ). ENDLOOP. ELSE. ri_html->add( iv_path ). ENDIF. ri_html->add( '' ). ENDMETHOD. METHOD render_repo_palette. DATA lt_repo_obj_list TYPE zif_abapgit_repo_srv=>ty_repo_list. DATA lt_repo_list TYPE zif_abapgit_persistence=>ty_repos. DATA lv_repo_json TYPE string. DATA lv_size TYPE i. DATA ls_repo_data LIKE LINE OF lt_repo_list. FIELD-SYMBOLS: LIKE LINE OF lt_repo_list, LIKE LINE OF lt_repo_obj_list. lt_repo_obj_list = zcl_abapgit_repo_srv=>get_instance( )->list( ). LOOP AT lt_repo_obj_list ASSIGNING . ls_repo_data = ->ms_data. ls_repo_data-local_settings-display_name = ->get_name( ). APPEND ls_repo_data TO lt_repo_list. ENDLOOP. lv_size = lines( lt_repo_list ). SORT lt_repo_list BY local_settings-display_name AS TEXT. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( 'var repoCatalog = [' ). " Maybe separate this into another method if needed in more places LOOP AT lt_repo_list ASSIGNING . lv_repo_json = |\{ key: "{ -key }", isOffline: "{ -offline }", displayName: "{ escape( val = -local_settings-display_name format = cl_abap_format=>e_html_js ) }" \}|. IF sy-tabix < lv_size. lv_repo_json = lv_repo_json && ','. ENDIF. ri_html->add( lv_repo_json ). ENDLOOP. ri_html->add( '];' ). ri_html->add( |var gGoRepoPalette = new CommandPalette(createRepoCatalogEnumerator(repoCatalog, "{ iv_action }"), \{| ). ri_html->add( ' toggleKey: "F2",' ). ri_html->add( ' hotkeyDescription: "Go to Repository ..."' ). ri_html->add( '});' ). ENDMETHOD. METHOD render_repo_top. DATA: lo_repo_online TYPE REF TO zcl_abapgit_repo_online, lo_pback TYPE REF TO zcl_abapgit_persist_background, lx_error TYPE REF TO zcx_abapgit_exception, lv_hint TYPE string, lv_icon TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. CREATE OBJECT lo_pback. IF io_repo->is_offline( ) = abap_true. lv_icon = 'plug/darkgrey'. lv_hint = 'Offline Repository'. ELSE. lv_icon = 'cloud-upload-alt/blue'. lv_hint = 'On-line Repository'. ENDIF. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '
    ' ). " Repo type and name ri_html->add_icon( iv_name = lv_icon iv_hint = lv_hint ). ri_html->add( |{ io_repo->get_name( ) }| ). IF io_repo->is_offline( ) = abap_false. lo_repo_online ?= io_repo. ri_html->add( render_repo_url( lo_repo_online->get_url( ) ) ). ENDIF. IF iv_show_edit = abap_true. ri_html->add_a( iv_txt = ri_html->icon( iv_name = 'edit-solid' iv_class = 'pad-sides' iv_hint = 'Change Remote' ) iv_act = |{ zif_abapgit_definitions=>c_action-repo_remote_settings }?| && |key={ io_repo->get_key( ) }| iv_class = |url| ). ENDIF. IF io_repo->is_offline( ) = abap_false. lo_repo_online ?= io_repo. ri_html->add_a( iv_txt = ri_html->icon( iv_name = 'copy-solid' iv_class = 'pad-sides' iv_hint = 'Copy URL to Clipboard' ) iv_act = |{ zif_abapgit_definitions=>c_action-clipboard }| && |?clipboard={ lo_repo_online->get_url( ) }| iv_class = |url| ). ENDIF. IF io_repo->is_offline( ) = abap_false AND iv_show_commit = abap_true. TRY. render_repo_top_commit_hash( ii_html = ri_html io_repo_online = lo_repo_online ). CATCH zcx_abapgit_exception INTO lx_error. " In case of missing or wrong credentials, show message in status bar lv_hint = lx_error->get_text( ). IF lv_hint CS 'credentials'. MESSAGE lv_hint TYPE 'S' DISPLAY LIKE 'E'. ENDIF. ENDTRY. ENDIF. " News IF io_news IS BOUND AND io_news->has_news( ) = abap_true. IF io_news->has_updates( ) = abap_true. lv_icon = 'arrow-circle-up/warning'. ELSE. lv_icon = 'arrow-circle-up'. ENDIF. ri_html->add_a( iv_act = |toggleDisplay('news')| iv_typ = zif_abapgit_html=>c_action_type-onclick iv_txt = ri_html->icon( iv_name = lv_icon iv_class = 'pad-sides' iv_hint = 'Display Changelog' ) iv_class = |url| ). ENDIF. ri_html->add( '' ). " Fav IF abap_true = zcl_abapgit_persistence_user=>get_instance( )->is_favorite_repo( io_repo->get_key( ) ). lv_icon = 'star/blue'. ELSE. lv_icon = 'star/grey'. ENDIF. ri_html->add_a( iv_act = |{ zif_abapgit_definitions=>c_action-repo_toggle_fav }?key={ io_repo->get_key( ) }| iv_txt = ri_html->icon( iv_name = lv_icon iv_class = 'pad-sides' iv_hint = 'Toggle Favorite' ) ). " BG IF lo_pback->exists( io_repo->get_key( ) ) = abap_true. ri_html->add( 'BG' ). ENDIF. " Write protect IF io_repo->get_local_settings( )-write_protected = abap_true. ri_html->add_icon( iv_name = 'lock/grey70' iv_hint = 'Locked from Pulls' ). ENDIF. IF io_repo->get_local_settings( )-flow = abap_true. ri_html->add_icon( iv_name = 'flow/grey70' iv_hint = 'Flow' ). ENDIF. " Branch IF io_repo->is_offline( ) = abap_false. lo_repo_online ?= io_repo. IF iv_show_branch = abap_true. ri_html->add( render_branch_name( io_repo = lo_repo_online iv_interactive = iv_interactive_branch ) ). ENDIF. ENDIF. " Package IF iv_show_package = abap_true. ri_html->add( render_package_name( io_repo->get_package( ) ) ). ENDIF. ri_html->add( '
    ' ). ENDMETHOD. METHOD render_repo_top_commit_hash. DATA: lv_commit_hash TYPE zif_abapgit_git_definitions=>ty_sha1, lv_commit_short_hash TYPE zif_abapgit_git_definitions=>ty_sha1, lv_display_url TYPE zif_abapgit_persistence=>ty_repo-url, lo_url TYPE REF TO zcl_abapgit_git_url, lv_icon_commit TYPE string. lv_commit_hash = io_repo_online->get_current_remote( ). lv_commit_short_hash = lv_commit_hash(7). lv_icon_commit = ii_html->icon( iv_name = 'code-commit' iv_class = 'pad-sides' iv_hint = 'Commit' ). CREATE OBJECT lo_url. TRY. lv_display_url = lo_url->get_commit_display_url( io_repo_online ). ii_html->add_a( iv_txt = |{ lv_icon_commit }{ lv_commit_short_hash }| iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ lv_display_url }| iv_title = 'Commit' iv_class = |url| ). CATCH zcx_abapgit_exception. ii_html->add( |{ lv_icon_commit }{ lv_commit_short_hash }| ). ENDTRY. ENDMETHOD. METHOD render_repo_url. ri_html = zcl_abapgit_html=>create( )->add_a( iv_txt = shorten_repo_url( iv_url ) iv_title = iv_url iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ iv_url }| iv_class = 'url' ). IF iv_render_remote_edit_for_key IS NOT INITIAL. ri_html->add_a( iv_txt = ri_html->icon( iv_name = 'edit-solid' iv_class = 'pad-sides' iv_hint = 'Change remote' ) iv_act = |{ zif_abapgit_definitions=>c_action-repo_remote_settings }?key={ iv_render_remote_edit_for_key }| iv_class = |remote_repo| ). ENDIF. ENDMETHOD. METHOD render_sci_result. DATA lv_icon TYPE string. lv_icon = ii_html->icon( iv_name = 'bug-solid' iv_hint = 'Code inspector result' ). CASE iv_sci_result. WHEN zif_abapgit_definitions=>c_sci_result-passed. ii_html->add( |{ lv_icon }PASSED| ). WHEN zif_abapgit_definitions=>c_sci_result-failed. ii_html->add( |{ lv_icon }FAILED| ). WHEN zif_abapgit_definitions=>c_sci_result-warning. ii_html->add( |{ lv_icon }WARN| ). WHEN OTHERS. " Including NO_RUN RETURN. ENDCASE. ENDMETHOD. METHOD render_success. ri_html = zcl_abapgit_html=>create( ). ri_html->add( '
    ' ). ri_html->add_icon( 'check' ). ri_html->add( iv_message ). ri_html->add( '
    ' ). ENDMETHOD. METHOD render_table_footer. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( iv_message ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ENDMETHOD. METHOD render_table_header. DATA: lv_tmp TYPE string, lv_disp_name TYPE string. FIELD-SYMBOLS LIKE LINE OF it_col_spec. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( '' ). LOOP AT it_col_spec ASSIGNING . " e.g. Created at [{ gv_time_zone }] lv_tmp = '-css_class IS NOT INITIAL. lv_tmp = lv_tmp && | class="{ -css_class }"|. ENDIF. lv_tmp = lv_tmp && '>'. IF -display_name IS NOT INITIAL. lv_disp_name = -display_name. IF -add_tz = abap_true. lv_disp_name = lv_disp_name && | [{ gv_time_zone }]|. ENDIF. IF -tech_name = iv_order_by. IF iv_order_descending = abap_true. lv_tmp = lv_tmp && ri_html->a( iv_txt = lv_disp_name iv_act = |{ zif_abapgit_definitions=>c_action-change_order_by }| iv_title = -title ). ELSE. lv_tmp = lv_tmp && ri_html->a( iv_txt = lv_disp_name iv_act = |{ zif_abapgit_definitions=>c_action-direction }?direction=DESCENDING| iv_title = -title ). ENDIF. ELSEIF -allow_order_by = abap_true. lv_tmp = lv_tmp && ri_html->a( iv_txt = lv_disp_name iv_act = |{ zif_abapgit_definitions=>c_action-change_order_by }?orderBy={ -tech_name }| iv_title = -title ). ELSE. lv_tmp = lv_tmp && lv_disp_name. ENDIF. ENDIF. IF -tech_name = iv_order_by AND iv_order_by IS NOT INITIAL. IF iv_order_descending = abap_true. lv_tmp = lv_tmp && | ▾|. " arrow down ELSE. lv_tmp = lv_tmp && | ▴|. " arrow up ENDIF. ENDIF. lv_tmp = lv_tmp && ''. ri_html->add( lv_tmp ). ENDLOOP. ri_html->add( '' ). ri_html->add( '' ). ENDMETHOD. METHOD render_text_input. DATA lv_attrs TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF iv_value IS NOT INITIAL. lv_attrs = | value="{ iv_value }"|. ENDIF. IF iv_max_length IS NOT INITIAL. lv_attrs = lv_attrs && | maxlength="{ iv_max_length }"|. ENDIF. IF iv_autofocus = abap_true. lv_attrs = lv_attrs && | autofocus|. ENDIF. ri_html->add( || ). ri_html->add( || ). ENDMETHOD. METHOD render_timestamp. DATA lv_date TYPE d. DATA lv_time TYPE t. CONVERT TIME STAMP iv_timestamp TIME ZONE gv_time_zone INTO DATE lv_date TIME lv_time. rv_rendered = |{ lv_date DATE = USER } { lv_time TIME = USER }|. ENDMETHOD. METHOD render_transport. DATA: lv_title TYPE string, lv_jump TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF iv_transport IS INITIAL. RETURN. ENDIF. lv_title = zcl_abapgit_factory=>get_cts_api( )->read_description( iv_transport ). lv_jump = |{ zif_abapgit_definitions=>c_action-jump_transport }?transport={ iv_transport }|. IF iv_icon_only = abap_true. ri_html->add_a( iv_act = lv_jump iv_title = |Transport { iv_transport }| iv_txt = zcl_abapgit_html=>icon( 'truck-solid/darkgrey' ) ). ELSE. ri_html->add( || ). ri_html->add_icon( iv_name = 'truck-solid/grey70' iv_hint = 'Transport' ). IF iv_interactive = abap_true. ri_html->add_a( iv_act = lv_jump iv_title = lv_title iv_txt = |{ iv_transport }| ). ELSE. ri_html->add( iv_transport ). ENDIF. ri_html->add( '' ). ENDIF. ENDMETHOD. METHOD render_user_name. DATA: lv_title TYPE string, lv_jump TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. IF iv_username IS INITIAL. RETURN. ENDIF. IF iv_username <> zcl_abapgit_objects_super=>c_user_unknown AND iv_suppress_title = abap_false. lv_title = zcl_abapgit_user_record=>get_title( iv_username ). ENDIF. lv_jump = |{ zif_abapgit_definitions=>c_action-jump_user }?user={ iv_username }|. IF iv_icon_only = abap_true. ri_html->add_a( iv_act = lv_jump iv_title = lv_title iv_txt = zcl_abapgit_html=>icon( 'user-solid/darkgrey' ) ). ELSE. ri_html->add( || ). ri_html->add_icon( iv_name = 'user-solid/grey70' iv_hint = 'User name' ). IF iv_interactive = abap_true AND iv_username <> zcl_abapgit_objects_super=>c_user_unknown. ri_html->add_a( iv_act = lv_jump iv_title = lv_title iv_txt = |{ iv_username }| ). ELSE. ri_html->add( iv_username ). ENDIF. ri_html->add( '' ). ENDIF. ENDMETHOD. METHOD render_warning_banner. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
    ' ). ri_html->add( |{ ri_html->icon( 'exclamation-triangle/yellow' ) } { iv_text }| ). ri_html->add( '
    ' ). ENDMETHOD. METHOD shorten_repo_url. DATA lv_new_length TYPE i. DATA lv_length_to_truncate_to TYPE i. rv_shortened = iv_full_url. REPLACE FIRST OCCURRENCE OF 'https://' IN rv_shortened WITH ''. REPLACE FIRST OCCURRENCE OF 'http://' IN rv_shortened WITH ''. IF rv_shortened CP '*.git'. lv_new_length = strlen( rv_shortened ) - 4. rv_shortened = rv_shortened(lv_new_length). ENDIF. IF strlen( rv_shortened ) > iv_max_length. lv_length_to_truncate_to = iv_max_length - 3. rv_shortened = rv_shortened(lv_length_to_truncate_to) && `...`. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_buttons IMPLEMENTATION. METHOD advanced. rv_html_string = zcl_abapgit_html=>icon( iv_name = 'tools-solid' iv_hint = 'Utilities' ). ENDMETHOD. METHOD experimental. rv_html_string = zcl_abapgit_html=>icon( iv_name = 'vial-solid/red' iv_hint = 'Experimental Features are Enabled' ). ENDMETHOD. METHOD help. rv_html_string = zcl_abapgit_html=>icon( iv_name = 'question-circle-solid' iv_hint = 'Help' ). ENDMETHOD. METHOD new_offline. rv_html_string = zcl_abapgit_html=>icon( 'plug' ) && ' New Offline'. ENDMETHOD. METHOD new_online. rv_html_string = zcl_abapgit_html=>icon( 'cloud-upload-alt' ) && ' New Online'. ENDMETHOD. METHOD flow. rv_html_string = zcl_abapgit_html=>icon( 'flow' ) && ' Flow'. ENDMETHOD. METHOD repo_list. rv_html_string = zcl_abapgit_html=>icon( 'bars' ) && ' Repository List'. ENDMETHOD. METHOD settings. rv_html_string = zcl_abapgit_html=>icon( 'cog' ) && ' Global Settings'. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_exception_viewer IMPLEMENTATION. METHOD add_row. DATA: lo_row TYPE REF TO cl_salv_form_layout_flow. lo_row = io_grid->add_row( ). lo_row->create_label( position = 1 text = iv_col_1 ). lo_row->create_label( position = 2 text = iv_col_2 ). ENDMETHOD. METHOD build_top_of_list. DATA: lo_grid TYPE REF TO cl_salv_form_layout_grid. CREATE OBJECT lo_grid EXPORTING columns = 2. add_row( io_grid = lo_grid iv_col_1 = 'Main program:' iv_col_2 = is_top_of_stack-mainprogram ). add_row( io_grid = lo_grid iv_col_1 = 'Include name:' iv_col_2 = is_top_of_stack-include ). add_row( io_grid = lo_grid iv_col_1 = 'Source line' iv_col_2 = |{ is_top_of_stack-line }| ). ro_form = lo_grid. ENDMETHOD. METHOD constructor. mx_error = ix_error. mt_callstack = mx_error->mt_callstack. ENDMETHOD. METHOD extract_classname. rv_classname = substring_before( val = iv_mainprogram regex = '=*CP$' ). ENDMETHOD. METHOD get_top_of_callstack. READ TABLE mt_callstack INDEX 1 INTO rs_top_of_callstack. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Callstack is empty| ). ENDIF. ENDMETHOD. METHOD goto_message. DATA: lt_bdcdata TYPE STANDARD TABLE OF bdcdata, ls_bdcdata LIKE LINE OF lt_bdcdata. ls_bdcdata-program = 'SAPLWBMESSAGES'. ls_bdcdata-dynpro = '0100'. ls_bdcdata-dynbegin = abap_true. INSERT ls_bdcdata INTO TABLE lt_bdcdata. CLEAR: ls_bdcdata. ls_bdcdata-fnam = 'RSDAG-ARBGB'. ls_bdcdata-fval = mx_error->if_t100_message~t100key-msgid. INSERT ls_bdcdata INTO TABLE lt_bdcdata. CLEAR: ls_bdcdata. ls_bdcdata-fnam = 'MSG_NUMMER'. ls_bdcdata-fval = mx_error->if_t100_message~t100key-msgno. INSERT ls_bdcdata INTO TABLE lt_bdcdata. CLEAR: ls_bdcdata. ls_bdcdata-fnam = 'RSDAG-MSGFLAG'. ls_bdcdata-fval = 'X'. INSERT ls_bdcdata INTO TABLE lt_bdcdata. CLEAR: ls_bdcdata. ls_bdcdata-fnam = 'BDC_OKCODE'. ls_bdcdata-fval = '=WB_DISPLAY'. INSERT ls_bdcdata INTO TABLE lt_bdcdata. CALL FUNCTION 'ABAP4_CALL_TRANSACTION' STARTING NEW TASK 'GIT' EXPORTING tcode = 'SE91' mode_val = 'E' TABLES using_tab = lt_bdcdata EXCEPTIONS call_transaction_denied = 1 tcode_invalid = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD goto_source. goto_source_code( get_top_of_callstack( ) ). ENDMETHOD. METHOD goto_source_code. CONSTANTS: BEGIN OF lc_obj_type, class TYPE trobjtype VALUE `CLAS`, program TYPE trobjtype VALUE `PROG`, END OF lc_obj_type. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, ls_sub_item TYPE zif_abapgit_definitions=>ty_item, lv_classname LIKE ls_item-obj_name. " you should remember that we distinct two cases " 1) we navigate to a global class " 2) we navigate to a program " the latter one is the default case lv_classname = extract_classname( is_callstack-mainprogram ). IF lv_classname IS NOT INITIAL. ls_item-obj_name = lv_classname. ls_item-obj_type = lc_obj_type-class. ELSE. ls_item-obj_name = is_callstack-mainprogram. ls_item-obj_type = lc_obj_type-program. ENDIF. ls_sub_item-obj_name = is_callstack-include. ls_sub_item-obj_type = lc_obj_type-program. zcl_abapgit_objects=>jump( is_item = ls_item is_sub_item = ls_sub_item iv_line_number = is_callstack-line ). ENDMETHOD. METHOD on_double_click. DATA: lx_error TYPE REF TO zcx_abapgit_exception. FIELD-SYMBOLS: TYPE abap_callstack_line. READ TABLE mt_callstack ASSIGNING INDEX row. IF sy-subrc <> 0. RETURN. ENDIF. TRY. goto_source_code( ). CATCH zcx_abapgit_exception INTO lx_error. MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. ENDMETHOD. METHOD set_text. DATA: lo_column TYPE REF TO cl_salv_column, lv_short_text TYPE scrtext_s, lv_medium_text TYPE scrtext_m, lv_long_text TYPE scrtext_l. lo_column = io_columns->get_column( iv_column ). lv_short_text = iv_text. lv_medium_text = iv_text. lv_long_text = iv_text. lo_column->set_short_text( lv_short_text ). lo_column->set_medium_text( lv_medium_text ). lo_column->set_long_text( lv_long_text ). ENDMETHOD. METHOD show_callstack. DATA: lx_error TYPE REF TO cx_static_check, lo_event TYPE REF TO cl_salv_events_table, lo_columns TYPE REF TO cl_salv_columns_table, lo_alv TYPE REF TO cl_salv_table. DATA ls_position TYPE zif_abapgit_popups=>ty_popup_position. TRY. cl_salv_table=>factory( IMPORTING r_salv_table = lo_alv CHANGING t_table = mt_callstack ). lo_alv->get_columns( )->set_optimize( ). lo_alv->set_top_of_list( build_top_of_list( get_top_of_callstack( ) ) ). ls_position = zcl_abapgit_popups=>center( iv_width = 150 iv_height = 25 ). lo_alv->set_screen_popup( start_column = ls_position-start_column end_column = ls_position-end_column start_line = ls_position-start_row end_line = ls_position-end_row ). lo_event = lo_alv->get_event( ). lo_columns = lo_alv->get_columns( ). set_text( io_columns = lo_columns iv_column = |LINE| iv_text = |Line| ). set_text( io_columns = lo_columns iv_column = |LINE| iv_text = |Line| ). set_text( io_columns = lo_columns iv_column = |BLOCKTYPE| iv_text = |Event Type| ). set_text( io_columns = lo_columns iv_column = |BLOCKNAME| iv_text = |Event| ). set_text( io_columns = lo_columns iv_column = |FLAG_SYSTEM| iv_text = |System| ). SET HANDLER on_double_click FOR lo_event. lo_alv->display( ). CATCH cx_static_check INTO lx_error. MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. ENDMETHOD. ENDCLASS. CLASS kHGwlHbtMQYaNXTWgQdwprsTTRQzio DEFINITION DEFERRED. CLASS kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn DEFINITION DEFERRED. CLASS kHGwlHbtMQYaNXTWgQdwhPIfZcUzJG DEFINITION DEFERRED. *"* use this source file for the definition and implementation of *"* local helper classes, interface definitions and type *"* declarations * renamed: zcl_abapgit_gui_page_flow :: lcl_sha1_stack CLASS kHGwlHbtMQYaNXTWgQdwhPIfZcUzJG DEFINITION. PUBLIC SECTION. METHODS clear RETURNING VALUE(ro_stack) TYPE REF TO kHGwlHbtMQYaNXTWgQdwhPIfZcUzJG. METHODS push IMPORTING iv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1. METHODS pop RETURNING VALUE(rv_sha1) TYPE zif_abapgit_git_definitions=>ty_sha1. METHODS size RETURNING VALUE(rv_size) TYPE i. PRIVATE SECTION. DATA mt_list TYPE STANDARD TABLE OF zif_abapgit_git_definitions=>ty_sha1 WITH DEFAULT KEY. ENDCLASS. CLASS kHGwlHbtMQYaNXTWgQdwhPIfZcUzJG IMPLEMENTATION. METHOD clear. CLEAR mt_list. ro_stack = me. ENDMETHOD. METHOD push. INSERT iv_sha1 INTO mt_list INDEX 1. ENDMETHOD. METHOD pop. READ TABLE mt_list INDEX 1 INTO rv_sha1. ASSERT sy-subrc = 0. DELETE mt_list INDEX 1. ENDMETHOD. METHOD size. rv_size = lines( mt_list ). ENDMETHOD. ENDCLASS. *************************************************** * renamed: zcl_abapgit_gui_page_flow :: lcl_filter CLASS kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn DEFINITION FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_object_filter. METHODS constructor IMPORTING it_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. PRIVATE SECTION. DATA mt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. ENDCLASS. CLASS kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn IMPLEMENTATION. METHOD constructor. mt_filter = it_filter. ENDMETHOD. METHOD zif_abapgit_object_filter~get_filter. rt_filter = mt_filter. ENDMETHOD. ENDCLASS. *************************************************** * renamed: zcl_abapgit_gui_page_flow :: lcl_helper CLASS kHGwlHbtMQYaNXTWgQdwprsTTRQzio DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS get_information RETURNING VALUE(rt_features) TYPE zif_abapgit_gui_page_flow=>ty_features RAISING zcx_abapgit_exception. PRIVATE SECTION. CONSTANTS c_main TYPE string VALUE 'main'. TYPES: BEGIN OF ty_transport, trkorr TYPE trkorr, title TYPE string, object TYPE e071-object, obj_name TYPE e071-obj_name, devclass TYPE tadir-devclass, END OF ty_transport. TYPES ty_transports_tt TYPE STANDARD TABLE OF ty_transport WITH DEFAULT KEY. CLASS-METHODS build_repo_data IMPORTING io_online TYPE REF TO zif_abapgit_repo RETURNING VALUE(rs_data) TYPE zif_abapgit_gui_page_flow=>ty_feature-repo. CLASS-METHODS map_files_to_objects IMPORTING it_files TYPE zif_abapgit_gui_page_flow=>ty_path_name_tt io_online TYPE REF TO zcl_abapgit_repo_online RETURNING VALUE(rt_changed_objects) TYPE zif_abapgit_definitions=>ty_items_ts RAISING zcx_abapgit_exception. CLASS-METHODS find_changed_files_all IMPORTING io_online TYPE REF TO zcl_abapgit_repo_online it_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt EXPORTING et_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt CHANGING ct_features TYPE zif_abapgit_gui_page_flow=>ty_features RAISING zcx_abapgit_exception. CLASS-METHODS try_matching_transports IMPORTING ii_repo TYPE REF TO zif_abapgit_repo it_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt CHANGING ct_features TYPE zif_abapgit_gui_page_flow=>ty_features ct_transports TYPE ty_transports_tt RAISING zcx_abapgit_exception. CLASS-METHODS add_objects_and_files_from_tr IMPORTING iv_trkorr TYPE trkorr ii_repo TYPE REF TO zif_abapgit_repo it_transports TYPE ty_transports_tt it_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt CHANGING cs_feature TYPE zif_abapgit_gui_page_flow=>ty_feature RAISING zcx_abapgit_exception. CLASS-METHODS find_up_to_date IMPORTING iv_url TYPE string it_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt CHANGING ct_features TYPE zif_abapgit_gui_page_flow=>ty_features RAISING zcx_abapgit_exception. CLASS-METHODS find_prs IMPORTING iv_url TYPE string CHANGING ct_features TYPE zif_abapgit_gui_page_flow=>ty_features RAISING zcx_abapgit_exception. CLASS-METHODS add_local_status IMPORTING io_online TYPE REF TO zcl_abapgit_repo_online CHANGING ct_features TYPE zif_abapgit_gui_page_flow=>ty_features RAISING zcx_abapgit_exception. CLASS-METHODS find_open_transports RETURNING VALUE(rt_transports) TYPE ty_transports_tt RAISING zcx_abapgit_exception. CLASS-METHODS find_changed_files IMPORTING it_expanded1 TYPE zif_abapgit_git_definitions=>ty_expanded_tt it_expanded2 TYPE zif_abapgit_git_definitions=>ty_expanded_tt RETURNING VALUE(rt_files) TYPE zif_abapgit_gui_page_flow=>ty_path_name_tt. ENDCLASS. CLASS kHGwlHbtMQYaNXTWgQdwprsTTRQzio IMPLEMENTATION. METHOD find_prs. DATA lt_pulls TYPE zif_abapgit_pr_enum_provider=>ty_pull_requests. DATA ls_pull LIKE LINE OF lt_pulls. FIELD-SYMBOLS LIKE LINE OF ct_features. IF lines( ct_features ) = 0. " only main branch RETURN. ENDIF. lt_pulls = zcl_abapgit_pr_enumerator=>new( iv_url )->get_pulls( ). LOOP AT ct_features ASSIGNING . READ TABLE lt_pulls INTO ls_pull WITH KEY head_branch = -branch-display_name. IF sy-subrc = 0. -pr-title = |{ ls_pull-title } #{ ls_pull-number }|. -pr-url = ls_pull-html_url. -pr-draft = ls_pull-draft. ENDIF. ENDLOOP. ENDMETHOD. METHOD build_repo_data. rs_data-name = io_online->get_name( ). rs_data-key = io_online->get_key( ). rs_data-package = io_online->get_package( ). ENDMETHOD. METHOD get_information. DATA lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. DATA ls_branch LIKE LINE OF lt_branches. DATA ls_result LIKE LINE OF rt_features. DATA lt_favorites TYPE zif_abapgit_repo_srv=>ty_repo_list. DATA li_favorite LIKE LINE OF lt_favorites. DATA lo_online TYPE REF TO zcl_abapgit_repo_online. DATA lt_features LIKE rt_features. DATA lt_transports TYPE ty_transports_tt. DATA lt_main_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt. FIELD-SYMBOLS LIKE LINE OF lt_features. FIELD-SYMBOLS LIKE LINE OF -changed_files. lt_transports = find_open_transports( ). * list branches on favorite + flow enabled + transported repos lt_favorites = zcl_abapgit_repo_srv=>get_instance( )->list_favorites( abap_false ). LOOP AT lt_favorites INTO li_favorite. IF li_favorite->get_local_settings( )-flow = abap_false. CONTINUE. ELSEIF zcl_abapgit_factory=>get_sap_package( li_favorite->get_package( ) )->are_changes_recorded_in_tr_req( ) = abap_false. CONTINUE. ENDIF. lo_online ?= li_favorite. lt_branches = zcl_abapgit_git_factory=>get_v2_porcelain( )->list_branches( iv_url = lo_online->get_url( ) iv_prefix = 'refs/heads/' )->get_all( ). CLEAR lt_features. LOOP AT lt_branches INTO ls_branch WHERE display_name <> c_main. ls_result-repo = build_repo_data( lo_online ). ls_result-branch-display_name = ls_branch-display_name. ls_result-branch-sha1 = ls_branch-sha1. INSERT ls_result INTO TABLE lt_features. ENDLOOP. find_changed_files_all( EXPORTING io_online = lo_online it_branches = lt_branches IMPORTING et_main_expanded = lt_main_expanded CHANGING ct_features = lt_features ). try_matching_transports( EXPORTING ii_repo = li_favorite it_main_expanded = lt_main_expanded CHANGING ct_transports = lt_transports ct_features = lt_features ). find_up_to_date( EXPORTING iv_url = lo_online->get_url( ) it_branches = lt_branches CHANGING ct_features = lt_features ). find_prs( EXPORTING iv_url = lo_online->get_url( ) CHANGING ct_features = lt_features ). add_local_status( EXPORTING io_online = lo_online CHANGING ct_features = lt_features ). LOOP AT lt_features ASSIGNING . -full_match = abap_true. LOOP AT -changed_files ASSIGNING . IF -remote_sha1 <> -local_sha1. -full_match = abap_false. ENDIF. ENDLOOP. ENDLOOP. INSERT LINES OF lt_features INTO TABLE rt_features. ENDLOOP. SORT rt_features BY full_match transport-trkorr DESCENDING. ENDMETHOD. METHOD try_matching_transports. DATA lt_trkorr LIKE ct_transports. DATA ls_trkorr LIKE LINE OF lt_trkorr. DATA ls_result LIKE LINE OF ct_features. DATA lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. DATA lv_package LIKE LINE OF lt_packages. DATA lv_found TYPE abap_bool. FIELD-SYMBOLS LIKE LINE OF ct_features. FIELD-SYMBOLS LIKE LINE OF ct_transports. FIELD-SYMBOLS LIKE LINE OF -changed_objects. SORT ct_transports BY object obj_name. LOOP AT ct_features ASSIGNING . LOOP AT -changed_objects ASSIGNING . READ TABLE ct_transports ASSIGNING WITH KEY object = -obj_type obj_name = -obj_name BINARY SEARCH. IF sy-subrc = 0. -transport-trkorr = -trkorr. -transport-title = -title. add_objects_and_files_from_tr( EXPORTING iv_trkorr = -trkorr ii_repo = ii_repo it_main_expanded = it_main_expanded it_transports = ct_transports CHANGING cs_feature = ). DELETE ct_transports WHERE trkorr = -trkorr. EXIT. ENDIF. ENDLOOP. ENDLOOP. * unmatched transports lt_trkorr = ct_transports. SORT lt_trkorr BY trkorr. DELETE ADJACENT DUPLICATES FROM lt_trkorr COMPARING trkorr. lt_packages = zcl_abapgit_factory=>get_sap_package( ii_repo->get_package( ) )->list_subpackages( ). INSERT ii_repo->get_package( ) INTO TABLE lt_packages. LOOP AT lt_trkorr INTO ls_trkorr. lv_found = abap_false. LOOP AT lt_packages INTO lv_package. READ TABLE ct_transports ASSIGNING WITH KEY trkorr = ls_trkorr-trkorr devclass = lv_package. IF sy-subrc = 0. lv_found = abap_true. ENDIF. ENDLOOP. IF lv_found = abap_false. CONTINUE. ENDIF. CLEAR ls_result. ls_result-repo = build_repo_data( ii_repo ). ls_result-transport-trkorr = -trkorr. ls_result-transport-title = -title. add_objects_and_files_from_tr( EXPORTING iv_trkorr = ls_trkorr-trkorr ii_repo = ii_repo it_main_expanded = it_main_expanded it_transports = ct_transports CHANGING cs_feature = ls_result ). INSERT ls_result INTO TABLE ct_features. ENDLOOP. ENDMETHOD. METHOD add_objects_and_files_from_tr. DATA ls_changed LIKE LINE OF cs_feature-changed_objects. DATA lo_filter TYPE REF TO kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn. DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. DATA lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. DATA ls_changed_file LIKE LINE OF cs_feature-changed_files. FIELD-SYMBOLS LIKE LINE OF it_transports. FIELD-SYMBOLS LIKE LINE OF lt_local. FIELD-SYMBOLS LIKE LINE OF lt_filter. FIELD-SYMBOLS LIKE LINE OF it_main_expanded. LOOP AT it_transports ASSIGNING WHERE trkorr = iv_trkorr. ls_changed-obj_type = -object. ls_changed-obj_name = -obj_name. INSERT ls_changed INTO TABLE cs_feature-changed_objects. APPEND INITIAL LINE TO lt_filter ASSIGNING . -object = -object. -obj_name = -obj_name. ENDLOOP. CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. lt_local = ii_repo->get_files_local_filtered( lo_filter ). LOOP AT lt_local ASSIGNING WHERE file-filename <> zif_abapgit_definitions=>c_dot_abapgit. ls_changed_file-path = -file-path. ls_changed_file-filename = -file-filename. ls_changed_file-local_sha1 = -file-sha1. READ TABLE it_main_expanded ASSIGNING WITH TABLE KEY path_name COMPONENTS path = ls_changed_file-path name = ls_changed_file-filename. IF sy-subrc = 0. ls_changed_file-remote_sha1 = -sha1. ENDIF. INSERT ls_changed_file INTO TABLE cs_feature-changed_files. ENDLOOP. ENDMETHOD. METHOD find_open_transports. DATA lt_trkorr TYPE zif_abapgit_cts_api=>ty_trkorr_tt. DATA lv_trkorr LIKE LINE OF lt_trkorr. DATA ls_result LIKE LINE OF rt_transports. DATA lt_objects TYPE zif_abapgit_cts_api=>ty_transport_obj_tt. DATA lv_obj_name TYPE tadir-obj_name. FIELD-SYMBOLS LIKE LINE OF lt_objects. lt_trkorr = zcl_abapgit_factory=>get_cts_api( )->list_open_requests_by_user( ). LOOP AT lt_trkorr INTO lv_trkorr. ls_result-trkorr = lv_trkorr. ls_result-title = zcl_abapgit_factory=>get_cts_api( )->read_description( lv_trkorr ). lt_objects = zcl_abapgit_factory=>get_cts_api( )->list_r3tr_by_request( lv_trkorr ). LOOP AT lt_objects ASSIGNING . ls_result-object = -object. ls_result-obj_name = -obj_name. lv_obj_name = -obj_name. ls_result-devclass = zcl_abapgit_factory=>get_tadir( )->read_single( iv_object = ls_result-object iv_obj_name = lv_obj_name )-devclass. INSERT ls_result INTO TABLE rt_transports. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD find_up_to_date. DATA ls_branch LIKE LINE OF it_branches. DATA lt_commits TYPE zif_abapgit_definitions=>ty_objects_tt. DATA ls_main LIKE LINE OF it_branches. DATA lv_current TYPE zif_abapgit_git_definitions=>ty_sha1. DATA lt_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt. DATA lo_visit TYPE REF TO kHGwlHbtMQYaNXTWgQdwhPIfZcUzJG. DATA ls_raw TYPE zcl_abapgit_git_pack=>ty_commit. DATA lt_main_reachable TYPE HASHED TABLE OF zif_abapgit_git_definitions=>ty_sha1 WITH UNIQUE KEY table_line. FIELD-SYMBOLS LIKE LINE OF ct_features. FIELD-SYMBOLS LIKE LINE OF lt_commits. IF lines( it_branches ) = 1. " only main branch RETURN. ENDIF. READ TABLE it_branches INTO ls_main WITH KEY display_name = c_main. ASSERT sy-subrc = 0. LOOP AT it_branches INTO ls_branch WHERE is_head = abap_false. APPEND ls_branch-sha1 TO lt_sha1. ENDLOOP. lt_commits = zcl_abapgit_git_factory=>get_v2_porcelain( )->commits_last_year( iv_url = iv_url it_sha1 = lt_sha1 ). CREATE OBJECT lo_visit. lo_visit->clear( )->push( ls_main-sha1 ). WHILE lo_visit->size( ) > 0. lv_current = lo_visit->pop( ). INSERT lv_current INTO TABLE lt_main_reachable. READ TABLE lt_commits ASSIGNING WITH TABLE KEY sha COMPONENTS sha1 = lv_current. IF sy-subrc = 0. ls_raw = zcl_abapgit_git_pack=>decode_commit( -data ). lo_visit->push( ls_raw-parent ). IF ls_raw-parent2 IS NOT INITIAL. lo_visit->push( ls_raw-parent2 ). ENDIF. ENDIF. ENDWHILE. LOOP AT ct_features ASSIGNING . -branch-up_to_date = abap_undefined. lo_visit->clear( )->push( -branch-sha1 ). WHILE lo_visit->size( ) > 0. lv_current = lo_visit->pop( ). IF lv_current = ls_main-sha1. -branch-up_to_date = abap_true. EXIT. ENDIF. READ TABLE lt_main_reachable WITH KEY table_line = lv_current TRANSPORTING NO FIELDS. IF sy-subrc = 0. -branch-up_to_date = abap_false. EXIT. ENDIF. READ TABLE lt_commits ASSIGNING WITH TABLE KEY sha COMPONENTS sha1 = lv_current. IF sy-subrc = 0. ls_raw = zcl_abapgit_git_pack=>decode_commit( -data ). lo_visit->push( ls_raw-parent ). IF ls_raw-parent2 IS NOT INITIAL. lo_visit->push( ls_raw-parent2 ). ENDIF. ENDIF. ENDWHILE. ENDLOOP. ENDMETHOD. METHOD find_changed_files_all. DATA ls_branch LIKE LINE OF it_branches. DATA lt_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt. DATA lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. DATA lv_starting_folder TYPE string. DATA ls_main LIKE LINE OF it_branches. DATA lt_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt. FIELD-SYMBOLS LIKE LINE OF ct_features. LOOP AT it_branches INTO ls_branch WHERE is_head = abap_false. APPEND ls_branch-sha1 TO lt_sha1. ENDLOOP. lt_objects = zcl_abapgit_git_factory=>get_v2_porcelain( )->list_no_blobs_multi( iv_url = io_online->get_url( ) it_sha1 = lt_sha1 ). lv_starting_folder = io_online->get_dot_abapgit( )->get_starting_folder( ) && '*'. READ TABLE it_branches INTO ls_main WITH KEY display_name = c_main. ASSERT sy-subrc = 0. et_main_expanded = zcl_abapgit_git_porcelain=>full_tree( it_objects = lt_objects iv_parent = ls_main-sha1 ). DELETE et_main_expanded WHERE path NP lv_starting_folder. LOOP AT ct_features ASSIGNING WHERE branch-display_name <> c_main. lt_expanded = zcl_abapgit_git_porcelain=>full_tree( it_objects = lt_objects iv_parent = -branch-sha1 ). DELETE lt_expanded WHERE path NP lv_starting_folder. -changed_files = find_changed_files( it_expanded1 = lt_expanded it_expanded2 = et_main_expanded ). -changed_objects = map_files_to_objects( io_online = io_online it_files = -changed_files ). ENDLOOP. ENDMETHOD. METHOD add_local_status. DATA lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. DATA lo_filter TYPE REF TO kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn. DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. FIELD-SYMBOLS LIKE LINE OF ct_features. FIELD-SYMBOLS LIKE LINE OF lt_local. FIELD-SYMBOLS TYPE zif_abapgit_gui_page_flow=>ty_path_name. FIELD-SYMBOLS LIKE LINE OF lt_filter. FIELD-SYMBOLS LIKE LINE OF -changed_objects. LOOP AT ct_features ASSIGNING . LOOP AT -changed_objects ASSIGNING . APPEND INITIAL LINE TO lt_filter ASSIGNING . -object = -obj_type. -obj_name = -obj_name. ENDLOOP. ENDLOOP. SORT lt_filter BY object obj_name. DELETE ADJACENT DUPLICATES FROM lt_filter COMPARING object obj_name. IF lines( lt_filter ) = 0. RETURN. ENDIF. CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. lt_local = io_online->get_files_local_filtered( lo_filter ). LOOP AT ct_features ASSIGNING . LOOP AT -changed_files ASSIGNING . READ TABLE lt_local ASSIGNING WITH KEY file-filename = -filename file-path = -path. IF sy-subrc = 0. -local_sha1 = -file-sha1. ENDIF. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD map_files_to_objects. DATA ls_item TYPE zif_abapgit_definitions=>ty_item. FIELD-SYMBOLS LIKE LINE OF it_files. LOOP AT it_files ASSIGNING . zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = -filename iv_path = -path iv_devclass = io_online->get_package( ) io_dot = io_online->get_dot_abapgit( ) IMPORTING es_item = ls_item ). INSERT ls_item INTO TABLE rt_changed_objects. ENDLOOP. ENDMETHOD. METHOD find_changed_files. * don't care if its added or removed or changed, just remove identical * also list identical moved files DATA ls_path_name LIKE LINE OF rt_files. FIELD-SYMBOLS LIKE LINE OF it_expanded1. FIELD-SYMBOLS LIKE LINE OF it_expanded1. LOOP AT it_expanded1 ASSIGNING . READ TABLE it_expanded2 ASSIGNING WITH TABLE KEY path_name COMPONENTS path = -path name = -name. IF sy-subrc = 0 AND -sha1 = -sha1. CONTINUE. ENDIF. MOVE-CORRESPONDING TO ls_path_name. ls_path_name-filename = -name. ls_path_name-remote_sha1 = -sha1. INSERT ls_path_name INTO TABLE rt_files. ENDLOOP. LOOP AT it_expanded2 ASSIGNING . READ TABLE it_expanded1 ASSIGNING WITH TABLE KEY path_name COMPONENTS path = -path name = -name. IF sy-subrc = 0 AND -sha1 = -sha1. CONTINUE. ENDIF. MOVE-CORRESPONDING TO ls_path_name. ls_path_name-filename = -name. ls_path_name-remote_sha1 = -sha1. INSERT ls_path_name INTO TABLE rt_files. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_FLOW IMPLEMENTATION. METHOD constructor. super->constructor( ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_flow. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Flow' ii_page_menu_provider = lo_component ii_child_component = lo_component ). ENDMETHOD. METHOD refresh. DATA ls_feature LIKE LINE OF mt_features. DATA lo_online TYPE REF TO zcl_abapgit_repo_online. LOOP AT mt_features INTO ls_feature. lo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( ls_feature-repo-key ). lo_online->refresh( ). ENDLOOP. CLEAR mt_features. ENDMETHOD. METHOD render_table. DATA ls_path_name LIKE LINE OF is_feature-changed_files. DATA lv_status TYPE string. DATA lv_branch TYPE string. DATA lv_param TYPE string. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( || ). ri_html->add( || ). lv_branch = is_feature-branch-display_name. IF lv_branch IS INITIAL. lv_branch = 'main'. ENDIF. LOOP AT is_feature-changed_files INTO ls_path_name. IF ls_path_name-remote_sha1 = ls_path_name-local_sha1. lv_status = 'Match'. ELSE. ASSERT is_feature-repo-key IS NOT INITIAL. lv_param = zcl_abapgit_html_action_utils=>file_encode( iv_key = is_feature-repo-key ig_file = ls_path_name iv_extra = lv_branch ). lv_status = ri_html->a( iv_txt = 'Diff' iv_act = |{ zif_abapgit_definitions=>c_action-go_file_diff }?{ lv_param }| ). ENDIF. ri_html->add( || ). ENDLOOP. ri_html->add( |
    FilenameRemoteLocal
    { ls_path_name-path }{ ls_path_name-filename }{ ls_path_name-remote_sha1(7) }{ ls_path_name-local_sha1(7) }{ lv_status }
    | ). ENDMETHOD. METHOD render_toolbar. DATA lo_toolbar TYPE REF TO zcl_abapgit_html_toolbar. DATA lv_extra TYPE string. * todo: crossout pull if write protected CREATE OBJECT ri_html TYPE zcl_abapgit_html. CREATE OBJECT lo_toolbar EXPORTING iv_id = 'toolbar-flow'. IF is_feature-full_match = abap_false. lv_extra = |?index={ iv_index }&key={ is_feature-repo-key }&branch={ is_feature-branch-display_name }|. lo_toolbar->add( iv_txt = 'Pull' iv_act = |{ c_action-pull }{ lv_extra }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). lo_toolbar->add( iv_txt = 'Stage' iv_act = |{ c_action-stage }{ lv_extra }| iv_opt = zif_abapgit_html=>c_html_opt-strong ). ENDIF. zcl_abapgit_flow_exit=>get_instance( )->toolbar_extras( io_toolbar = lo_toolbar iv_index = iv_index is_feature = is_feature ). ri_html->add( lo_toolbar->render( ) ). ENDMETHOD. METHOD set_branch. DATA lv_branch TYPE string. DATA lo_online TYPE REF TO zcl_abapgit_repo_online. IF iv_branch IS NOT INITIAL. lv_branch = 'refs/heads/' && iv_branch. lo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). IF lo_online->get_selected_branch( ) <> lv_branch. lo_online->select_branch( lv_branch ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA lv_key TYPE zif_abapgit_persistence=>ty_value. DATA lv_branch TYPE string. DATA lo_filter TYPE REF TO kHGwlHbtMQYaNXTWgQdwmgPrpXDFKn. DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. DATA lv_index TYPE i. DATA lo_online TYPE REF TO zcl_abapgit_repo_online. DATA ls_feature LIKE LINE OF mt_features. DATA ls_event_result TYPE zif_abapgit_flow_exit=>ty_event_result. FIELD-SYMBOLS LIKE LINE OF ls_feature-changed_objects. FIELD-SYMBOLS LIKE LINE OF lt_filter. CASE ii_event->mv_action. WHEN c_action-refresh. refresh( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN zif_abapgit_definitions=>c_action-go_file_diff. lv_key = ii_event->query( )->get( 'KEY' ). lv_branch = ii_event->query( )->get( 'EXTRA' ). set_branch( iv_branch = lv_branch iv_key = lv_key ). * calling the page is done by the global router WHEN c_action-stage. lv_key = ii_event->query( )->get( 'KEY' ). lv_index = ii_event->query( )->get( 'INDEX' ). lv_branch = ii_event->query( )->get( 'BRANCH' ). lo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). READ TABLE mt_features INTO ls_feature INDEX lv_index. ASSERT sy-subrc = 0. LOOP AT ls_feature-changed_objects ASSIGNING . APPEND INITIAL LINE TO lt_filter ASSIGNING . -object = -obj_type. -obj_name = -obj_name. ENDLOOP. CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. set_branch( iv_branch = lv_branch iv_key = lv_key ). rs_handled-page = zcl_abapgit_gui_page_stage=>create( ii_force_refresh = abap_false io_repo = lo_online ii_obj_filter = lo_filter ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_w_bookmark. refresh( ). WHEN c_action-pull. lv_key = ii_event->query( )->get( 'KEY' ). lv_index = ii_event->query( )->get( 'INDEX' ). lv_branch = ii_event->query( )->get( 'BRANCH' ). lo_online ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). READ TABLE mt_features INTO ls_feature INDEX lv_index. ASSERT sy-subrc = 0. LOOP AT ls_feature-changed_objects ASSIGNING . APPEND INITIAL LINE TO lt_filter ASSIGNING . -object = -obj_type. -obj_name = -obj_name. ENDLOOP. CREATE OBJECT lo_filter EXPORTING it_filter = lt_filter. set_branch( iv_branch = lv_branch iv_key = lv_key ). rs_handled-page = zcl_abapgit_gui_page_pull=>create( io_repo = lo_online iv_trkorr = ls_feature-transport-trkorr ii_obj_filter = lo_filter ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. refresh( ). WHEN OTHERS. ls_event_result = zcl_abapgit_flow_exit=>get_instance( )->on_event( ii_event = ii_event it_features = mt_features ). rs_handled = ls_event_result-handled. IF ls_event_result-refresh = abap_true. refresh( ). ENDIF. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. CREATE OBJECT ro_toolbar EXPORTING iv_id = 'toolbar-main'. ro_toolbar->add( iv_txt = 'Refresh' iv_act = c_action-refresh ). ro_toolbar->add( iv_txt = zcl_abapgit_gui_buttons=>repo_list( ) iv_act = zif_abapgit_definitions=>c_action-abapgit_home ). ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA ls_feature LIKE LINE OF mt_features. DATA lv_index TYPE i. DATA lv_rendered TYPE abap_bool. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
    ' ). IF mt_features IS INITIAL. mt_features = kHGwlHbtMQYaNXTWgQdwprsTTRQzio=>get_information( ). ENDIF. LOOP AT mt_features INTO ls_feature. lv_index = sy-tabix. IF lines( ls_feature-changed_files ) = 0. * no changes, eg. only files outside of starting folder changed CONTINUE. ENDIF. lv_rendered = abap_true. ri_html->add( '' && ls_feature-repo-name ). IF ls_feature-branch-display_name IS NOT INITIAL. ri_html->add( | - | ). ri_html->add_icon( 'code-branch' ). ri_html->add( ls_feature-branch-display_name ). ENDIF. IF ls_feature-transport-trkorr IS NOT INITIAL. ri_html->add( | - | ). ri_html->add_icon( 'truck-solid' ). ri_html->add( |{ ls_feature-transport-trkorr }| ). ENDIF. ri_html->add( |
    | ). IF ls_feature-branch-display_name IS INITIAL. ri_html->add( |No branch found, comparing with main| ). ELSEIF ls_feature-pr IS NOT INITIAL. ri_html->add_a( iv_txt = ls_feature-pr-title iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ ls_feature-pr-url }| iv_class = |url| ). IF ls_feature-pr-draft = abap_true. ri_html->add( 'DRAFT' ). ENDIF. ELSE. ri_html->add( |No PR found| ). ENDIF. ri_html->add( |
    | ). IF ls_feature-transport IS NOT INITIAL. ri_html->add( |{ ls_feature-transport-trkorr } - { ls_feature-transport-title }
    | ). ELSE. ri_html->add( |No corresponding transport found
    | ). ENDIF. IF ls_feature-branch IS NOT INITIAL AND ls_feature-branch-up_to_date = abap_false. ri_html->add( 'Branch not up to date

    ' ). CONTINUE. ENDIF. ri_html->add( render_toolbar( iv_index = lv_index is_feature = ls_feature ) ). IF ls_feature-full_match = abap_true. ri_html->add( |Full Match
    | ). ELSE. ri_html->add( render_table( ls_feature ) ). ENDIF. * todo LOOP AT ls_feature-changed_objects INTO ls_item. * todo ri_html->add( |{ ls_item-obj_type } { ls_item-obj_name }
    | ). * todo ENDLOOP. ri_html->add( '
    ' ). ENDLOOP. IF lines( mt_features ) = 0 OR lv_rendered = abap_false. ri_html->add( 'Empty, repositories must be favorite + flow enabled

    ' ). ri_html->add( 'Or nothing in progress

    ' ). ri_html->add_a( iv_txt = 'abapGit flow documentation' iv_act = |{ zif_abapgit_definitions=>c_action-url }?url=https://docs.abapgit.org/user-guide/reference/flow.html| iv_class = |url| ). ENDIF. ri_html->add( '
    ' ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_FLOW_EXIT IMPLEMENTATION. METHOD get_instance. * this exit only works with global classes IF gi_global_exit IS NOT INITIAL. ri_exit = gi_global_exit. RETURN. ENDIF. TRY. CREATE OBJECT gi_exit TYPE ('ZCL_ABAPGIT_FLOW_USER_EXIT'). CATCH cx_sy_create_object_error ##NO_HANDLER. ENDTRY. CREATE OBJECT gi_global_exit TYPE zcl_abapgit_flow_exit. " this class ri_exit = gi_global_exit. ENDMETHOD. METHOD zif_abapgit_flow_exit~on_event. IF gi_exit IS NOT INITIAL. TRY. rs_result = gi_exit->on_event( ii_event = ii_event it_features = it_features ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_flow_exit~toolbar_extras. IF gi_exit IS NOT INITIAL. TRY. gi_exit->toolbar_extras( io_toolbar = io_toolbar iv_index = iv_index is_feature = is_feature ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_html_viewer_gui IMPLEMENTATION. METHOD constructor. DATA: lt_events TYPE cntl_simple_events, ls_event LIKE LINE OF lt_events. CREATE OBJECT mo_html_viewer EXPORTING query_table_disabled = iv_disable_query_table parent = io_container. ls_event-eventid = zif_abapgit_html_viewer=>c_id_sapevent. ls_event-appl_event = abap_true. APPEND ls_event TO lt_events. mo_html_viewer->set_registered_events( lt_events ). SET HANDLER on_event FOR mo_html_viewer. ENDMETHOD. METHOD on_event. RAISE EVENT zif_abapgit_html_viewer~sapevent EXPORTING action = action frame = frame getdata = getdata postdata = postdata query_table = query_table. ENDMETHOD. METHOD zif_abapgit_html_viewer~back. mo_html_viewer->go_back( ). ENDMETHOD. METHOD zif_abapgit_html_viewer~close_document. mo_html_viewer->close_document( ). ENDMETHOD. METHOD zif_abapgit_html_viewer~free. mo_html_viewer->free( ). ENDMETHOD. METHOD zif_abapgit_html_viewer~get_url. DATA lv_url TYPE c LENGTH 250. mo_html_viewer->get_current_url( IMPORTING url = lv_url ). cl_gui_cfw=>flush( ). rv_url = lv_url. ENDMETHOD. METHOD zif_abapgit_html_viewer~load_data. DATA lv_url TYPE c LENGTH 250. DATA lv_assigned TYPE c LENGTH 250. ASSERT strlen( iv_url ) <= 250. lv_url = iv_url. mo_html_viewer->load_data( EXPORTING url = lv_url type = iv_type subtype = iv_subtype size = iv_size IMPORTING assigned_url = lv_assigned CHANGING data_table = ct_data_table EXCEPTIONS dp_invalid_parameter = 1 dp_error_general = 2 cntl_error = 3 " html_syntax_notcorrect = 4 " not in lower releases OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error loading data for HTML viewer' ). ENDIF. ev_assigned_url = lv_assigned. ENDMETHOD. METHOD zif_abapgit_html_viewer~set_focus. cl_gui_control=>set_focus( EXPORTING control = mo_html_viewer EXCEPTIONS cntl_error = 1 cntl_system_error = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error in: cl_gui_control=>set_focus - SUBRC = { sy-subrc }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_html_viewer~set_registered_events. mo_html_viewer->set_registered_events( EXPORTING events = it_events EXCEPTIONS cntl_error = 1 cntl_system_error = 2 illegal_event_combination = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error registering events for HTML viewer' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_html_viewer~set_visiblity. DATA: lv_visible TYPE c LENGTH 1. IF iv_visible = abap_true. lv_visible = cl_gui_container=>visible_true. ELSE. lv_visible = cl_gui_container=>visible_false. ENDIF. mo_html_viewer->set_visible( lv_visible ). ENDMETHOD. METHOD zif_abapgit_html_viewer~show_url. DATA lv_url TYPE c LENGTH 250. lv_url = iv_url. mo_html_viewer->show_url( EXPORTING url = lv_url EXCEPTIONS cntl_error = 1 cnht_error_not_allowed = 2 cnht_error_parameter = 3 dp_error_general = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error showing URL in HTML viewer' ). ENDIF. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_HTML_PARTS IMPLEMENTATION. METHOD add_part. DATA lr_collection TYPE REF TO ty_named_collection. lr_collection = get_collection( iv_collection = iv_collection iv_create_if_missing = abap_true ). APPEND ii_part TO lr_collection->pile. ENDMETHOD. METHOD clear. CLEAR mt_part_collections. ENDMETHOD. METHOD get_collection. READ TABLE mt_part_collections REFERENCE INTO rr_collection WITH KEY name = iv_collection. IF sy-subrc <> 0 AND iv_create_if_missing = abap_true. APPEND INITIAL LINE TO mt_part_collections REFERENCE INTO rr_collection. rr_collection->name = iv_collection. ENDIF. ENDMETHOD. METHOD get_collection_names. FIELD-SYMBOLS LIKE LINE OF mt_part_collections. LOOP AT mt_part_collections ASSIGNING . APPEND -name TO rt_list. ENDLOOP. ENDMETHOD. METHOD get_collection_size. DATA lr_collection TYPE REF TO ty_named_collection. lr_collection = get_collection( iv_collection ). IF lr_collection IS BOUND. rv_size = lines( lr_collection->pile ). ENDIF. ENDMETHOD. METHOD get_parts. DATA lr_collection TYPE REF TO ty_named_collection. lr_collection = get_collection( iv_collection ). IF lr_collection IS BOUND. rt_parts = lr_collection->pile. ENDIF. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION. METHOD checkbox. DATA: lv_checked TYPE string. IF iv_checked = abap_true. lv_checked = |checked|. ENDIF. rv_html = |`. ENDMETHOD. METHOD class_constructor. DATA lv_mode TYPE tabname. CREATE OBJECT go_single_tags_re EXPORTING pattern = '<(AREA|BASE|BR|COL|COMMAND|EMBED|HR|IMG|INPUT|LINK|META|PARAM|SOURCE|!)' ignore_case = abap_false. gv_spaces = repeat( val = ` ` occ = c_max_indent ). GET PARAMETER ID 'DBT' FIELD lv_mode. gv_debug_mode = boolc( lv_mode = 'HREF' ). ENDMETHOD. METHOD create. CREATE OBJECT ri_instance TYPE zcl_abapgit_html. IF iv_initial_chunk IS NOT INITIAL. ri_instance->add( iv_initial_chunk ). ENDIF. ENDMETHOD. METHOD icon. DATA: lv_hint TYPE string, lv_name TYPE string, lv_color TYPE string, lv_class TYPE string, lv_large_icon TYPE string, lv_xpixel TYPE i, lv_onclick TYPE string. SPLIT iv_name AT '/' INTO lv_name lv_color. IF iv_hint IS NOT INITIAL. lv_hint = | title="{ iv_hint }"|. ENDIF. IF iv_onclick IS NOT INITIAL. lv_onclick = | onclick="{ iv_onclick }"|. ENDIF. IF iv_class IS NOT INITIAL. lv_class = | { iv_class }|. ENDIF. IF lv_color IS NOT INITIAL. lv_color = | { lv_color }|. ENDIF. " Automatic icon scaling (could be overwritten by personal setting) " see zcl_abapgit_gui_page->html_head lv_xpixel = cl_gui_cfw=>compute_pixel_from_metric( x_or_y = 'X' in = 1 ). IF lv_xpixel >= 2. lv_large_icon = ' large'. ENDIF. rv_str = ||. ENDMETHOD. METHOD indent_line. DATA: ls_study TYPE ty_study_result, lv_spaces TYPE i. ls_study = study_line( is_context = cs_context iv_line = cv_line ). " No indent for textarea tags IF ls_study-textarea_open = abap_true. cs_context-within_textarea = abap_true. RETURN. ELSEIF ls_study-textarea_close = abap_true. cs_context-within_textarea = abap_false. RETURN. ELSEIF cs_context-within_textarea = abap_true. RETURN. ENDIF. " First closing tag - shift back exceptionally IF ( ls_study-script_close = abap_true OR ls_study-style_close = abap_true OR ls_study-curly_close = abap_true OR ls_study-tag_close = abap_true ) AND cs_context-indent > 0. lv_spaces = ( cs_context-indent - 1 ) * c_indent_size. IF lv_spaces <= c_max_indent. cv_line = gv_spaces(lv_spaces) && cv_line. ELSE. cv_line = gv_spaces && cv_line. ENDIF. ELSE. cv_line = cs_context-indent_str && cv_line. ENDIF. " Context status update CASE abap_true. WHEN ls_study-script_open. cs_context-within_js = abap_true. cs_context-within_style = abap_false. WHEN ls_study-style_open. cs_context-within_js = abap_false. cs_context-within_style = abap_true. WHEN ls_study-script_close OR ls_study-style_close. cs_context-within_js = abap_false. cs_context-within_style = abap_false. ls_study-closings = ls_study-closings + 1. ENDCASE. " More-less logic chosen due to possible double tags in a line '' IF ls_study-openings <> ls_study-closings. IF ls_study-openings > ls_study-closings. cs_context-indent = cs_context-indent + 1. ELSEIF cs_context-indent > 0. " AND ls_study-openings < ls_study-closings cs_context-indent = cs_context-indent - 1. ENDIF. lv_spaces = cs_context-indent * c_indent_size. IF lv_spaces <= c_max_indent. cs_context-indent_str = gv_spaces(lv_spaces). ELSE. cv_line = gv_spaces && cv_line. ENDIF. ENDIF. ENDMETHOD. METHOD parse_data_attr. SPLIT iv_str AT '=' INTO rs_data_attr-name rs_data_attr-value. IF rs_data_attr-name IS INITIAL. CLEAR rs_data_attr. ENDIF. ENDMETHOD. METHOD study_line. DATA: lv_line TYPE string, lv_len TYPE i. lv_line = to_upper( shift_left( val = iv_line sub = ` ` ) ). lv_len = strlen( lv_line ). " Some assumptions for simplification and speed " - style & scripts tag should be opened/closed in a separate line " - style & scripts opening and closing in one line is possible but only once " TODO & Issues " - What if the string IS a well formed html already not just single line ? IF is_context-within_js = abap_true OR is_context-within_style = abap_true. IF is_context-within_js = abap_true AND lv_len >= 8 AND lv_line(8) = '= 7 AND lv_line(7) = '= 1 AND lv_line(1) = '}'. rs_result-curly_close = abap_true. ENDIF. FIND ALL OCCURRENCES OF '{' IN lv_line MATCH COUNT rs_result-openings. FIND ALL OCCURRENCES OF '}' IN lv_line MATCH COUNT rs_result-closings. ENDIF. ELSE. IF lv_len >= 7 AND lv_line(7) = ' 0. " Not found rs_result-script_open = abap_true. ENDIF. ENDIF. IF lv_len >= 6 AND lv_line(6) = ' 0. " Not found rs_result-style_open = abap_true. ENDIF. ENDIF. IF lv_len >= 2 AND lv_line(2) = ' rs_result-openings. * if everything is closings, there are no single tags FIND ALL OCCURRENCES OF REGEX go_single_tags_re IN lv_line MATCH COUNT rs_result-singles. ENDIF. rs_result-openings = rs_result-openings - rs_result-closings - rs_result-singles. ENDIF. " Textarea (same assumptions as above) IF is_context-within_textarea = abap_true AND lv_len >= 10 AND lv_line(10) = '= 9 AND lv_line(9) = ' 0. " Not found rs_result-textarea_open = abap_true. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_html~a. DATA: lv_class TYPE string, lv_href TYPE string, lv_click TYPE string, lv_id TYPE string, lv_act TYPE string, lv_style TYPE string, lv_title TYPE string. lv_class = iv_class. IF iv_opt CA zif_abapgit_html=>c_html_opt-strong. lv_class = lv_class && ' emphasis'. ENDIF. IF iv_opt CA zif_abapgit_html=>c_html_opt-cancel. lv_class = lv_class && ' attention'. ENDIF. IF iv_opt CA zif_abapgit_html=>c_html_opt-crossout. lv_class = lv_class && ' crossout grey'. ENDIF. IF lv_class IS NOT INITIAL. SHIFT lv_class LEFT DELETING LEADING space. lv_class = | class="{ lv_class }"|. ENDIF. lv_href = ' href="#"'. " Default, dummy lv_act = iv_act. IF ( iv_act IS NOT INITIAL OR iv_typ = zif_abapgit_html=>c_action_type-dummy ) AND iv_opt NA zif_abapgit_html=>c_html_opt-crossout. CASE iv_typ. WHEN zif_abapgit_html=>c_action_type-url. IF iv_query IS NOT INITIAL. lv_act = lv_act && `?` && iv_query. ENDIF. lv_href = | href="{ lv_act }"|. WHEN zif_abapgit_html=>c_action_type-sapevent. IF iv_query IS NOT INITIAL. lv_act = lv_act && `?` && iv_query. ENDIF. lv_href = | href="sapevent:{ lv_act }"|. WHEN zif_abapgit_html=>c_action_type-onclick. lv_href = ' href="#"'. lv_click = | onclick="{ iv_act }"|. WHEN zif_abapgit_html=>c_action_type-dummy. lv_href = ' href="#"'. ENDCASE. ENDIF. IF iv_id IS NOT INITIAL. lv_id = | id="{ iv_id }"|. ENDIF. IF iv_style IS NOT INITIAL. lv_style = | style="{ iv_style }"|. ENDIF. IF iv_title IS NOT INITIAL. lv_title = | title="{ iv_title }"|. ENDIF. " Debug option to display href-link on hover IF gv_debug_mode = abap_true. lv_title = | title="{ escape( val = lv_href format = cl_abap_format=>e_html_attr ) }"|. ENDIF. rv_str = || && |{ iv_txt }|. ENDMETHOD. METHOD zif_abapgit_html~add. DATA: lv_type TYPE c, li_renderable TYPE REF TO zif_abapgit_gui_renderable, lx_error TYPE REF TO zcx_abapgit_exception, lo_html TYPE REF TO zcl_abapgit_html. FIELD-SYMBOLS: TYPE string_table. lv_type = cl_abap_typedescr=>describe_by_data( ig_chunk )->type_kind. CASE lv_type. WHEN 'C' OR 'g'. " Char or string APPEND ig_chunk TO mt_buffer. WHEN 'h'. " Table ASSIGN ig_chunk TO . " Assuming table of strings ! Will dump otherwise APPEND LINES OF TO mt_buffer. WHEN 'r'. " Object ref ASSERT ig_chunk IS BOUND. " Dev mistake TRY. lo_html ?= ig_chunk. CATCH cx_sy_move_cast_error. TRY. li_renderable ?= ig_chunk. lo_html ?= li_renderable->render( ). CATCH cx_sy_move_cast_error. ASSERT 1 = 0. " Dev mistake CATCH zcx_abapgit_exception INTO lx_error. lo_html ?= create( |Render error: { lx_error->get_text( ) }| ). ENDTRY. ENDTRY. APPEND LINES OF lo_html->mt_buffer TO mt_buffer. WHEN OTHERS. ASSERT 1 = 0. " Dev mistake ENDCASE. ri_self = me. ENDMETHOD. METHOD zif_abapgit_html~add_a. zif_abapgit_html~add( zif_abapgit_html~a( iv_txt = iv_txt iv_act = iv_act iv_query = iv_query iv_typ = iv_typ iv_opt = iv_opt iv_class = iv_class iv_id = iv_id iv_style = iv_style iv_title = iv_title ) ). ri_self = me. ENDMETHOD. METHOD zif_abapgit_html~add_checkbox. zif_abapgit_html~add( checkbox( iv_id = iv_id iv_checked = iv_checked ) ). ri_self = me. ENDMETHOD. METHOD zif_abapgit_html~add_icon. zif_abapgit_html~add( icon( iv_name = iv_name iv_class = iv_class iv_hint = iv_hint iv_onclick = iv_onclick ) ). ri_self = me. ENDMETHOD. METHOD zif_abapgit_html~div. zif_abapgit_html~wrap( iv_tag = 'div' iv_content = iv_content ii_content = ii_content is_data_attr = is_data_attr it_data_attrs = it_data_attrs iv_id = iv_id iv_class = iv_class ). ri_self = me. ENDMETHOD. METHOD zif_abapgit_html~icon. rv_str = icon( iv_name = iv_name iv_hint = iv_hint iv_class = iv_class iv_onclick = iv_onclick ). ENDMETHOD. METHOD zif_abapgit_html~is_empty. rv_yes = boolc( lines( mt_buffer ) = 0 ). ENDMETHOD. METHOD zif_abapgit_html~render. DATA: ls_context TYPE ty_indent_context, lt_temp TYPE string_table. FIELD-SYMBOLS: LIKE LINE OF lt_temp, LIKE LINE OF lt_temp. IF iv_no_line_breaks = abap_true. CONCATENATE LINES OF mt_buffer INTO rv_html. ELSE. ls_context-no_indent_jscss = iv_no_indent_jscss. LOOP AT mt_buffer ASSIGNING . APPEND TO lt_temp ASSIGNING . indent_line( CHANGING cs_context = ls_context cv_line = ). ENDLOOP. CONCATENATE LINES OF lt_temp INTO rv_html SEPARATED BY cl_abap_char_utilities=>newline. ENDIF. ENDMETHOD. METHOD zif_abapgit_html~set_title. zif_abapgit_html~mv_chunk_title = iv_title. ri_self = me. ENDMETHOD. METHOD zif_abapgit_html~td. zif_abapgit_html~wrap( iv_format_single_line = iv_format_single_line iv_tag = 'td' iv_content = iv_content ii_content = ii_content iv_id = iv_id iv_class = iv_class is_data_attr = is_data_attr it_data_attrs = it_data_attrs iv_hint = iv_hint ). ri_self = me. ENDMETHOD. METHOD zif_abapgit_html~th. zif_abapgit_html~wrap( iv_format_single_line = iv_format_single_line iv_tag = 'th' iv_content = iv_content ii_content = ii_content iv_id = iv_id iv_class = iv_class is_data_attr = is_data_attr it_data_attrs = it_data_attrs iv_hint = iv_hint ). ri_self = me. ENDMETHOD. METHOD zif_abapgit_html~wrap. DATA lv_open_tag TYPE string. DATA lv_close_tag TYPE string. DATA ls_data_attr LIKE LINE OF it_data_attrs. DATA: lv_class TYPE string, lv_id TYPE string, lv_data_attr TYPE string, lv_title TYPE string. IF iv_id IS NOT INITIAL. lv_id = | id="{ iv_id }"|. ENDIF. IF iv_class IS NOT INITIAL. lv_class = | class="{ iv_class }"|. ENDIF. IF iv_hint IS NOT INITIAL. lv_title = | title="{ iv_hint }"|. ENDIF. IF is_data_attr IS NOT INITIAL. lv_data_attr = | data-{ is_data_attr-name }="{ is_data_attr-value }"|. ENDIF. LOOP AT it_data_attrs INTO ls_data_attr. lv_data_attr = lv_data_attr && | data-{ ls_data_attr-name }="{ ls_data_attr-value }"|. ENDLOOP. lv_open_tag = |<{ iv_tag }{ lv_id }{ lv_class }{ lv_data_attr }{ lv_title }>|. lv_close_tag = ||. IF ii_content IS NOT BOUND AND iv_content IS INITIAL. lv_open_tag = lv_open_tag && lv_close_tag. CLEAR lv_close_tag. ENDIF. IF iv_format_single_line = abap_true AND iv_content IS NOT INITIAL. zif_abapgit_html~add( lv_open_tag && iv_content && lv_close_tag ). ELSE. zif_abapgit_html~add( lv_open_tag ). IF ii_content IS BOUND. zif_abapgit_html~add( ii_content ). ELSEIF iv_content IS NOT INITIAL. zif_abapgit_html~add( iv_content ). ENDIF. IF lv_close_tag IS NOT INITIAL. zif_abapgit_html~add( lv_close_tag ). ENDIF. ENDIF. ri_self = me. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_UTILS IMPLEMENTATION. METHOD is_event_handler. DATA li_event_handler TYPE REF TO zif_abapgit_gui_event_handler. TRY. li_event_handler ?= io_obj. rv_yes = abap_true. CATCH cx_sy_move_cast_error. rv_yes = abap_false. ENDTRY. ENDMETHOD. METHOD is_renderable. DATA li_renderable TYPE REF TO zif_abapgit_gui_renderable. TRY. li_renderable ?= io_obj. rv_yes = abap_true. CATCH cx_sy_move_cast_error. rv_yes = abap_false. ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_HTML_PROCESSOR IMPLEMENTATION. METHOD constructor. mi_asset_man = ii_asset_man. ENDMETHOD. METHOD is_preserved. READ TABLE mt_preserve_css TRANSPORTING NO FIELDS WITH KEY table_line = iv_css_url. rv_yes = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD patch_html. CONSTANTS lc_css_re TYPE string VALUE ``. DATA lv_head_end TYPE i. DATA lo_css_re TYPE REF TO cl_abap_regex. DATA lo_matcher TYPE REF TO cl_abap_matcher. DATA lv_css_path TYPE string. DATA lv_marker TYPE string. DATA lv_off TYPE i. DATA lv_len TYPE i. DATA lv_cur TYPE i. DATA lv_css_build TYPE string VALUE ''. REPLACE FIRST OCCURRENCE OF '$BUILD_NAME' IN lv_css_build WITH c_css_build_name. " Mmmm CLEAR: ev_html, et_css_urls. lv_head_end = find_head_offset( iv_html ). CREATE OBJECT lo_css_re EXPORTING ignore_case = abap_true pattern = lc_css_re. lo_matcher = lo_css_re->create_matcher( text = substring( val = iv_html len = lv_head_end ) ). WHILE lo_matcher->find_next( ) = abap_true. lv_css_path = lo_matcher->get_submatch( 1 ). IF abap_false = is_preserved( lv_css_path ). lv_off = lo_matcher->get_offset( ). lv_len = lo_matcher->get_length( ). ev_html = ev_html && substring( val = iv_html off = lv_cur len = lv_off - lv_cur ). ev_html = ev_html && c_comment_start && substring( val = iv_html off = lv_off len = lv_len ) && c_comment_end. lv_cur = lv_off + lv_len. APPEND lv_css_path TO et_css_urls. ENDIF. ENDWHILE. ev_html = ev_html && substring( val = iv_html off = lv_cur len = lv_head_end - lv_cur ). IF lines( et_css_urls ) > 0. lv_marker = cl_abap_char_utilities=>newline && ` ` " Assume 4 space indent, maybe improve and detect ? && c_preprocess_marker && cl_abap_char_utilities=>newline && ` `. ev_html = ev_html && lv_marker && lv_css_build. ENDIF. ev_html = ev_html && substring( val = iv_html off = lv_head_end ). ENDMETHOD. METHOD preserve_css. APPEND iv_css_url TO mt_preserve_css. ENDMETHOD. METHOD zif_abapgit_gui_html_processor~process. DATA lo_css_processor TYPE REF TO zcl_abapgit_gui_css_processor. DATA lt_css_urls TYPE string_table. DATA lv_css_build TYPE string. FIELD-SYMBOLS LIKE LINE OF lt_css_urls. patch_html( EXPORTING iv_html = iv_html IMPORTING ev_html = rv_html et_css_urls = lt_css_urls ). IF lines( lt_css_urls ) > 0. CREATE OBJECT lo_css_processor EXPORTING ii_asset_manager = mi_asset_man. LOOP AT lt_css_urls ASSIGNING . lo_css_processor->add_file( ). ENDLOOP. lv_css_build = lo_css_processor->process( ). ii_gui_services->cache_asset( iv_url = |{ c_css_build_name }| iv_type = 'text' iv_subtype = 'css' iv_text = lv_css_build ). ENDIF. ENDMETHOD. METHOD find_head_offset. rv_head_end = find( val = iv_html regex = |{ cl_abap_char_utilities=>newline }?\\s*| case = abap_false ). IF rv_head_end <= 0. rv_head_end = find( val = iv_html regex = || case = abap_false ). IF rv_head_end <= 0. zcx_abapgit_exception=>raise( 'HTML preprocessor: not found' ). ENDIF. ENDIF. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_HOTKEY_CTL IMPLEMENTATION. METHOD constructor. super->constructor( ). ms_user_settings = zcl_abapgit_persistence_user=>get_instance( )->get_settings( ). ENDMETHOD. METHOD render_scripts. DATA lv_json TYPE string. FIELD-SYMBOLS: LIKE LINE OF it_hotkeys. lv_json = `{`. LOOP AT it_hotkeys ASSIGNING . IF sy-tabix > 1. lv_json = lv_json && |,|. ENDIF. lv_json = lv_json && | "{ -hotkey }" : "{ -action }" |. ENDLOOP. lv_json = lv_json && `}`. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->set_title( cl_abap_typedescr=>describe_by_object_ref( me )->get_relative_name( ) ). ri_html->add( |setKeyBindings({ lv_json });| ). ENDMETHOD. METHOD should_show_hint. IF gv_hint_was_shown = abap_false. rv_yes = abap_true. gv_hint_was_shown = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA ls_hotkey LIKE LINE OF rt_hotkey_actions. ls_hotkey-ui_component = 'Hotkeys'. ls_hotkey-action = c_showhotkeys_action. ls_hotkey-description = 'Show Hotkeys Help'. ls_hotkey-hotkey = '?'. INSERT ls_hotkey INTO TABLE rt_hotkey_actions. ENDMETHOD. METHOD zif_abapgit_gui_hotkey_ctl~get_registered_hotkeys. rt_registered_hotkeys = mt_hotkeys. ENDMETHOD. METHOD zif_abapgit_gui_hotkey_ctl~register_hotkeys. FIELD-SYMBOLS LIKE LINE OF it_hotkeys. " Compress duplicates LOOP AT it_hotkeys ASSIGNING . READ TABLE mt_hotkeys WITH KEY hotkey = -hotkey TRANSPORTING NO FIELDS. IF sy-subrc = 0. " If found command with same hotkey DELETE mt_hotkeys INDEX sy-tabix. " Later registered commands enjoys the priority ENDIF. IF ms_user_settings-link_hints_enabled = abap_true AND ms_user_settings-link_hint_key = -hotkey. " Link hint activation key is more important CONTINUE. ENDIF. APPEND TO mt_hotkeys. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_gui_hotkey_ctl~reset. CLEAR mt_hotkeys. ENDMETHOD. METHOD zif_abapgit_gui_hotkey_ctl~set_visible. mv_visible = iv_visible. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. DATA: lv_hint TYPE string, lt_registered_hotkeys TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr, lv_hotkey TYPE string, ls_user_settings TYPE zif_abapgit_definitions=>ty_s_user_settings. FIELD-SYMBOLS LIKE LINE OF lt_registered_hotkeys. register_handlers( ). CREATE OBJECT ri_html TYPE zcl_abapgit_html. lt_registered_hotkeys = zif_abapgit_gui_hotkey_ctl~get_registered_hotkeys( ). SORT lt_registered_hotkeys BY ui_component description. register_deferred_script( render_scripts( lt_registered_hotkeys ) ). " Render hotkeys ri_html->add( '
      ' ). LOOP AT lt_registered_hotkeys ASSIGNING . ri_html->add( |
    • | && |{ -hotkey }| && |{ -description }| && |
    • | ). ENDLOOP. " render link hints activation key ls_user_settings = zcl_abapgit_persistence_user=>get_instance( )->get_settings( ). IF ls_user_settings-link_hints_enabled = abap_true. ri_html->add( |
    • | && |{ ls_user_settings-link_hint_key }| && |Link Hints| && |
    • | ). ri_html->add( |
    • | && |y{ ls_user_settings-link_hint_key }| && |Copy Link Text| && |
    • | ). ENDIF. ri_html->add( '
    ' ). CLEAR lv_hotkey. READ TABLE lt_registered_hotkeys ASSIGNING WITH KEY action = c_showhotkeys_action. IF sy-subrc = 0. lv_hotkey = -hotkey. ENDIF. lv_hint = |Close window with upper right corner 'X'|. IF lv_hotkey IS NOT INITIAL. lv_hint = lv_hint && | or press '{ -hotkey }'|. ENDIF. ri_html = zcl_abapgit_gui_chunk_lib=>render_infopanel( iv_div_id = 'hotkeys' iv_title = 'Hotkeys' iv_hint = lv_hint iv_hide = boolc( mv_visible = abap_false ) iv_scrollable = abap_false io_content = ri_html ). IF lv_hotkey IS NOT INITIAL AND should_show_hint( ) = abap_true. ri_html->add( |
    | && |Press '{ -hotkey }' to get keyboard shortcuts list| && |
    | ). ENDIF. " Always reset visibility here. Closing of the popup has to be done by the " user and is handled in JS. mv_visible = abap_false. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_event IMPLEMENTATION. METHOD constructor. " Edge Webview control returns upper case action but abapGit requires lower case (#4841) zif_abapgit_gui_event~mi_gui_services = ii_gui_services. zif_abapgit_gui_event~mv_action = to_lower( iv_action ). zif_abapgit_gui_event~mv_getdata = iv_getdata. zif_abapgit_gui_event~mt_postdata = it_postdata. IF ii_gui_services IS BOUND. zif_abapgit_gui_event~mv_current_page_name = ii_gui_services->get_current_page_name( ). ENDIF. ENDMETHOD. METHOD fields_to_map. FIELD-SYMBOLS LIKE LINE OF it_fields. CREATE OBJECT ro_string_map EXPORTING iv_case_insensitive = abap_true. LOOP AT it_fields ASSIGNING . ro_string_map->set( iv_key = -name iv_val = -value ). ENDLOOP. ENDMETHOD. METHOD new. CREATE OBJECT ro_instance EXPORTING ii_gui_services = ii_gui_services iv_action = iv_action iv_getdata = iv_getdata it_postdata = it_postdata. ENDMETHOD. METHOD zif_abapgit_gui_event~form_data. IF mo_form_data IS NOT BOUND. mo_form_data = fields_to_map( parse_post_form_data( zif_abapgit_gui_event~mt_postdata ) ). mo_form_data->freeze( ). ENDIF. ro_string_map = mo_form_data. ENDMETHOD. METHOD zif_abapgit_gui_event~query. IF mo_query IS NOT BOUND. mo_query = fields_to_map( parse_fields( zif_abapgit_gui_event~mv_getdata ) ). mo_query->freeze( ). ENDIF. ro_string_map = mo_query. ENDMETHOD. METHOD parse_fields_upper_case_name. rt_fields = parse_fields( iv_string = iv_string iv_upper_cased = abap_true ). ENDMETHOD. METHOD parse_post_form_data. DATA lv_serialized_post_data TYPE string. lv_serialized_post_data = translate_postdata( it_post_data ). IF iv_upper_cased = abap_true. rt_fields = parse_fields_upper_case_name( lv_serialized_post_data ). ELSE. rt_fields = parse_fields( lv_serialized_post_data ). ENDIF. ENDMETHOD. METHOD parse_fields. DATA: lt_substrings TYPE string_table, ls_field LIKE LINE OF rt_fields. FIELD-SYMBOLS LIKE LINE OF lt_substrings. SPLIT iv_string AT '&' INTO TABLE lt_substrings. LOOP AT lt_substrings ASSIGNING . CLEAR ls_field. " On attempt to change unescaping -> run unit tests to check ! " Unescape name and value separately ls_field-name = unescape( substring_before( val = sub = '=' ) ). ls_field-value = unescape( substring_after( val = sub = '=' ) ). IF ls_field IS INITIAL. " Not a field with proper structure CONTINUE. ENDIF. APPEND ls_field TO rt_fields. ENDLOOP. IF iv_upper_cased = abap_true. field_keys_to_upper( CHANGING ct_fields = rt_fields ). ENDIF. ENDMETHOD. METHOD translate_postdata. DATA: lt_post_data TYPE zif_abapgit_html_viewer=>ty_post_data, ls_last_line LIKE LINE OF it_postdata, lv_last_line_index TYPE i. IF it_postdata IS INITIAL. RETURN. "Nothing to do ENDIF. lt_post_data = it_postdata. "Save the last line for separate merge, because we don't need its trailing spaces WHILE ls_last_line IS INITIAL. lv_last_line_index = lines( lt_post_data ). READ TABLE lt_post_data INTO ls_last_line INDEX lv_last_line_index. DELETE lt_post_data INDEX lv_last_line_index. ENDWHILE. CONCATENATE LINES OF lt_post_data INTO rv_string IN CHARACTER MODE RESPECTING BLANKS. CONCATENATE rv_string ls_last_line INTO rv_string IN CHARACTER MODE. ENDMETHOD. METHOD field_keys_to_upper. FIELD-SYMBOLS LIKE LINE OF ct_fields. LOOP AT ct_fields ASSIGNING . -name = to_upper( -name ). ENDLOOP. ENDMETHOD. METHOD unescape. * do not use cl_http_utility as it does strange things with the encoding rv_string = iv_string. * todo, more to be added here REPLACE ALL OCCURRENCES OF '%3A' IN rv_string WITH ':' IGNORING CASE. REPLACE ALL OCCURRENCES OF '%3F' IN rv_string WITH '?' IGNORING CASE. REPLACE ALL OCCURRENCES OF '%3D' IN rv_string WITH '=' IGNORING CASE. REPLACE ALL OCCURRENCES OF '%2F' IN rv_string WITH '/' IGNORING CASE. REPLACE ALL OCCURRENCES OF '%25' IN rv_string WITH '%' IGNORING CASE. REPLACE ALL OCCURRENCES OF '%26' IN rv_string WITH '&' IGNORING CASE. REPLACE ALL OCCURRENCES OF gv_non_breaking_space IN rv_string WITH ` `. ENDMETHOD. METHOD class_constructor. CONSTANTS lc_nbsp TYPE xstring VALUE 'C2A0'. "   TRY. gv_non_breaking_space = zcl_abapgit_convert=>xstring_to_string_utf8( lc_nbsp ). CATCH zcx_abapgit_exception. ASSERT 0 = 1. ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_CSS_PROCESSOR IMPLEMENTATION. METHOD add_file. APPEND iv_url TO mt_files. ENDMETHOD. METHOD constructor. mi_asset_manager = ii_asset_manager. ENDMETHOD. METHOD get_css_vars_in_string. CONSTANTS: lc_root_pattern TYPE string VALUE `:root\s*\{([^\}]*)\}`, lc_variable_pattern TYPE string VALUE `\-\-([\w\d-]+)\s*:\s*([^\n\r;]*);`. DATA: lv_root TYPE string, lo_matcher TYPE REF TO cl_abap_matcher, lo_regex TYPE REF TO cl_abap_regex, ls_variable LIKE LINE OF rt_variables. " Only the :root element may define variables for now FIND FIRST OCCURRENCE OF REGEX lc_root_pattern IN iv_string SUBMATCHES lv_root. IF sy-subrc = 0 AND lv_root IS NOT INITIAL. CREATE OBJECT lo_regex EXPORTING pattern = lc_variable_pattern. lo_matcher = lo_regex->create_matcher( text = lv_root ). WHILE lo_matcher->find_next( ) = abap_true. ls_variable-name = lo_matcher->get_submatch( 1 ). ls_variable-value = lo_matcher->get_submatch( 2 ). INSERT ls_variable INTO TABLE rt_variables. IF sy-subrc <> 0. MODIFY TABLE rt_variables FROM ls_variable. ENDIF. ENDWHILE. ENDIF. ENDMETHOD. METHOD process. DATA: lt_contents TYPE STANDARD TABLE OF string, lv_content TYPE string, lt_css_variables TYPE ty_css_vars, lt_css_vars_in_file TYPE ty_css_vars. FIELD-SYMBOLS: TYPE string, LIKE LINE OF lt_css_vars_in_file, LIKE LINE OF lt_contents. " 1. Determine all variables and their values. Later definitions overwrite previous ones. LOOP AT mt_files ASSIGNING . lv_content = mi_asset_manager->get_text_asset( iv_url = iv_assert_subtype = 'css' ). lt_css_vars_in_file = get_css_vars_in_string( lv_content ). LOOP AT lt_css_vars_in_file ASSIGNING . INSERT INTO TABLE lt_css_variables. IF sy-subrc <> 0. MODIFY TABLE lt_css_variables FROM . ENDIF. ENDLOOP. APPEND lv_content TO lt_contents. ENDLOOP. " 2. Replace all variable usages in variables LOOP AT lt_css_variables ASSIGNING WHERE value CS 'var(--'. resolve_var_recursively( EXPORTING iv_variable_name = -name CHANGING ct_variables = lt_css_variables ). ENDLOOP. " 3. Replace all other variable usages by inlining the values. LOOP AT lt_contents ASSIGNING . LOOP AT lt_css_variables ASSIGNING . REPLACE ALL OCCURRENCES OF |var(--{ -name })| IN WITH -value. ENDLOOP. ENDLOOP. rv_result = concat_lines_of( table = lt_contents sep = cl_abap_char_utilities=>newline ). ENDMETHOD. METHOD resolve_var_recursively. CONSTANTS: lc_variable_usage_pattern TYPE string VALUE `var\(\-\-([^\)]*)\)`. DATA: lv_variable_name TYPE string. FIELD-SYMBOLS: LIKE LINE OF ct_variables, LIKE LINE OF ct_variables. READ TABLE ct_variables WITH TABLE KEY name = iv_variable_name ASSIGNING . IF sy-subrc = 0. DO. FIND FIRST OCCURRENCE OF REGEX lc_variable_usage_pattern IN -value SUBMATCHES lv_variable_name. IF sy-subrc = 0. resolve_var_recursively( EXPORTING iv_variable_name = lv_variable_name CHANGING ct_variables = ct_variables ). READ TABLE ct_variables WITH TABLE KEY name = lv_variable_name ASSIGNING . REPLACE FIRST OCCURRENCE OF |var(--{ lv_variable_name })| IN -value WITH -value. ELSE. EXIT. ENDIF. ENDDO. ELSE. zcx_abapgit_exception=>raise( |CSS variable { iv_variable_name } not resolvable| ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_asset_manager IMPLEMENTATION. METHOD create. CREATE OBJECT ri_asset_manager TYPE zcl_abapgit_gui_asset_manager. ENDMETHOD. METHOD get_mime_asset. DATA: ls_key TYPE wwwdatatab, lv_size_c TYPE wwwparams-value, lv_size TYPE i, lt_w3mime TYPE STANDARD TABLE OF w3mime, ls_w3mime LIKE LINE OF lt_w3mime. ls_key-relid = 'MI'. ls_key-objid = iv_mime_name. " Get exact file size CALL FUNCTION 'WWWPARAMS_READ' EXPORTING relid = ls_key-relid objid = ls_key-objid name = 'filesize' IMPORTING value = lv_size_c EXCEPTIONS entry_not_exists = 1. IF sy-subrc IS NOT INITIAL. RETURN. ENDIF. lv_size = lv_size_c. " Get binary data CALL FUNCTION 'WWWDATA_IMPORT' EXPORTING key = ls_key TABLES mime = lt_w3mime EXCEPTIONS wrong_object_type = 1 import_error = 2. IF sy-subrc IS NOT INITIAL. RETURN. ENDIF. LOOP AT lt_w3mime INTO ls_w3mime. CONCATENATE rv_xdata ls_w3mime-line INTO rv_xdata IN BYTE MODE. ENDLOOP. rv_xdata = rv_xdata(lv_size). ENDMETHOD. METHOD load_asset. MOVE-CORRESPONDING is_asset_entry TO rs_asset. IF rs_asset-content IS INITIAL AND is_asset_entry-mime_name IS NOT INITIAL. " inline content has the priority rs_asset-content = get_mime_asset( is_asset_entry-mime_name ). ENDIF. IF rs_asset-content IS INITIAL. zcx_abapgit_exception=>raise( |failed to load GUI asset: { is_asset_entry-url }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_asset_manager~get_all_assets. FIELD-SYMBOLS LIKE LINE OF mt_asset_register. LOOP AT mt_asset_register ASSIGNING . APPEND load_asset( ) TO rt_assets. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_gui_asset_manager~get_asset. FIELD-SYMBOLS LIKE LINE OF mt_asset_register. READ TABLE mt_asset_register WITH KEY url = iv_url ASSIGNING . IF IS NOT ASSIGNED. zcx_abapgit_exception=>raise( |Cannot find GUI asset: { iv_url }| ). ENDIF. rs_asset = load_asset( ). ENDMETHOD. METHOD zif_abapgit_gui_asset_manager~get_text_asset. DATA ls_asset TYPE zif_abapgit_gui_asset_manager~ty_web_asset. ls_asset = zif_abapgit_gui_asset_manager~get_asset( iv_url ). IF ls_asset-type <> 'text'. zcx_abapgit_exception=>raise( |Not a text asset: { iv_url }| ). ENDIF. IF iv_assert_subtype IS NOT INITIAL AND ls_asset-subtype <> iv_assert_subtype. zcx_abapgit_exception=>raise( |Wrong subtype ({ iv_assert_subtype }): { iv_url }| ). ENDIF. rv_asset = zcl_abapgit_convert=>xstring_to_string_utf8( ls_asset-content ). ENDMETHOD. METHOD zif_abapgit_gui_asset_manager~register_asset. DATA ls_asset LIKE LINE OF mt_asset_register. SPLIT iv_type AT '/' INTO ls_asset-type ls_asset-subtype. ls_asset-url = iv_url. ls_asset-mime_name = iv_mime_name. ls_asset-is_cacheable = iv_cacheable. IF iv_base64 IS NOT INITIAL. ls_asset-content = zcl_abapgit_convert=>base64_to_xstring( iv_base64 ). ELSEIF iv_inline IS NOT INITIAL. ls_asset-content = zcl_abapgit_convert=>string_to_xstring( iv_inline ). ENDIF. DELETE mt_asset_register WHERE url = iv_url. " TODO: Maybe forbid overwriting cacheable assets as they were probably already cached ... arguable APPEND ls_asset TO mt_asset_register. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI IMPLEMENTATION. METHOD back. DATA lv_index TYPE i. DATA ls_stack LIKE LINE OF mt_stack. " If viewer is showing Internet page, then use browser navigation IF mi_html_viewer->get_url( ) CP 'http*'. mi_html_viewer->back( ). RETURN. ENDIF. lv_index = lines( mt_stack ). IF lv_index = 0. rv_exit = abap_true. RETURN. ENDIF. IF iv_graceful = abap_true AND back_graceful( ) = abap_true. RETURN. ENDIF. DO lv_index TIMES. READ TABLE mt_stack INDEX lv_index INTO ls_stack. ASSERT sy-subrc = 0. DELETE mt_stack INDEX lv_index. ASSERT sy-subrc = 0. lv_index = lv_index - 1. IF iv_to_bookmark = abap_false OR ls_stack-bookmark = abap_true. EXIT. ENDIF. ENDDO. mi_cur_page = ls_stack-page. " last page always stays render( ). ENDMETHOD. METHOD back_graceful. DATA li_handler TYPE REF TO zif_abapgit_gui_event_handler. DATA ls_handled TYPE zif_abapgit_gui_event_handler=>ty_handling_result. " This code can be potentially improved " Why send go_back to the topmost handler only ? It makes sense to notify the whole stack " But than how to handle re-render ? render if at least one handler asks for it ? " Probably that's the way but needs a relevant example. Postponed arch decision. READ TABLE mt_event_handlers INTO li_handler INDEX 1. IF sy-subrc = 0. ls_handled = li_handler->on_event( zcl_abapgit_gui_event=>new( iv_action = zif_abapgit_definitions=>c_action-go_back ii_gui_services = me ) ). IF ls_handled-state = c_event_state-re_render. " soft exit, probably popup render( ). rv_handled = abap_true. ELSEIF ls_handled-state = c_event_state-no_more_act. " soft exit, probably GUI popup rv_handled = abap_true. ENDIF. ENDIF. ENDMETHOD. METHOD cache_html. rv_url = zif_abapgit_gui_services~cache_asset( iv_text = iv_text iv_type = 'text' iv_subtype = 'html' ). ENDMETHOD. METHOD call_page. DATA: ls_stack TYPE ty_page_stack. IF iv_replacing = abap_false AND NOT mi_cur_page IS INITIAL. ls_stack-page = mi_cur_page. ls_stack-bookmark = iv_with_bookmark. APPEND ls_stack TO mt_stack. ENDIF. mi_cur_page = ii_page. render( ). ENDMETHOD. METHOD constructor. IF io_component IS BOUND. IF zcl_abapgit_gui_utils=>is_renderable( io_component ) = abap_true. mi_cur_page ?= io_component. " direct page ELSE. IF zcl_abapgit_gui_utils=>is_event_handler( io_component ) = abap_false. zcx_abapgit_exception=>raise( 'Component must be renderable or be an event handler' ). ENDIF. mi_router ?= io_component. ENDIF. ENDIF. CREATE OBJECT mo_html_parts. mv_rollback_on_error = iv_rollback_on_error. mi_asset_man = ii_asset_man. mi_hotkey_ctl = ii_hotkey_ctl. mi_html_processor = ii_html_processor. " Maybe improve to middlewares stack ?? startup( ). ENDMETHOD. METHOD free. SET HANDLER on_event FOR mi_html_viewer ACTIVATION space. mi_html_viewer->close_document( ). mi_html_viewer->free( ). FREE mi_html_viewer. ENDMETHOD. METHOD go_home. DATA ls_stack LIKE LINE OF mt_stack. IF mi_router IS BOUND. CLEAR: mt_stack, mt_event_handlers. APPEND mi_router TO mt_event_handlers. on_event( action = |{ iv_action }| ). ELSE. IF lines( mt_stack ) > 0. READ TABLE mt_stack INTO ls_stack INDEX 1. mi_cur_page = ls_stack-page. ENDIF. render( ). ENDIF. ENDMETHOD. METHOD handle_action. DATA: lx_exception TYPE REF TO zcx_abapgit_exception, li_handler TYPE REF TO zif_abapgit_gui_event_handler, li_event TYPE REF TO zif_abapgit_gui_event, ls_handled TYPE zif_abapgit_gui_event_handler=>ty_handling_result. CREATE OBJECT li_event TYPE zcl_abapgit_gui_event EXPORTING ii_gui_services = me iv_action = iv_action iv_getdata = iv_getdata it_postdata = it_postdata. TRY. ls_handled = zcl_abapgit_exit=>get_instance( )->on_event( li_event ). IF ls_handled-state = c_event_state-not_handled. LOOP AT mt_event_handlers INTO li_handler. ls_handled = li_handler->on_event( li_event ). IF ls_handled-state IS NOT INITIAL AND ls_handled-state <> c_event_state-not_handled. " is handled EXIT. ENDIF. ENDLOOP. ENDIF. IF is_page_modal( mi_cur_page ) = abap_true AND NOT ( ls_handled-state = c_event_state-re_render OR ls_handled-state = c_event_state-go_back OR ls_handled-state = c_event_state-no_more_act ). " Restrict new page switching from modals ls_handled-state = c_event_state-no_more_act. ENDIF. CASE ls_handled-state. WHEN c_event_state-re_render. render( ). WHEN c_event_state-new_page. call_page( ls_handled-page ). WHEN c_event_state-new_page_w_bookmark. call_page( ii_page = ls_handled-page iv_with_bookmark = abap_true ). WHEN c_event_state-new_page_replacing. call_page( ii_page = ls_handled-page iv_replacing = abap_true ). WHEN c_event_state-go_back. back( ). WHEN c_event_state-go_back_to_bookmark. back( iv_to_bookmark = abap_true ). WHEN c_event_state-no_more_act. " Do nothing, handling completed WHEN OTHERS. zcx_abapgit_exception=>raise( |Unknown action: { iv_action }| ). ENDCASE. CATCH zcx_abapgit_cancel ##NO_HANDLER. " Do nothing = c_event_state-no_more_act CATCH zcx_abapgit_exception INTO lx_exception. handle_error( lx_exception ). ENDTRY. ENDMETHOD. METHOD handle_error. DATA: li_gui_error_handler TYPE REF TO zif_abapgit_gui_error_handler, lx_exception TYPE REF TO cx_root. IF mv_rollback_on_error = abap_true. ROLLBACK WORK. ENDIF. TRY. li_gui_error_handler ?= mi_cur_page. IF li_gui_error_handler IS BOUND AND li_gui_error_handler->handle_error( ix_exception ) = abap_true. " We rerender the current page to display the error box render( ). ELSEIF ix_exception->mi_log IS BOUND. mi_common_log = ix_exception->mi_log. IF mi_common_log->get_log_level( ) >= zif_abapgit_log=>c_log_level-warning. zcl_abapgit_log_viewer=>show_log( mi_common_log ). ENDIF. ELSE. MESSAGE ix_exception TYPE 'S' DISPLAY LIKE 'E'. ENDIF. CATCH zcx_abapgit_exception cx_sy_move_cast_error INTO lx_exception. " In case of fire we just fallback to plain old message MESSAGE lx_exception TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. ENDMETHOD. METHOD is_page_modal. DATA li_modal TYPE REF TO zif_abapgit_gui_modal. TRY. IF ii_page IS BOUND. li_modal ?= ii_page. rv_yes = li_modal->is_modal( ). ENDIF. CATCH cx_sy_move_cast_error. ENDTRY. ENDMETHOD. METHOD on_event. handle_action( iv_action = action iv_getdata = getdata it_postdata = postdata ). ENDMETHOD. METHOD render. DATA: lv_url TYPE string, lv_html TYPE string, li_html TYPE REF TO zif_abapgit_html. IF mi_cur_page IS NOT BOUND. zcx_abapgit_exception=>raise( 'GUI error: no current page' ). ENDIF. CLEAR mt_event_handlers. mo_html_parts->clear( ). IF mi_router IS BOUND AND is_page_modal( mi_cur_page ) = abap_false. " No global commands in modals APPEND mi_router TO mt_event_handlers. ENDIF. IF mi_hotkey_ctl IS BOUND. mi_hotkey_ctl->reset( ). ENDIF. li_html = mi_cur_page->render( ). lv_html = li_html->render( iv_no_indent_jscss = abap_true ). IF mi_html_processor IS BOUND. lv_html = mi_html_processor->process( iv_html = lv_html ii_gui_services = me ). ENDIF. lv_url = cache_html( lv_html ). mi_html_viewer->show_url( lv_url ). ENDMETHOD. METHOD set_focus. mi_html_viewer->set_focus( ). ENDMETHOD. METHOD startup. DATA: lt_events TYPE cntl_simple_events, ls_event LIKE LINE OF lt_events, lt_assets TYPE zif_abapgit_gui_asset_manager=>ty_web_assets. FIELD-SYMBOLS LIKE LINE OF lt_assets. mi_html_viewer = zcl_abapgit_ui_factory=>get_html_viewer( ). IF mi_asset_man IS BOUND. lt_assets = mi_asset_man->get_all_assets( ). LOOP AT lt_assets ASSIGNING WHERE is_cacheable = abap_true. zif_abapgit_gui_services~cache_asset( iv_xdata = -content iv_url = -url iv_type = -type iv_subtype = -subtype ). ENDLOOP. ENDIF. ls_event-eventid = mi_html_viewer->c_id_sapevent. ls_event-appl_event = abap_true. APPEND ls_event TO lt_events. mi_html_viewer->set_registered_events( lt_events ). SET HANDLER on_event FOR mi_html_viewer. ENDMETHOD. METHOD zif_abapgit_gui_services~cache_asset. TYPES ty_hex TYPE x LENGTH 200. TYPES ty_char TYPE c LENGTH 200. DATA: lt_xdata TYPE STANDARD TABLE OF ty_hex WITH DEFAULT KEY, lv_size TYPE i, lt_html TYPE STANDARD TABLE OF ty_char WITH DEFAULT KEY. ASSERT iv_text IS SUPPLIED OR iv_xdata IS SUPPLIED. IF iv_text IS SUPPLIED. " String input zcl_abapgit_convert=>string_to_tab( EXPORTING iv_str = iv_text IMPORTING ev_size = lv_size et_tab = lt_html ). mi_html_viewer->load_data( EXPORTING iv_type = iv_type iv_subtype = iv_subtype iv_size = lv_size iv_url = iv_url IMPORTING ev_assigned_url = rv_url CHANGING ct_data_table = lt_html ). ELSE. " Raw input zcl_abapgit_convert=>xstring_to_bintab( EXPORTING iv_xstr = iv_xdata IMPORTING ev_size = lv_size et_bintab = lt_xdata ). mi_html_viewer->load_data( EXPORTING iv_type = iv_type iv_subtype = iv_subtype iv_size = lv_size iv_url = iv_url IMPORTING ev_assigned_url = rv_url CHANGING ct_data_table = lt_xdata ). ENDIF. ASSERT sy-subrc = 0. " Image data error ENDMETHOD. METHOD zif_abapgit_gui_services~get_current_page_name. DATA li_page_hoc TYPE REF TO zcl_abapgit_gui_page_hoc. IF mi_cur_page IS BOUND. rv_page_name = cl_abap_classdescr=>describe_by_object_ref( mi_cur_page )->get_relative_name( ). " For HOC components return name of child component instead IF rv_page_name = 'ZCL_ABAPGIT_GUI_PAGE_HOC'. li_page_hoc ?= mi_cur_page. IF li_page_hoc->get_child( ) IS BOUND. rv_page_name = cl_abap_classdescr=>describe_by_object_ref( li_page_hoc->get_child( ) )->get_relative_name( ). ENDIF. ENDIF. ENDIF." ELSE - return is empty => initial page ENDMETHOD. METHOD zif_abapgit_gui_services~get_hotkeys_ctl. ri_hotkey_ctl = mi_hotkey_ctl. ENDMETHOD. METHOD zif_abapgit_gui_services~get_html_parts. ro_parts = mo_html_parts. ENDMETHOD. METHOD zif_abapgit_gui_services~get_log. IF iv_create_new = abap_true OR mi_common_log IS NOT BOUND. CREATE OBJECT mi_common_log TYPE zcl_abapgit_log. ENDIF. ri_log = mi_common_log. ENDMETHOD. METHOD zif_abapgit_gui_services~register_event_handler. ASSERT ii_event_handler IS BOUND. INSERT ii_event_handler INTO mt_event_handlers INDEX 1. ENDMETHOD. METHOD zif_abapgit_gui_services~register_page_asset. " Maybe forbid registering cacheable existing assets, maybe this is the right place (see also asset_man comments) mi_asset_man->register_asset( iv_url = iv_url iv_type = iv_type iv_mime_name = iv_mime_name iv_inline = iv_inline " This registering will happen after initialization so all cacheable already cached iv_cacheable = abap_false ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GUI_PAGE_TEMPLATE IMPLEMENTATION. METHOD constructor. super->constructor( ). " ... ENDMETHOD. METHOD create. " TODO: replace with name of class (self) DATA lo_component TYPE REF TO zcl_abapgit_gui_page_template. CREATE OBJECT lo_component. ri_page = zcl_abapgit_gui_page_hoc=>create( lo_component ). ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. CASE ii_event->mv_action. " TODO: action handling, refresh is just an example WHEN c_action-refresh. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. WHEN 'xyz'. ASSERT 1 = 1. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. DATA ls_hotkey_action LIKE LINE OF rt_hotkey_actions. ls_hotkey_action-ui_component = c_title. " TODO: define hotkeys ls_hotkey_action-description = 'Refresh'. ls_hotkey_action-action = c_action-refresh. ls_hotkey_action-hotkey = 'r'. INSERT ls_hotkey_action INTO TABLE rt_hotkey_actions. ENDMETHOD. METHOD zif_abapgit_gui_menu_provider~get_menu. " TODO: top level menu ro_toolbar = zcl_abapgit_html_toolbar=>create( )->add( iv_txt = 'Refresh' iv_act = c_action-refresh ). ENDMETHOD. METHOD zif_abapgit_gui_page_title~get_page_title. rv_title = c_title. " Fixed title ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). ri_html = zcl_abapgit_html=>create( ). " TODO: do your rendering ri_html->div( iv_class = 'template' iv_content = 'Hello!' ). ENDMETHOD. METHOD zif_abapgit_html_table~get_row_attrs. " ... in case of table on the page, otherwise remove the interface at all ENDMETHOD. METHOD zif_abapgit_html_table~render_cell. " ... in case of table on the page, otherwise remove the interface at all ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_syntax_xml IMPLEMENTATION. METHOD constructor. super->constructor( ). " Reset indicator for multi-line comments CLEAR gv_comment. " Initialize instances of regular expressions add_rule( iv_regex = c_regex-xml_tag iv_token = c_token-xml_tag iv_style = c_css-xml_tag iv_submatch = 1 ). add_rule( iv_regex = c_regex-attr iv_token = c_token-attr iv_style = c_css-attr ). add_rule( iv_regex = c_regex-attr_val iv_token = c_token-attr_val iv_style = c_css-attr_val ). add_rule( iv_regex = c_regex-comment iv_token = c_token-comment iv_style = c_css-comment ). ENDMETHOD. METHOD order_matches. DATA: lv_match TYPE string, lv_line_len TYPE i, lv_cmmt_end TYPE i, lv_index TYPE sy-tabix, lv_prev_token TYPE c, lv_state TYPE c VALUE 'O'. " O - for open tag; C - for closed tag; FIELD-SYMBOLS: TYPE ty_match, TYPE ty_match. SORT ct_matches BY offset. lv_line_len = strlen( iv_line ). " Check if this is part of multi-line comment and mark it accordingly IF gv_comment = abap_true. READ TABLE ct_matches WITH KEY token = c_token-comment TRANSPORTING NO FIELDS. IF sy-subrc <> 0. CLEAR ct_matches. APPEND INITIAL LINE TO ct_matches ASSIGNING . -token = c_token-comment. -offset = 0. -length = lv_line_len. RETURN. ENDIF. ENDIF. LOOP AT ct_matches ASSIGNING . lv_index = sy-tabix. lv_match = substring( val = iv_line off = -offset len = -length ). CASE -token. WHEN c_token-xml_tag. -text_tag = lv_match. " No other matches between two tags IF -text_tag = '>' AND lv_prev_token = c_token-xml_tag. lv_state = 'C'. -length = -offset - -offset + -length. DELETE ct_matches INDEX lv_index. CONTINUE. " Adjust length and offset of closing tag ELSEIF -text_tag = '>' AND lv_prev_token <> c_token-xml_tag. lv_state = 'C'. IF IS ASSIGNED. -length = -offset - -offset - -length + -length. -offset = -offset + -length. ENDIF. ELSE. lv_state = 'O'. ENDIF. WHEN c_token-comment. IF lv_match = ''. DELETE ct_matches WHERE offset < -offset. -length = -offset + 3. -offset = 0. gv_comment = abap_false. ELSE. lv_cmmt_end = -offset + -length. DELETE ct_matches WHERE offset > -offset AND offset <= lv_cmmt_end. DELETE ct_matches WHERE offset = -offset AND token = c_token-xml_tag. ENDIF. WHEN OTHERS. IF lv_prev_token = c_token-xml_tag. -length = -offset - -offset. " Extend length of the opening tag ENDIF. IF lv_state = 'C'. " Delete all matches between tags DELETE ct_matches INDEX lv_index. CONTINUE. ENDIF. ENDCASE. lv_prev_token = -token. ASSIGN TO . ENDLOOP. "if the last XML tag is not closed, extend it to the end of the tag IF lv_prev_token = c_token-xml_tag AND IS ASSIGNED AND -length = 1 AND -text_tag = '<'. FIND REGEX '<\s*[^\s]*' IN iv_line+-offset MATCH LENGTH -length. IF sy-subrc <> 0. -length = 1. ENDIF. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_syntax_txt IMPLEMENTATION. METHOD constructor. super->constructor( ). " No rules for plain text files ENDMETHOD. METHOD process_line. rv_line = apply_style( iv_line = iv_line iv_class = '' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_syntax_json IMPLEMENTATION. METHOD constructor. super->constructor( ). " Initialize instances of regular expression add_rule( iv_regex = c_regex-keyword iv_token = c_token-keyword iv_style = c_css-keyword ). " Style for keys add_rule( iv_regex = c_regex-text iv_token = c_token-text iv_style = c_css-text ). " Style for values add_rule( iv_regex = '' iv_token = c_token-values iv_style = c_css-values ). " JSONC comments add_rule( iv_regex = c_regex-comment iv_token = c_token-comment iv_style = c_css-comment ). ENDMETHOD. METHOD order_matches. DATA: lv_match TYPE string, lv_count TYPE i, lv_line_len TYPE i, lv_prev_token TYPE c. FIELD-SYMBOLS: TYPE ty_match, TYPE ty_match. " Longest matches SORT ct_matches BY offset length DESCENDING. lv_line_len = strlen( iv_line ). LOOP AT ct_matches ASSIGNING . " Delete matches after open text match IF lv_prev_token = c_token-text AND -token <> c_token-text. CLEAR -token. CONTINUE. ENDIF. lv_match = substring( val = iv_line off = -offset len = -length ). IF -token = c_token-text. -text_tag = lv_match. IF lv_prev_token = c_token-text. IF -text_tag = -text_tag. -length = -offset + -length - -offset. CLEAR lv_prev_token. ENDIF. CLEAR -token. CONTINUE. ENDIF. ENDIF. lv_prev_token = -token. ASSIGN TO . ENDLOOP. DELETE ct_matches WHERE token IS INITIAL. " Switch style of second text match to values LOOP AT ct_matches ASSIGNING WHERE token = c_token-text. lv_count = lv_count + 1. IF lv_count >= 2. -token = c_token-values. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_syntax_js IMPLEMENTATION. METHOD class_constructor. init_keywords( ). ENDMETHOD. METHOD constructor. super->constructor( ). " Reset indicator for multi-line comments CLEAR gv_comment. " Initialize instances of regular expression add_rule( iv_regex = c_regex-keyword iv_token = c_token-keyword iv_style = c_css-keyword ). add_rule( iv_regex = c_regex-comment iv_token = c_token-comment iv_style = c_css-comment ). add_rule( iv_regex = c_regex-text iv_token = c_token-text iv_style = c_css-text ). " Styles for keywords add_rule( iv_regex = '' iv_token = c_token-variables iv_style = c_css-variables ). ENDMETHOD. METHOD init_keywords. DATA: lv_keywords TYPE string. CLEAR gt_keywords. " 1) General keywords lv_keywords = 'alert|all|body|break|bytetostring|case|continue|default|delete|do|document|else|event|export|for|function|if|' && 'import|in|innerhtml|isnan|item|mimetypes|navigator|new|onabort|onblur|onchange|onclick|ondblclick|ondragdrop|' && 'onerror|onfocus|onkeydown|onkeypress|onkeyup|onload|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|' && 'onmove|onreset|onselect|onsubmit|onunload|onresize|options|parsefloat|parseint|prototype|return|screen|switch|' && 'unit|var|void|while|window|with|anchor|applet|area|button|checkbox|fileupload|form|frame|hidden|link|mimetype|' && 'password|plugin|radio|reset|select|submit|text|textarea|abs|acos|alert|anchor|asin|atan|atan2|back|big|blink|' && 'blur|bold|captureevents|ceil|charat|charcodeat|clearinterval|cleartimeout|click|close|concat|confirm|cos|' && 'disableexternalcapture|enableexternalcapture|eval|exp|find|fixed|floor|focus|fontcolor|fontsize|forward|' && 'fromcharcode|getdate|getday|getelementbyid|gethours|getminutes|getmonth|getoptionvalue|getoptionvaluecount|' && 'getseconds|getselection|gettime|gettimezoneoffset|getyear|go|handleevent|home|indexof|italics|javaenabled|join|' && 'lastindexof|link|load|log|match|max|min|moveabove|movebelow|moveby|moveto|movetoabsolute|open|parse|plugins|' && 'pop|pow|preference|print|prompt|push|random|refresh|releaseevents|reload|replace|reset|resizeby|resizeto|' && 'reverse|round|routeevent|scroll|scrollby|scrollto|search|select|setdate|sethours|setinterval|setminutes|' && 'setmonth|setseconds|settime|settimeout|setyear|shift|sin|slice|small|sort|splice|split|sqrt|stop|strike|sub|' && 'submit|substr|substring|sup|taintenabled|tan|togmtstring|tolocalestring|tolowercase|tostring|touppercase|' && 'unshift|unwatch|utc|valueof|watch|write|writeln|e|ln10|ln2|log10e|log2e|max_value|min_value|negative_infinity|' && 'nan|pi|positive_infinity|url|above|action|alinkcolor|anchors|appcodename|appname|appversion|applets|arguments|' && 'arity|availheight|availwidth|background|backgroundcolor|below|bgcolor|border|bottom|caller|cancelbubble|' && 'checked|clientheight|clientwidth|clientx|clienty|clip|closed|color|colordepth|complete|constructor|cookie|' && 'count|current|defaultchecked|defaultselected|defaultstatus|defaultvalue|description|display|document|domain|' && 'elements|embeds|enabledplugin|encoding|false|fgcolor|filename|form|formname|forms|frames|hash|height|history|' && 'host|hostname|href|hspace|images|innerheight|innerwidth|language|lastmodified|layers|left|length|linkcolor|' && 'links|location|locationbar|lowsrc|menubar|method|mimetypes|name|next|null|offsetheight|offsetleft|offsetparent|' && 'offsetwidth|opener|outerheight|outerwidth|pagex|pagexoffset|pagey|pageyoffset|parent|parentlayer|pathname|' && 'personalbar|pixeldepth|platform|plugins|port|poswidth|previous|protocol|prototype|referrer|right|scrolltop|' && 'scrollbars|search|selected|selectedindex|self|siblingabove|siblingbelow|src|srcelement|status|statusbar|style|' && 'suffixes|tags|target|text|this|title|toolbar|top|true|type|useragent|value|visibility|vlinkcolor|vspace|width|' && 'window|zindex'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-keyword ). " 2) Variable types lv_keywords = 'array|boolean|date|function|image|layer|math|number|object|option|regexp|string'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-variables ). ENDMETHOD. METHOD insert_keywords. DATA: lt_keywords TYPE STANDARD TABLE OF string, ls_keyword TYPE ty_keyword. FIELD-SYMBOLS: TYPE any. SPLIT iv_keywords AT '|' INTO TABLE lt_keywords. LOOP AT lt_keywords ASSIGNING . CLEAR ls_keyword. ls_keyword-keyword = . ls_keyword-token = iv_token. INSERT ls_keyword INTO TABLE gt_keywords. ENDLOOP. ENDMETHOD. METHOD is_keyword. DATA lv_str TYPE string. lv_str = to_lower( iv_chunk ). READ TABLE gt_keywords WITH TABLE KEY keyword = lv_str TRANSPORTING NO FIELDS. rv_yes = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD order_matches. DATA: lv_match TYPE string, lv_line_len TYPE i, lv_cmmt_end TYPE i, lv_prev_end TYPE i, lv_prev_token TYPE c. FIELD-SYMBOLS: TYPE ty_match, TYPE ty_match, TYPE ty_keyword. " Longest matches SORT ct_matches BY offset length DESCENDING. lv_line_len = strlen( iv_line ). " Check if this is part of multi-line comment and mark it accordingly IF gv_comment = abap_true. READ TABLE ct_matches WITH KEY token = c_token-comment TRANSPORTING NO FIELDS. IF sy-subrc <> 0. CLEAR ct_matches. APPEND INITIAL LINE TO ct_matches ASSIGNING . -token = c_token-comment. -offset = 0. -length = lv_line_len. RETURN. ENDIF. ENDIF. LOOP AT ct_matches ASSIGNING . " Delete matches after open text match IF lv_prev_token = c_token-text AND -token <> c_token-text. CLEAR -token. CONTINUE. ENDIF. lv_match = substring( val = iv_line off = -offset len = -length ). CASE -token. WHEN c_token-keyword. " Skip keyword that's part of previous (longer) keyword IF -offset < lv_prev_end. CLEAR -token. CONTINUE. ENDIF. " Map generic keyword to specific token lv_match = to_lower( lv_match ). READ TABLE gt_keywords ASSIGNING WITH TABLE KEY keyword = lv_match. IF sy-subrc = 0. -token = -token. ENDIF. WHEN c_token-comment. IF lv_match = '/*'. DELETE ct_matches WHERE offset > -offset. -length = lv_line_len - -offset. gv_comment = abap_true. ELSEIF lv_match = '//'. DELETE ct_matches WHERE offset > -offset. -length = lv_line_len - -offset. ELSEIF lv_match = '*/'. DELETE ct_matches WHERE offset < -offset. -length = -offset + 2. -offset = 0. gv_comment = abap_false. ELSE. lv_cmmt_end = -offset + -length. DELETE ct_matches WHERE offset > -offset AND offset <= lv_cmmt_end. ENDIF. WHEN c_token-text. -text_tag = lv_match. IF lv_prev_token = c_token-text. IF -text_tag = -text_tag. -length = -offset + -length - -offset. CLEAR lv_prev_token. ENDIF. CLEAR -token. CONTINUE. ENDIF. ENDCASE. lv_prev_token = -token. lv_prev_end = -offset + -length. ASSIGN TO . ENDLOOP. DELETE ct_matches WHERE token IS INITIAL. ENDMETHOD. METHOD parse_line. "REDEFINITION DATA lv_index TYPE i. FIELD-SYMBOLS LIKE LINE OF rt_matches. rt_matches = super->parse_line( iv_line ). " Remove non-keywords LOOP AT rt_matches ASSIGNING WHERE token = c_token-keyword. lv_index = sy-tabix. IF abap_false = is_keyword( substring( val = iv_line off = -offset len = -length ) ). CLEAR -token. ENDIF. ENDLOOP. DELETE rt_matches WHERE token IS INITIAL. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_syntax_highlighter IMPLEMENTATION. METHOD add_rule. DATA ls_rule LIKE LINE OF mt_rules. IF NOT iv_regex IS INITIAL. CREATE OBJECT ls_rule-regex EXPORTING pattern = iv_regex ignore_case = abap_true. ENDIF. ls_rule-token = iv_token. ls_rule-style = iv_style. ls_rule-relevant_submatch = iv_submatch. APPEND ls_rule TO mt_rules. ENDMETHOD. METHOD apply_style. DATA lv_escaped TYPE string. lv_escaped = escape( val = iv_line format = cl_abap_format=>e_html_text ). lv_escaped = show_hidden_chars( lv_escaped ). IF iv_class IS NOT INITIAL. rv_line = |{ lv_escaped }|. ELSE. rv_line = lv_escaped. ENDIF. ENDMETHOD. METHOD extend_matches. DATA: lv_line_len TYPE i, lv_last_pos TYPE i VALUE 0, lv_length TYPE i, ls_match TYPE ty_match. FIELD-SYMBOLS TYPE ty_match. lv_line_len = strlen( iv_line ). SORT ct_matches BY offset. " Add entries referring to parts of text that should not be formatted LOOP AT ct_matches ASSIGNING . IF -offset > lv_last_pos. lv_length = -offset - lv_last_pos. ls_match-token = c_token_none. ls_match-offset = lv_last_pos. ls_match-length = lv_length. INSERT ls_match INTO ct_matches INDEX sy-tabix. ENDIF. lv_last_pos = -offset + -length. ENDLOOP. " Add remainder of the string IF lv_line_len > lv_last_pos. lv_length = lv_line_len - lv_last_pos. ls_match-token = c_token_none. ls_match-offset = lv_last_pos. ls_match-length = lv_length. APPEND ls_match TO ct_matches. ENDIF. ENDMETHOD. METHOD format_line. DATA: lv_chunk TYPE string, ls_rule LIKE LINE OF mt_rules. FIELD-SYMBOLS TYPE ty_match. LOOP AT it_matches ASSIGNING . lv_chunk = substring( val = iv_line off = -offset len = -length ). CLEAR ls_rule. " Failed read equals no style READ TABLE mt_rules INTO ls_rule WITH KEY token = -token. lv_chunk = apply_style( iv_line = lv_chunk iv_class = ls_rule-style ). rv_line = rv_line && lv_chunk. ENDLOOP. ENDMETHOD. METHOD is_whitespace. DATA: lv_whitespace TYPE string. "/^\s+$/ lv_whitespace = ` ` && cl_abap_char_utilities=>horizontal_tab && cl_abap_char_utilities=>cr_lf. rv_result = boolc( iv_string CO lv_whitespace ). ENDMETHOD. METHOD order_matches. ENDMETHOD. METHOD parse_line. DATA: lo_regex TYPE REF TO cl_abap_regex, lo_matcher TYPE REF TO cl_abap_matcher, lt_result TYPE match_result_tab, ls_match TYPE ty_match. FIELD-SYMBOLS: LIKE LINE OF mt_rules, TYPE match_result, LIKE LINE OF -submatches. " Process syntax-dependent regex table and find all matches LOOP AT mt_rules ASSIGNING WHERE regex IS BOUND. lo_regex = -regex. lo_matcher = lo_regex->create_matcher( text = iv_line ). lt_result = lo_matcher->find_all( ). " Save matches into custom table with predefined tokens LOOP AT lt_result ASSIGNING . CLEAR: ls_match. IF -relevant_submatch = 0. ls_match-token = -token. ls_match-offset = -offset. ls_match-length = -length. APPEND ls_match TO rt_matches. ELSE. READ TABLE -submatches ASSIGNING INDEX -relevant_submatch. "submatch might be empty if only discarded parts matched IF sy-subrc = 0 AND -offset >= 0 AND -length > 0. ls_match-token = -token. ls_match-offset = -offset. ls_match-length = -length. APPEND ls_match TO rt_matches. ENDIF. ENDIF. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD process_line. DATA: lt_matches TYPE ty_match_tt. IF iv_line IS INITIAL OR is_whitespace( iv_line ) = abap_true. rv_line = show_hidden_chars( iv_line ). RETURN. ENDIF. lt_matches = parse_line( iv_line ). order_matches( EXPORTING iv_line = iv_line CHANGING ct_matches = lt_matches ). extend_matches( EXPORTING iv_line = iv_line CHANGING ct_matches = lt_matches ). rv_line = format_line( iv_line = iv_line it_matches = lt_matches ). ENDMETHOD. METHOD set_hidden_chars. mv_hidden_chars = iv_hidden_chars. ENDMETHOD. METHOD show_hidden_chars. DATA lv_bom TYPE x LENGTH 3. rv_line = iv_line. IF mv_hidden_chars = abap_true. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>horizontal_tab IN rv_line WITH ' → '. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf(1) IN rv_line WITH '¶'. REPLACE ALL OCCURRENCES OF ` ` IN rv_line WITH '·'. REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>form_feed IN rv_line WITH ''. IF strlen( rv_line ) BETWEEN 1 AND 2. TRY. lv_bom = zcl_abapgit_convert=>string_to_xstring( rv_line ). CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. IF lv_bom(2) = cl_abap_char_utilities=>byte_order_mark_big. rv_line = ''. " UTF-16 big-endian (FE FF) ENDIF. IF lv_bom(2) = cl_abap_char_utilities=>byte_order_mark_little. rv_line = ''. " UTF-16 little-endian (FF FE) ENDIF. IF lv_bom(3) = cl_abap_char_utilities=>byte_order_mark_utf8. rv_line = '¤'. " UTF-8 (EF BB BF) ENDIF. ENDIF. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_syntax_factory IMPLEMENTATION. METHOD create. " Create instance of highlighter dynamically dependent on syntax type IF iv_filename CP '*.abap'. CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_abap. ELSEIF iv_filename CP '*.xml' OR iv_filename CP '*.html'. CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_xml. ELSEIF iv_filename CP '*.css'. CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_css. ELSEIF iv_filename CP '*.js'. CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_js. ELSEIF iv_filename CP '*.json' OR iv_filename CP '*.jsonc'. CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_json. ELSEIF iv_filename CP '*.txt' OR iv_filename CP '*.ini' OR iv_filename CP '*.text'. CREATE OBJECT ro_instance TYPE zcl_abapgit_syntax_txt. ELSE. CLEAR ro_instance. ENDIF. IF ro_instance IS BOUND. ro_instance->set_hidden_chars( iv_hidden_chars ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_syntax_css IMPLEMENTATION. METHOD class_constructor. init_keywords( ). ENDMETHOD. METHOD constructor. super->constructor( ). " Reset indicator for multi-line comments CLEAR gv_comment. " Initialize instances of regular expression add_rule( iv_regex = c_regex-keyword iv_token = c_token-keyword iv_style = c_css-keyword ). add_rule( iv_regex = c_regex-comment iv_token = c_token-comment iv_style = c_css-comment ). add_rule( iv_regex = c_regex-text iv_token = c_token-text iv_style = c_css-text ). add_rule( iv_regex = c_regex-selectors iv_token = c_token-selectors iv_style = c_css-selectors ). add_rule( iv_regex = c_regex-units iv_token = c_token-units iv_style = c_css-units ). " Styles for keywords add_rule( iv_regex = '' iv_token = c_token-html iv_style = c_css-html ). add_rule( iv_regex = '' iv_token = c_token-properties iv_style = c_css-properties ). add_rule( iv_regex = '' iv_token = c_token-values iv_style = c_css-values ). add_rule( iv_regex = '' iv_token = c_token-functions iv_style = c_css-functions ). add_rule( iv_regex = '' iv_token = c_token-colors iv_style = c_css-colors ). add_rule( iv_regex = '' iv_token = c_token-extensions iv_style = c_css-extensions ). add_rule( iv_regex = '' iv_token = c_token-at_rules iv_style = c_css-at_rules ). ENDMETHOD. METHOD init_keywords. DATA: lv_keywords TYPE string. CLEAR gt_keywords. " 1) CSS Properties lv_keywords = 'align-content|align-items|align-self|animation|animation-delay|animation-direction|animation-duration|' && 'animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|' && 'backface-visibility|background|background-attachment|background-blend-mode|background-clip|background-color|' && 'background-image|background-origin|background-position|background-repeat|background-size|border|' && 'border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|' && 'border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|' && 'border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|' && 'border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|' && 'border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|' && 'border-top-style|border-top-width|border-width|box-decoration-break|box-shadow|box-sizing|caption-side|' && 'caret-color|clear|clip|color|column-count|column-fill|column-gap|column-rule|column-rule-color|' && 'column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|' && 'counter-reset|cursor|direction|display|empty-cells|filter|flex|flex-basis|flex-direction|flex-flow|' && 'flex-grow|flex-shrink|flex-wrap|float|font|font-family|font-kerning|font-size|font-size-adjust|' && 'font-stretch|font-style|font-variant|font-weight|grid|grid-area|grid-auto-columns|grid-auto-flow|' && 'grid-auto-rows|grid-column|grid-column-end|grid-column-gap|grid-column-start|grid-gap|grid-row|' && 'grid-row-end|grid-row-gap|grid-row-start|grid-template|grid-template-areas|grid-template-columns|' && 'grid-template-rows|hanging-punctuation|height|hyphens|isolation|justify-content|' && 'letter-spacing|line-height|list-style|list-style-image|list-style-position|list-style-type|margin|' && 'margin-bottom|margin-left|margin-right|margin-top|max-height|max-width|media|min-height|min-width|' && 'mix-blend-mode|object-fit|object-position|opacity|order|outline|outline-color|outline-offset|' && 'outline-style|outline-width|overflow|overflow-x|overflow-y|padding|padding-bottom|padding-left|' && 'padding-right|padding-top|page-break-after|page-break-before|page-break-inside|perspective|' && 'perspective-origin|pointer-events|position|quotes|resize|scroll-behavior|tab-size|table-layout|' && 'text-align|text-align-last|text-decoration|text-decoration-color|text-decoration-line|' && 'text-decoration-style|text-indent|text-justify|text-overflow|text-rendering|text-shadow|text-transform|' && 'transform|transform-origin|transform-style|transition|transition-delay|transition-duration|' && 'transition-property|transition-timing-function|unicode-bidi|user-select|vertical-align|visibility|' && 'white-space|width|word-break|word-spacing|word-wrap|writing-mode|z-index'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-properties ). " 2) CSS Values lv_keywords = 'absolute|all|auto|block|bold|border-box|both|bottom|center|counter|cover|dashed|fixed|hidden|important|' && 'inherit|initial|inline-block|italic|left|max-content|middle|min-content|no-repeat|none|normal|pointer|' && 'relative|rem|right|solid|table-cell|text|top|transparent|underline|url'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-values ). " 3) CSS Selectors lv_keywords = ':active|::after|::before|:checked|:disabled|:empty|:enabled|:first-child|::first-letter|::first-line|' && ':first-of-type|:focus|:hover|:lang|:last-child|:last-of-type|:link|:not|:nth-child|:nth-last-child|' && ':nth-last-of-type|:nth-of-type|:only-child|:only-of-type|:root|:target|:visited'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-selectors ). " 4) CSS Functions lv_keywords = 'attr|calc|cubic-bezier|hsl|hsla|linear-gradient|radial-gradient|repeating-linear-gradient|' && 'repeating-radial-gradient|rgb|rgba|rotate|scale|translateX|translateY|var'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-functions ). " 5) CSS Colors lv_keywords = '#|aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|' && 'burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|' && 'darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|' && 'darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|' && 'deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|' && 'ghostwhite|gold|goldenrod|gray|green|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|' && 'lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|' && 'lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|' && 'lightslategrey|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|' && 'mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|' && 'mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|' && 'orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|' && 'peru|pink|plum|powderblue|purple|rebeccapurple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|' && 'seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|' && 'tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-colors ). " 6) CSS Extensions lv_keywords = 'moz|moz-binding|moz-border-bottom-colors|moz-border-left-colors|moz-border-right-colors|' && 'moz-border-top-colors|moz-box-align|moz-box-direction|moz-box-flex|moz-box-ordinal-group|' && 'moz-box-orient|moz-box-pack|moz-box-shadow|moz-context-properties|moz-float-edge|' && 'moz-force-broken-image-icon|moz-image-region|moz-orient|moz-osx-font-smoothing|' && 'moz-outline-radius|moz-outline-radius-bottomleft|moz-outline-radius-bottomright|' && 'moz-outline-radius-topleft|moz-outline-radius-topright|moz-stack-sizing|moz-system-metric|' && 'moz-transform|moz-transform-origin|moz-transition|moz-transition-delay|moz-user-focus|' && 'moz-user-input|moz-user-modify|moz-window-dragging|moz-window-shadow|ms|ms-accelerator|' && 'ms-block-progression|ms-content-zoom-chaining|ms-content-zoom-limit|' && 'ms-content-zoom-limit-max|ms-content-zoom-limit-min|ms-content-zoom-snap|' && 'ms-content-zoom-snap-points|ms-content-zoom-snap-type|ms-content-zooming|ms-filter|' && 'ms-flow-from|ms-flow-into|ms-high-contrast-adjust|ms-hyphenate-limit-chars|' && 'ms-hyphenate-limit-lines|ms-hyphenate-limit-zone|ms-ime-align|ms-overflow-style|' && 'ms-scroll-chaining|ms-scroll-limit|ms-scroll-limit-x-max|ms-scroll-limit-x-min|' && 'ms-scroll-limit-y-max|ms-scroll-limit-y-min|ms-scroll-rails|ms-scroll-snap-points-x|' && 'ms-scroll-snap-points-y|ms-scroll-snap-x|ms-scroll-snap-y|ms-scroll-translation|' && 'ms-scrollbar-3dlight-color|ms-scrollbar-arrow-color|ms-scrollbar-base-color|' && 'ms-scrollbar-darkshadow-color|ms-scrollbar-face-color|ms-scrollbar-highlight-color|' && 'ms-scrollbar-shadow-color|ms-scrollbar-track-color|ms-transform|ms-text-autospace|' && 'ms-touch-select|ms-wrap-flow|ms-wrap-margin|ms-wrap-through|o|o-transform|webkit|' && 'webkit-animation-trigger|webkit-app-region|webkit-appearance|webkit-aspect-ratio|' && 'webkit-backdrop-filter|webkit-background-composite|webkit-border-after|' && 'webkit-border-after-color|webkit-border-after-style|webkit-border-after-width|' && 'webkit-border-before|webkit-border-before-color|webkit-border-before-style|' && 'webkit-border-before-width|webkit-border-end|webkit-border-end-color|' && 'webkit-border-end-style|webkit-border-end-width|webkit-border-fit|' && 'webkit-border-horizontal-spacing|webkit-border-radius|webkit-border-start|' && 'webkit-border-start-color|webkit-border-start-style|webkit-border-start-width|' && 'webkit-border-vertical-spacing|webkit-box-align|webkit-box-direction|webkit-box-flex|' && 'webkit-box-flex-group|webkit-box-lines|webkit-box-ordinal-group|webkit-box-orient|' && 'webkit-box-pack|webkit-box-reflect|webkit-box-shadow|webkit-column-axis|' && 'webkit-column-break-after|webkit-column-break-before|webkit-column-break-inside|' && 'webkit-column-progression|webkit-cursor-visibility|webkit-dashboard-region|' && 'webkit-font-size-delta|webkit-font-smoothing|webkit-highlight|webkit-hyphenate-character|' && 'webkit-hyphenate-limit-after|webkit-hyphenate-limit-before|webkit-hyphenate-limit-lines|' && 'webkit-initial-letter|webkit-line-align|webkit-line-box-contain|webkit-line-clamp|' && 'webkit-line-grid|webkit-line-snap|webkit-locale|webkit-logical-height|' && 'webkit-logical-width|webkit-margin-after|webkit-margin-after-collapse|' && 'webkit-margin-before|webkit-margin-before-collapse|webkit-margin-bottom-collapse|' && 'webkit-margin-collapse|webkit-margin-end|webkit-margin-start|webkit-margin-top-collapse|' && 'webkit-marquee|webkit-marquee-direction|webkit-marquee-increment|' && 'webkit-marquee-repetition|webkit-marquee-speed|webkit-marquee-style|webkit-mask-box-image|' && 'webkit-mask-box-image-outset|webkit-mask-box-image-repeat|webkit-mask-box-image-slice|' && 'webkit-mask-box-image-source|webkit-mask-box-image-width|webkit-mask-repeat-x|' && 'webkit-mask-repeat-y|webkit-mask-source-type|webkit-max-logical-height|' && 'webkit-max-logical-width|webkit-min-logical-height|webkit-min-logical-width|' && 'webkit-nbsp-mode|webkit-padding-after|webkit-padding-before|webkit-padding-end|' && 'webkit-padding-start|webkit-perspective-origin-x|webkit-perspective-origin-y|' && 'webkit-print-color-adjust|webkit-rtl-ordering|webkit-svg-shadow|' && 'webkit-tap-highlight-color|webkit-text-combine|webkit-text-decoration-skip|' && 'webkit-text-decorations-in-effect|webkit-text-fill-color|webkit-text-security|' && 'webkit-text-stroke|webkit-text-stroke-color|webkit-text-stroke-width|webkit-text-zoom|' && 'webkit-transform|webkit-transform-origin|webkit-transform-origin-x|' && 'webkit-transform-origin-y|webkit-transform-origin-z|webkit-transition|' && 'webkit-transition-delay|webkit-user-drag|webkit-user-modify|overflow-clip-box|' && 'overflow-clip-box-block|overflow-clip-box-inline|zoom'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-extensions ). " 6) CSS At-Rules lv_keywords = '@|charset|counter-style|font-face|import|keyframes'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-at_rules ). " 7) HTML tag lv_keywords = 'doctyype|a|abbr|acronym|address|applet|area|b|base|basefont|bdo|bgsound|big|blink|blockquote|' && 'body|br|button|caption|center|cite|code|col|colgroup|dd|del|dfn|dir|div|dl|dt|em|embed|fieldset|' && 'font|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|hr|html|i|iframe|ilayer|img|input|ins|isindex|' && 'kbd|keygen|label|layer|legend|li|link|listing|map|menu|meta|multicol|nobr|noembed|noframes|' && 'nolayer|noscript|object|ol|optgroup|option|p|param|plaintext|pre|q|s|samp|script|select|server|' && 'small|sound|spacer|span|strike|strong|style|sub|sup|tbody|textarea|title|tt|u|ul|var|wbr|xmp|' && 'xsl|xml|accesskey|action|align|alink|alt|background|balance|behavior|bgcolor|bgproperties|' && 'border|bordercolor|bordercolordark|bordercolorlight|bottommargin|checked|class|classid|clear|' && 'code|codebase|codetype|color|cols|colspan|compact|content|controls|coords|data|datafld|' && 'dataformatas|datasrc|direction|disabled|dynsrc|enctype|event|face|for|frame|frameborder|' && 'framespacing|height|hidden|href|hspace|http-equiv|id|ismap|lang|language|leftmargin|link|loop|' && 'lowsrc|marginheight|marginwidth|maxlength|mayscript|method|methods|multiple|name|nohref|' && 'noresize|noshade|nowrap|palette|pluginspage|public|readonly|rel|rev|rightmargin|rows|rowspan|' && 'rules|scroll|scrollamount|scrolldelay|scrolling|selected|shape|size|span|src|start|style|' && 'tabindex|target|text|title|topmargin|truespeed|type|url|urn|usemap|valign|value|vlink|volume|' && 'vrml|vspace|width|wrap|apply-templates|attribute|choose|comment|define-template-set|' && 'entity-ref|eval|expr|for-each|if|match|no-entities|node-name|order-by|otherwise|select|' && 'stylesheet|template|test|value-of|version|when|xmlns|xsl|cellpadding|cellspacing|table|td|' && 'tfoot|th|thead|tr'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-html ). ENDMETHOD. METHOD insert_keywords. DATA: lt_keywords TYPE STANDARD TABLE OF string, ls_keyword TYPE ty_keyword. FIELD-SYMBOLS: TYPE any. SPLIT iv_keywords AT '|' INTO TABLE lt_keywords. LOOP AT lt_keywords ASSIGNING . CLEAR ls_keyword. ls_keyword-keyword = . ls_keyword-token = iv_token. INSERT ls_keyword INTO TABLE gt_keywords. ENDLOOP. ENDMETHOD. METHOD is_keyword. DATA lv_str TYPE string. lv_str = to_lower( iv_chunk ). READ TABLE gt_keywords WITH TABLE KEY keyword = lv_str TRANSPORTING NO FIELDS. rv_yes = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD order_matches. DATA: lv_match TYPE string, lv_line_len TYPE i, lv_cmmt_end TYPE i, lv_prev_end TYPE i, lv_prev_token TYPE c. FIELD-SYMBOLS: TYPE ty_match, TYPE ty_match, TYPE ty_keyword. " Longest matches SORT ct_matches BY offset length DESCENDING. lv_line_len = strlen( iv_line ). " Check if this is part of multi-line comment and mark it accordingly IF gv_comment = abap_true. READ TABLE ct_matches WITH KEY token = c_token-comment TRANSPORTING NO FIELDS. IF sy-subrc <> 0. CLEAR ct_matches. APPEND INITIAL LINE TO ct_matches ASSIGNING . -token = c_token-comment. -offset = 0. -length = lv_line_len. RETURN. ENDIF. ENDIF. LOOP AT ct_matches ASSIGNING . " Delete matches after open text match IF lv_prev_token = c_token-text AND -token <> c_token-text. CLEAR -token. CONTINUE. ENDIF. lv_match = substring( val = iv_line off = -offset len = -length ). CASE -token. WHEN c_token-keyword. " Skip keyword that's part of previous (longer) keyword IF -offset < lv_prev_end. CLEAR -token. CONTINUE. ENDIF. " Map generic keyword to specific CSS token lv_match = to_lower( lv_match ). READ TABLE gt_keywords ASSIGNING WITH TABLE KEY keyword = lv_match. IF sy-subrc = 0. -token = -token. ENDIF. WHEN c_token-comment. IF lv_match = '/*'. DELETE ct_matches WHERE offset > -offset. -length = lv_line_len - -offset. gv_comment = abap_true. ELSEIF lv_match = '*/'. DELETE ct_matches WHERE offset < -offset. -length = -offset + 2. -offset = 0. gv_comment = abap_false. ELSE. lv_cmmt_end = -offset + -length. DELETE ct_matches WHERE offset > -offset AND offset <= lv_cmmt_end. ENDIF. WHEN c_token-text. -text_tag = lv_match. IF lv_prev_token = c_token-text. IF -text_tag = -text_tag. -length = -offset + -length - -offset. CLEAR lv_prev_token. ENDIF. CLEAR -token. CONTINUE. ENDIF. ENDCASE. lv_prev_token = -token. lv_prev_end = -offset + -length. ASSIGN TO . ENDLOOP. DELETE ct_matches WHERE token IS INITIAL. ENDMETHOD. METHOD parse_line. "REDEFINITION DATA lv_index TYPE i. FIELD-SYMBOLS LIKE LINE OF rt_matches. rt_matches = super->parse_line( iv_line ). " Remove non-keywords LOOP AT rt_matches ASSIGNING WHERE token = c_token-keyword. lv_index = sy-tabix. IF abap_false = is_keyword( substring( val = iv_line off = -offset len = -length ) ). CLEAR -token. ENDIF. ENDLOOP. DELETE rt_matches WHERE token IS INITIAL. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_SYNTAX_ABAP IMPLEMENTATION. METHOD class_constructor. init_keywords( ). ENDMETHOD. METHOD constructor. super->constructor( ). " Initialize instances of regular expression add_rule( iv_regex = c_regex-keyword iv_token = c_token-keyword iv_style = c_css-keyword ). add_rule( iv_regex = c_regex-comment iv_token = c_token-comment iv_style = c_css-comment ). add_rule( iv_regex = c_regex-text iv_token = c_token-text iv_style = c_css-text ). ENDMETHOD. METHOD init_keywords. DATA: lv_keywords TYPE string, lt_keywords TYPE STANDARD TABLE OF string. lv_keywords = '&&|?TO|ABAP-SOURCE|ABBREVIATED|ABS|ABSTRACT|ACCEPT|ACCEPTING' && '|ACCORDING|ACOS|ACTIVATION|ACTUAL|ADD|ADD-CORRESPONDING|ADJACENT|AFTER|ALIAS' && '|ALIASES|ALIGN|ALL|ALLOCATE|ALPHA|ANALYSIS|ANALYZER|AND|ANY|APPEND|APPENDAGE' && '|APPENDING|APPLICATION|ARCHIVE|AREA|ARITHMETIC|AS|ASCENDING|ASIN|ASPECT|ASSERT' && '|ASSIGN|ASSIGNED|ASSIGNING|ASSOCIATION|ASYNCHRONOUS|AT|ATAN|ATTRIBUTES|AUTHORITY' && '|AUTHORITY-CHECK|AVG|BACK|BACKGROUND|BACKUP|BACKWARD|BADI|BASE|BEFORE|BEGIN' && '|BETWEEN|BIG|BINARY|BIT|BIT-AND|BIT-NOT|BIT-OR|BIT-XOR|BLACK|BLANK' && '|BLANKS|BLOB|BLOCK|BLOCKS|BLUE|BOUND|BOUNDARIES|BOUNDS|BOXED|BREAK-POINT|BT' && '|BUFFER|BY|BYPASSING|BYTE|BYTE-CA|BYTE-CN|BYTE-CO|BYTE-CS|BYTE-NA|BYTE-NS' && '|BYTE-ORDER|C|CA|CALL|CALLING|CASE|CAST|CASTING|CATCH|CEIL|CENTER|CENTERED' && '|CHAIN|CHAIN-INPUT|CHAIN-REQUEST|CHANGE|CHANGING|CHANNELS|CHARACTER|CHARLEN' && '|CHAR-TO-HEX|CHECK|CHECKBOX|CI_|CIRCULAR|CLASS|CLASS-CODING|CLASS-DATA' && '|CLASS-EVENTS|CLASS-METHODS|CLASS-POOL|CLEANUP|CLEAR|CLIENT|CLOB|CLOCK|CLOSE' && '|CN|CO|COALESCE|CODE|CODING|COL_BACKGROUND|COL_GROUP|COL_HEADING|COL_KEY' && '|COL_NEGATIVE|COL_NORMAL|COL_POSITIVE|COL_TOTAL|COLLECT|COLOR|COLUMN|COLUMNS' && '|COMMENT|COMMENTS|COMMIT|COMMON|COMMUNICATION|COMPARING|COMPONENT|COMPONENTS' && '|COMPRESSION|COMPUTE|CONCAT|CONCATENATE|COND|CONDENSE|CONDITION|CONNECT' && '|CONNECTION|CONSTANTS|CONTEXT|CONTEXTS|CONTINUE|CONTROL|CONTROLS|CONV|CONVERSION' && '|CONVERT|COPIES|COPY|CORRESPONDING|COS|COSH|COUNT|COUNTRY|COVER|CP|CPI|CREATE' && '|CREATING|CRITICAL|CS|CURRENCY|CURRENCY_CONVERSION|CURRENT|CURSOR|CURSOR-SELECTION' && '|CUSTOMER|CUSTOMER-FUNCTION|DANGEROUS|DATA|DATABASE|DATAINFO|DATASET|DATE' && '|DAYLIGHT|DBMAXLEN|DD/MM/YY|DD/MM/YYYY|DDMMYY|DEALLOCATE|DECIMAL_SHIFT|DECIMALS' && '|DECLARATIONS|DEEP|DEFAULT|DEFERRED|DEFINE|DEFINING|DEFINITION|DELETE|DELETING' && '|DEMAND|DEPARTMENT|DESCENDING|DESCRIBE|DESTINATION|DETAIL|DIALOG|DIRECTORY' && '|DISCONNECT|DISPLAY|DISPLAY-MODE|DISTANCE|DISTINCT|DIV|DIVIDE|DIVIDE-CORRESPONDING' && '|DIVISION|DO|DUMMY|DUPLICATE|DUPLICATES|DURATION|DURING|DYNAMIC|DYNPRO' && '|EDIT|EDITOR-CALL|ELSE|ELSEIF|EMPTY|ENABLED|ENABLING|ENCODING|END|ENDAT|ENDCASE' && '|ENDCATCH|ENDCHAIN|ENDCLASS|ENDDO|ENDENHANCEMENT|END-ENHANCEMENT-SECTION' && '|ENDEXEC|ENDFORM|ENDFUNCTION|ENDIAN|ENDIF|ENDING|ENDINTERFACE' && '|END-LINES|ENDLOOP|ENDMETHOD|ENDMODULE|END-OF-DEFINITION|END-OF-FILE' && '|END-OF-PAGE|END-OF-SELECTION|ENDON|ENDPROVIDE|ENDSELECT|ENDTRY|ENDWHILE' && '|ENGINEERING|ENHANCEMENT|ENHANCEMENT-POINT|ENHANCEMENTS|ENHANCEMENT-SECTION' && '|ENTRIES|ENTRY|ENVIRONMENT|EQ|EQUIV|ERRORMESSAGE|ERRORS|ESCAPE|ESCAPING' && '|EVENT|EVENTS|EXACT|EXCEPT|EXCEPTION|EXCEPTIONS|EXCEPTION-TABLE|EXCLUDE|EXCLUDING' && '|EXEC|EXECUTE|EXISTS|EXIT|EXIT-COMMAND|EXP|EXPAND|EXPANDING|EXPIRATION|EXPLICIT' && '|EXPONENT|EXPORT|EXPORTING|EXTEND|EXTENDED|EXTENSION|EXTRACT|FAIL|FETCH|FIELD' && '|FIELD-GROUPS|FIELDS|FIELD-SYMBOL|FIELD-SYMBOLS|FILE|FILTER|FILTERS|FILTER-TABLE' && '|FINAL|FIND|FIRST|FIRST-LINE|FIXED-POINT|FKEQ|FKGE|FLOOR|FLUSH|FONT|FOR|FORM' && '|FORMAT|FORWARD|FOUND|FRAC|FRAME|FRAMES|FREE|FRIENDS|FROM|FUNCTION|FUNCTIONALITY' && '|FUNCTION-POOL|FURTHER|GAPS|GE|GENERATE|GET|GIVING|GKEQ|GKGE|GLOBAL|GRANT' && '|GREEN|GROUP|GROUPS|GT|HANDLE|HANDLER|HARMLESS|HASHED|HAVING|HDB|HEADER|HEADERS' && '|HEADING|HEAD-LINES|HELP-ID|HELP-REQUEST|HIDE|HIGH|HINT|HOLD|HOTSPOT|I|ICON|ID' && '|IDENTIFICATION|IDENTIFIER|IDS|IF|IGNORE|IGNORING|IMMEDIATELY|IMPLEMENTATION' && '|IMPLEMENTATIONS|IMPLEMENTED|IMPLICIT|IMPORT|IMPORTING|IN|INACTIVE|INCL|INCLUDE' && '|INCLUDES|INCLUDING|INCREMENT|INDEX|INDEX-LINE|INFOTYPES|INHERITING|INIT|INITIAL' && '|INITIALIZATION|INNER|INOUT|INPUT|INSERT|INSTANCES|INTENSIFIED|INTERFACE' && '|INTERFACE-POOL|INTERFACES|INTERNAL|INTERVALS|INTO|INVERSE|INVERTED-DATE|IS' && '|ISO|JOB|JOIN|KEEP|KEEPING|KERNEL|KEY|KEYS|KEYWORDS|KIND' && '|LANGUAGE|LAST|LATE|LAYOUT|LE|LEADING|LEAVE|LEFT|LEFT-JUSTIFIED|LEFTPLUS' && '|LEFTSPACE|LEGACY|LENGTH|LET|LEVEL|LEVELS|LIKE|LINE|LINE-COUNT|LINEFEED' && '|LINES|LINE-SELECTION|LINE-SIZE|LIST|LISTBOX|LIST-PROCESSING|LITTLE|LLANG' && '|LOAD|LOAD-OF-PROGRAM|LOB|LOCAL|LOCALE|LOCATOR|LOG|LOG10|LOGFILE|LOGICAL' && '|LOG-POINT|LONG|LOOP|LOW|LOWER|LPAD|LPI|LT|M|MAIL|MAIN|MAJOR-ID|MAPPING|MARGIN' && '|MARK|MASK|MATCH|MATCHCODE|MAX|MAXIMUM|MEDIUM|MEMBERS|MEMORY|MESH|MESSAGE' && '|MESSAGE-ID|MESSAGES|MESSAGING|METHOD|METHODS|MIN|MINIMUM|MINOR-ID|MM/DD/YY' && '|MM/DD/YYYY|MMDDYY|MOD|MODE|MODIF|MODIFIER|MODIFY|MODULE|MOVE|MOVE-CORRESPONDING' && '|MULTIPLY|MULTIPLY-CORRESPONDING|NA|NAME|NAMETAB|NATIVE|NB|NE|NESTED|NESTING' && '|NEW|NEW-LINE|NEW-PAGE|NEW-SECTION|NEXT|NO|NODE|NODES|NO-DISPLAY' && '|NO-EXTENSION|NO-GAP|NO-GAPS|NO-GROUPING|NO-HEADING|NON-UNICODE|NON-UNIQUE' && '|NO-SCROLLING|NO-SIGN|NOT|NO-TITLE|NO-TOPOFPAGE|NO-ZERO|NP|NS|NULL|NUMBER' && '|NUMOFCHAR|O|OBJECT|OBJECTS|OBLIGATORY|OCCURRENCE|OCCURRENCES|OCCURS|OF|OFF' && '|OFFSET|OLE|ON|ONLY|OPEN|OPTION|OPTIONAL|OPTIONS|OR|ORDER|OTHER|OTHERS|OUT' && '|OUTER|OUTPUT|OUTPUT-LENGTH|OVERFLOW|OVERLAY|PACK|PACKAGE|PAD|PADDING|PAGE' && '|PAGES|PARAMETER|PARAMETERS|PARAMETER-TABLE|PART|PARTIALLY|PATTERN|PERCENTAGE' && '|PERFORM|PERFORMING|PERSON|PF1|PF2|PF3|PF4|PF5|PF6|PF7|PF8|PF9|PF10|PF11|PF12' && '|PF13|PF14|PF15|PF-STATUS|PINK|PLACES|POOL|POS_HIGH|POS_LOW' && '|POSITION|PRAGMAS|PRECOMPILED|PREFERRED|PRESERVING|PRIMARY|PRINT|PRINT-CONTROL' && '|PRIORITY|PRIVATE|PROCEDURE|PROCESS|PROGRAM|PROPERTY|PROTECTED|PROVIDE|PUBLIC' && '|PUSHBUTTON|PUT|QUEUE-ONLY|QUICKINFO|RADIOBUTTON|RAISE|RAISING|RANGE|RANGES' && '|RAW|READ|READER|READ-ONLY|RECEIVE|RECEIVED|RECEIVER|RECEIVING|RED|REDEFINITION' && '|REDUCE|REDUCED|REF|REFERENCE|REFRESH|REGEX|REJECT|REMOTE|RENAMING|REPLACE' && '|REPLACEMENT|REPLACING|REPORT|REQUEST|REQUESTED|RESERVE|RESET|RESOLUTION' && '|RESPECTING|RESPONSIBLE|RESULT|RESULTS|RESUMABLE|RESUME|RETRY|RETURN|RETURNCODE' && '|RETURNING|RIGHT|RIGHT-JUSTIFIED|RIGHTPLUS|RIGHTSPACE|RISK|RMC_COMMUNICATION_FAILURE' && '|RMC_INVALID_STATUS|RMC_SYSTEM_FAILURE|ROLE|ROLLBACK|ROUND|ROWS|RUN|SAP' && '|SAP-SPOOL|SAVING|SCALE_PRESERVING|SCALE_PRESERVING_SCIENTIFIC|SCAN|SCIENTIFIC' && '|SCIENTIFIC_WITH_LEADING_ZERO|SCREEN|SCROLL|SCROLL-BOUNDARY|SCROLLING|SEARCH' && '|SECONDARY|SECONDS|SECTION|SELECT|SELECTION|SELECTIONS|SELECTION-SCREEN|SELECTION-SET' && '|SELECTION-SETS|SELECTION-TABLE|SELECT-OPTIONS|SEND|SEPARATE|SEPARATED|SET' && '|SHARED|SHIFT|SHORT|SHORTDUMP-ID|SIGN|SIGN_AS_POSTFIX|SIMPLE|SIN|SINGLE|SINH|SIZE' && '|SKIP|SKIPPING|SMART|SOME|SORT|SORTABLE|SORTED|SOURCE|SPACE|SPECIFIED|SPLIT|SPOOL' && '|SPOTS|SQL|SQLSCRIPT|SQRT|STABLE|STAMP|STANDARD|STARTING|START-OF-SELECTION|STATE' && '|STATEMENT|STATEMENTS|STATIC|STATICS|STATUSINFO|STEP-LOOP|STOP|STRLEN|STRUCTURE' && '|STRUCTURES|STYLE|SUBKEY|SUBMATCHES|SUBMIT|SUBROUTINE|SUBSCREEN|SUBSTRING|SUBTRACT' && '|SUBTRACT-CORRESPONDING|SUFFIX|SUM|SUMMARY|SUMMING|SUPPLIED|SUPPLY|SUPPRESS|SWITCH' && '|SWITCHSTATES|SYMBOL|SYNCPOINTS|SYNTAX|SYNTAX-CHECK|SYNTAX-TRACE' && '|SYSTEM-CALL|SYSTEM-EXCEPTIONS|SYSTEM-EXIT|TAB|TABBED|TABLE|TABLES|TABLEVIEW|TABSTRIP' && '|TAN|TANH|TARGET|TASK|TASKS|TEST|TESTING|TEXT|TEXTPOOL|THEN|THROW|TIME|TIMES|TIMESTAMP' && '|TIMEZONE|TITLE|TITLEBAR|TITLE-LINES|TO|TOKENIZATION|TOKENS|TOP-LINES|TOP-OF-PAGE' && '|TRACE-FILE|TRACE-TABLE|TRAILING|TRANSACTION|TRANSFER|TRANSFORMATION|TRANSLATE' && '|TRANSPORTING|TRMAC|TRUNC|TRUNCATE|TRUNCATION|TRY|TYPE|TYPE-POOL|TYPE-POOLS|TYPES' && '|ULINE|UNASSIGN|UNDER|UNICODE|UNION|UNIQUE|UNIT|UNIT_CONVERSION|UNIX|UNPACK|UNTIL' && '|UNWIND|UP|UPDATE|UPPER|USER|USER-COMMAND|USING|UTF-8|VALID|VALUE|VALUE-REQUEST|VALUES' && '|VARY|VARYING|VERIFICATION-MESSAGE|VERSION|VIA|VIEW|VISIBLE|WAIT|WARNING|WHEN|WHENEVER' && '|WHERE|WHILE|WIDTH|WINDOW|WINDOWS|WITH|WITH-HEADING|WITHOUT|WITH-TITLE|WORD|WORK' && '|WRITE|WRITER|X|XML|XSD|XSTRLEN|YELLOW|YES|YYMMDD|Z|ZERO|ZONE' && '|BINTOHEX|CHAR|CLNT|CONCAT_WITH_SPACE|CURR|DATS|DATS_ADD_DAYS|DATS_ADD_MONTHS' && '|DATS_DAYS_BETWEEN|DATS_IS_VALID|DEC|END-OF-EDITING|END-TEST-INJECTION|END-TEST-SEAM' && '|ENDWITH|ENUM|HEXTOBIN|INSTANCE|INSTR|LANG|LTRIM|NUMC|PUSH' && '|QUAN|RETURNS|RPAD|RTRIM|SSTRING|START-OF-EDITING|TEST-INJECTION|TEST-SEAM|TIMS' && '|TIMS_IS_VALID|TSTMP_ADD_SECONDS|TSTMP_CURRENT_UTCTIMESTAMP|TSTMP_IS_VALID' && '|TSTMP_SECONDS_BETWEEN|B|D|DECFLOAT16|DECFLOAT34|F|INT8|N|P|S|STRING|T|UTCLONG|XSTRING' && '|ABAP_BOOL|ACCP|CUKY|DF16_DEC|DF16_RAW|DF34_DEC|DF34_RAW|FLTP' && '|INT1|INT2|INT4|LCHR|LRAW|RAWSTRING|DF16_SCL|DF34_SCL' && '|PREC|VARC|CLIKE|CSEQUENCE|DECFLOAT|NUMERIC|XSEQUENCE|ME|SYST|SY' && '|BIT-SET|BOOLC|BOOLX|CHAR_OFF|CMAX|CMIN|CONCAT_LINES_OF|CONTAINS|CONTAINS_ANY_NOT_OF' && '|CONTAINS_ANY_OF|COUNT_ANY_NOT_OF|COUNT_ANY_OF|FIND_ANY_NOT_OF|FIND_ANY_OF|FIND_END' && '|FROM_MIXED|IPOW|LINE_EXISTS|LINE_INDEX|MATCHES|NMAX|NMIN|REPEAT|RESCALE|REVERSE' && '|SEGMENT|SHIFT_LEFT|SHIFT_RIGHT|SUBSTRING_AFTER|SUBSTRING_BEFORE|SUBSTRING_FROM|SUBSTRING_TO' && '|TO_LOWER|TO_MIXED|TO_UPPER|UTCLONG_ADD|UTCLONG_CURRENT|UTCLONG_DIFF|XSDBOOL'. SPLIT lv_keywords AT '|' INTO TABLE lt_keywords. " remove duplicates to avoid dumps when converting to a hash table SORT lt_keywords BY table_line ASCENDING. DELETE ADJACENT DUPLICATES FROM lt_keywords. gt_keywords = lt_keywords. " Hash table ENDMETHOD. METHOD is_keyword. DATA lv_str TYPE string. lv_str = to_upper( iv_chunk ). READ TABLE gt_keywords WITH KEY table_line = lv_str TRANSPORTING NO FIELDS. rv_yes = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD order_matches. DATA: lv_index TYPE sy-tabix, lv_line_len TYPE i, lv_prev_token TYPE c. FIELD-SYMBOLS: TYPE ty_match, TYPE ty_match. SORT ct_matches BY offset. lv_line_len = strlen( iv_line ). LOOP AT ct_matches ASSIGNING . lv_index = sy-tabix. " Delete matches after open text match IF lv_prev_token = c_token-text AND -token <> c_token-text. DELETE ct_matches INDEX lv_index. CONTINUE. ENDIF. CASE -token. WHEN c_token-keyword. IF -offset > 0 AND substring( val = iv_line off = ( -offset - 1 ) len = 1 ) CA '-<'. " Delete match if keyword is part of structure or field symbol DELETE ct_matches INDEX lv_index. CONTINUE. ENDIF. WHEN c_token-comment. -length = lv_line_len - -offset. DELETE ct_matches FROM lv_index + 1. CONTINUE. WHEN c_token-text. -text_tag = substring( val = iv_line off = -offset len = -length ). IF lv_prev_token = c_token-text. IF -text_tag = -text_tag. -length = -offset + -length - -offset. CLEAR lv_prev_token. ELSEIF -text_tag = '}' AND -text_tag = '{'. -length = -offset - -offset - 1. " Shift } out of scope -offset = -offset + 1. " Shift { out of scope CLEAR lv_prev_token. ELSEIF -text_tag = '{'. -length = -offset - -offset. CLEAR lv_prev_token. ELSEIF -text_tag = '}'. -length = -offset - -offset. -offset = -offset + 1. " Shift } out of scope CLEAR lv_prev_token. ENDIF. DELETE ct_matches INDEX lv_index. CONTINUE. ENDIF. ENDCASE. lv_prev_token = -token. ASSIGN TO . ENDLOOP. ENDMETHOD. METHOD parse_line. "REDEFINITION DATA lv_index TYPE i. FIELD-SYMBOLS LIKE LINE OF rt_matches. rt_matches = super->parse_line( iv_line ). " Remove non-keywords LOOP AT rt_matches ASSIGNING WHERE token = c_token-keyword. lv_index = sy-tabix. IF abap_false = is_keyword( substring( val = iv_line off = -offset len = -length ) ). DELETE rt_matches INDEX lv_index. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS kHGwlVCHrsAtuwxHoXzuQzYvAOqpyr DEFINITION DEFERRED. * renamed: zcl_abapgit_repo_status :: lcl_status_consistency_checks CLASS kHGwlVCHrsAtuwxHoXzuQzYvAOqpyr DEFINITION FINAL. PUBLIC SECTION. METHODS constructor IMPORTING iv_root_package TYPE devclass io_dot TYPE REF TO zcl_abapgit_dot_abapgit. METHODS run_checks IMPORTING it_results TYPE zif_abapgit_definitions=>ty_results_tt RETURNING VALUE(ri_log) TYPE REF TO zif_abapgit_log RAISING zcx_abapgit_exception . PRIVATE SECTION. DATA mv_root_package TYPE devclass. DATA mo_dot TYPE REF TO zcl_abapgit_dot_abapgit. DATA mi_log TYPE REF TO zif_abapgit_log. METHODS check_package_move IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception . METHODS check_files_folder IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception . METHODS check_package_sub_package IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt !iv_top TYPE devclass RAISING zcx_abapgit_exception . METHODS check_package_folder IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt !io_dot TYPE REF TO zcl_abapgit_dot_abapgit !iv_top TYPE devclass RAISING zcx_abapgit_exception . METHODS check_multiple_files IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception . METHODS check_namespace IMPORTING !it_results TYPE zif_abapgit_definitions=>ty_results_tt RAISING zcx_abapgit_exception . ENDCLASS. CLASS kHGwlVCHrsAtuwxHoXzuQzYvAOqpyr IMPLEMENTATION. METHOD constructor. mv_root_package = iv_root_package. mo_dot = io_dot. ENDMETHOD. METHOD run_checks. CREATE OBJECT mi_log TYPE zcl_abapgit_log. " Find all objects which were assigned to a different package check_package_move( it_results ). " Check files for one object is in the same folder check_files_folder( it_results ). " Check that sub packages are included in the package hierarchy check_package_sub_package( it_results = it_results iv_top = mv_root_package ). " Check that objects are created in package corresponding to folder check_package_folder( it_results = it_results io_dot = mo_dot iv_top = mv_root_package ). " Check for multiple files with same filename check_multiple_files( it_results ). " Check if namespaces exist already check_namespace( it_results ). ri_log = mi_log. ENDMETHOD. METHOD check_files_folder. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, lt_res_sort LIKE it_results, lt_item_idx LIKE it_results. FIELD-SYMBOLS: LIKE LINE OF it_results, LIKE LINE OF it_results. " TODO optimize ? " sort by obj, path " loop, and compare to first object record " Collect object index lt_res_sort = it_results. SORT lt_res_sort BY obj_type ASCENDING obj_name ASCENDING. LOOP AT it_results ASSIGNING WHERE NOT obj_type IS INITIAL AND packmove = abap_false. IF NOT ( -obj_type = ls_item-obj_type AND -obj_name = ls_item-obj_name ). APPEND INITIAL LINE TO lt_item_idx ASSIGNING . -obj_type = -obj_type. -obj_name = -obj_name. -path = -path. MOVE-CORRESPONDING TO ls_item. ENDIF. ENDLOOP. LOOP AT it_results ASSIGNING WHERE NOT obj_type IS INITIAL AND obj_type <> 'DEVC' AND packmove = abap_false. READ TABLE lt_item_idx ASSIGNING WITH KEY obj_type = -obj_type obj_name = -obj_name BINARY SEARCH. " Sorted above IF sy-subrc <> 0 OR -path <> -path. " All paths are same mi_log->add_warning( |Files for object { -obj_type } { -obj_name }| && | are not placed in the same folder| ). ENDIF. ENDLOOP. ENDMETHOD. METHOD check_multiple_files. DATA: lt_res_sort LIKE it_results, ls_file TYPE zif_abapgit_git_definitions=>ty_file_signature. FIELD-SYMBOLS LIKE LINE OF it_results. lt_res_sort = it_results. SORT lt_res_sort BY filename ASCENDING. LOOP AT lt_res_sort ASSIGNING WHERE obj_type <> 'DEVC' AND packmove = abap_false. IF -filename IS NOT INITIAL AND -filename = ls_file-filename. mi_log->add_warning( |Multiple files with same filename, { -filename }| ). ENDIF. IF -filename IS INITIAL. mi_log->add_warning( |Filename is empty for object { -obj_type } { -obj_name }| ). ENDIF. MOVE-CORRESPONDING TO ls_file. ENDLOOP. ENDMETHOD. METHOD check_namespace. DATA: li_namespace TYPE REF TO zif_abapgit_sap_namespace, lv_namespace TYPE namespace, lt_namespace TYPE TABLE OF namespace. FIELD-SYMBOLS LIKE LINE OF it_results. " Collect all namespaces based on name of xml- and json-files LOOP AT it_results ASSIGNING . FIND REGEX '^#([a-zA-Z0-9]+)#.*\..*\.xml$' IN -filename SUBMATCHES lv_namespace. IF sy-subrc = 0. lv_namespace = '/' && to_upper( lv_namespace ) && '/'. COLLECT lv_namespace INTO lt_namespace. ENDIF. FIND REGEX '^\(([a-zA-Z0-9]+)\).*\..*\.json$' IN -filename SUBMATCHES lv_namespace. IF sy-subrc = 0. lv_namespace = '/' && to_upper( lv_namespace ) && '/'. COLLECT lv_namespace INTO lt_namespace. ENDIF. ENDLOOP. li_namespace = zcl_abapgit_factory=>get_sap_namespace( ). LOOP AT lt_namespace INTO lv_namespace. IF li_namespace->exists( lv_namespace ) = abap_false. mi_log->add_warning( |Namespace { lv_namespace } does not exist.| && | Pull it first (or create it in transaction SE03)| ). ELSEIF li_namespace->is_editable( lv_namespace ) = abap_false. mi_log->add_warning( |Namespace { lv_namespace } is not modifiable. Check it in transaction SE03| ). ENDIF. ENDLOOP. ENDMETHOD. METHOD check_package_folder. DATA: lv_path TYPE string, lv_object TYPE string, 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 WHERE NOT package IS INITIAL AND NOT path IS INITIAL AND packmove = abap_false. lv_path = lo_folder_logic->package_to_path( iv_top = iv_top io_dot = io_dot iv_package = -package ). lv_object = |{ -obj_type } { -obj_name }|. IF lv_path IS INITIAL. IF -package(1) = '$'. mi_log->add_warning( |{ lv_object } exists but package { -package } is missing| && | (might have been lost during an upgrade, SAP Note 2478895)| ). ELSE. mi_log->add_error( |{ lv_object } already exists outside of { iv_top } package hierarchy| ). ENDIF. ELSEIF lv_path <> -path. mi_log->add_warning( |Package and path do not match for object { lv_object }| ). ENDIF. ENDLOOP. ENDMETHOD. METHOD check_package_move. DATA lt_move_idx LIKE it_results. FIELD-SYMBOLS: LIKE LINE OF it_results, LIKE LINE OF it_results. " TODO: optimize ? " delete where packmove = false, delete adj duplicates and fire messages ? LOOP AT it_results ASSIGNING WHERE lstate = zif_abapgit_definitions=>c_state-added AND packmove = abap_true. READ TABLE lt_move_idx TRANSPORTING NO FIELDS WITH KEY obj_type = -obj_type obj_name = -obj_name BINARY SEARCH. " Sorted since it_result is sorted IF sy-subrc <> 0. mi_log->add_warning( |Changed package assignment for object| && | { -obj_type } { -obj_name }| ). APPEND INITIAL LINE TO lt_move_idx ASSIGNING . -obj_type = -obj_type. -obj_name = -obj_name. -path = -path. ENDIF. ENDLOOP. ENDMETHOD. METHOD check_package_sub_package. DATA lv_msg TYPE string. FIELD-SYMBOLS LIKE LINE OF it_results. LOOP AT it_results ASSIGNING USING KEY sec_key WHERE package IS INITIAL AND obj_type = 'DEVC'. IF zcl_abapgit_factory=>get_sap_package( |{ -obj_name }| )->exists( ) = abap_true. " 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 the repo package (or one of its " subpackages). We don't do this automatically since it's not clear where in the " hierarchy the new package should be located or whether the sub package shall be " removed from the repo. lv_msg = |Package { -obj_name } already exists but is not a sub-package of { iv_top }. | && |Check your package and folder logic, and either assign { -obj_name } | && |to the package hierarchy of { iv_top } or remove package { -obj_name } | && |from the repository.|. mi_log->add_warning( lv_msg ). ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_status IMPLEMENTATION. METHOD build_existing. DATA ls_file_sig LIKE LINE OF it_state. " Item rs_result-obj_type = is_local-item-obj_type. rs_result-obj_name = is_local-item-obj_name. rs_result-package = is_local-item-devclass. rs_result-srcsystem = is_local-item-srcsystem. rs_result-origlang = is_local-item-origlang. rs_result-inactive = is_local-item-inactive. " File rs_result-path = is_local-file-path. rs_result-filename = is_local-file-filename. rs_result-match = boolc( is_local-file-sha1 = is_remote-sha1 ). IF rs_result-match = abap_true. RETURN. ENDIF. " Match against current state READ TABLE it_state INTO ls_file_sig WITH KEY path = is_local-file-path filename = is_local-file-filename BINARY SEARCH. IF sy-subrc = 0. IF ls_file_sig-sha1 <> is_local-file-sha1. rs_result-lstate = zif_abapgit_definitions=>c_state-modified. ENDIF. IF ls_file_sig-sha1 <> is_remote-sha1. rs_result-rstate = zif_abapgit_definitions=>c_state-modified. ENDIF. ELSE. " This is a strange situation. As both local and remote exist " the state should also be present. Maybe this is a first run of the code. " In this case just compare hashes directly and mark both changed " the user will presumably decide what to do after checking the actual diff rs_result-lstate = zif_abapgit_definitions=>c_state-modified. rs_result-rstate = zif_abapgit_definitions=>c_state-modified. ENDIF. ENDMETHOD. METHOD build_new_local. " Item rs_result-obj_type = is_local-item-obj_type. rs_result-obj_name = is_local-item-obj_name. rs_result-package = is_local-item-devclass. rs_result-srcsystem = is_local-item-srcsystem. rs_result-origlang = is_local-item-origlang. rs_result-inactive = is_local-item-inactive. " File rs_result-path = is_local-file-path. rs_result-filename = is_local-file-filename. " Match rs_result-match = abap_false. rs_result-lstate = zif_abapgit_definitions=>c_state-added. ENDMETHOD. METHOD build_new_remote. DATA ls_item LIKE LINE OF it_items_idx. DATA ls_file_sig LIKE LINE OF it_state_idx. " Common and default part rs_result-path = is_remote-path. rs_result-filename = is_remote-filename. rs_result-match = abap_false. rs_result-rstate = zif_abapgit_definitions=>c_state-added. zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = is_remote-filename iv_path = is_remote-path iv_devclass = mv_root_package io_dot = mo_dot IMPORTING es_item = ls_item ). " Check if in item index + get package READ TABLE it_items_idx INTO ls_item WITH KEY obj_type = ls_item-obj_type obj_name = ls_item-obj_name. IF sy-subrc = 0. " Completely new (xml, abap) and new file in an existing object rs_result-obj_type = ls_item-obj_type. rs_result-obj_name = ls_item-obj_name. rs_result-package = ls_item-devclass. rs_result-srcsystem = ''. rs_result-origlang = ''. READ TABLE it_state_idx INTO ls_file_sig WITH KEY path = is_remote-path filename = is_remote-filename. " Existing file but from another package " was not added during local file proc as was not in tadir for repo package IF sy-subrc = 0. IF ls_file_sig-sha1 = is_remote-sha1. rs_result-match = abap_true. CLEAR rs_result-rstate. ELSE. rs_result-rstate = zif_abapgit_definitions=>c_state-modified. ENDIF. " Item is in state and in cache but with no package - it was deleted " OR devclass is the same as repo package (see #532) IF ls_item-devclass IS INITIAL OR ls_item-devclass = mv_root_package. rs_result-match = abap_false. rs_result-lstate = zif_abapgit_definitions=>c_state-deleted. ENDIF. ENDIF. ELSE. " Completely unknown file, probably non-abapgit ASSERT 1 = 1. " No action, just follow defaults ENDIF. ENDMETHOD. METHOD calculate. DATA lt_local TYPE zif_abapgit_definitions=>ty_files_item_tt. DATA lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt. DATA li_exit TYPE REF TO zif_abapgit_exit. DATA lo_instance TYPE REF TO zcl_abapgit_repo_status. DATA lo_consistency_checks TYPE REF TO kHGwlVCHrsAtuwxHoXzuQzYvAOqpyr. IF ii_obj_filter IS INITIAL. lt_local = ii_repo->get_files_local( ii_log ). ELSE. lt_local = ii_repo->get_files_local_filtered( ii_log = ii_log ii_obj_filter = ii_obj_filter ). ENDIF. IF lines( lt_local ) <= 2. " Less equal two means that we have only the .abapgit.xml and the package in " our local repository. In this case we have to update our local .abapgit.xml " from the remote one. Otherwise we get errors when e.g. the folder starting " folder is different. ii_repo->find_remote_dot_abapgit( ). ENDIF. lt_remote = ii_repo->get_files_remote( ii_obj_filter = ii_obj_filter iv_ignore_files = abap_true ). li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->pre_calculate_repo_status( EXPORTING is_repo_meta = ii_repo->ms_data CHANGING ct_local = lt_local ct_remote = lt_remote ). CREATE OBJECT lo_instance EXPORTING iv_root_package = ii_repo->get_package( ) io_dot = ii_repo->get_dot_abapgit( ). rt_results = lo_instance->calculate_status( it_local = lt_local it_remote = lt_remote it_cur_state = ii_repo->checksums( )->get_checksums_per_file( ) ). IF ii_log IS BOUND. " This method just adds messages to the log. No log, nothing to do here CREATE OBJECT lo_consistency_checks EXPORTING iv_root_package = ii_repo->get_package( ) io_dot = ii_repo->get_dot_abapgit( ). ii_log->merge_with( lo_consistency_checks->run_checks( rt_results ) ). ENDIF. ENDMETHOD. METHOD calculate_status. DATA: lt_remote LIKE it_remote, lt_items TYPE zif_abapgit_definitions=>ty_items_tt, lt_items_by_obj TYPE zif_abapgit_definitions=>ty_items_ts, " Sorted by obj_type+obj_name lt_state_by_file TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts. " Sorted by path+filename lt_state_by_file = ensure_state( " Index by file it_cur_state = it_cur_state it_local = it_local ). lt_remote = it_remote. " Process local files and new local files process_local( EXPORTING it_local = it_local it_state_idx = lt_state_by_file CHANGING ct_remote = lt_remote ct_items = lt_items ct_results = rt_results ). " Remove processed remotes (with cleared SHA1) DELETE lt_remote WHERE sha1 IS INITIAL. " Complete item index for unmarked remote files process_items( " TODO: rename ? EXPORTING it_unprocessed_remote = lt_remote CHANGING ct_items = lt_items ). " The item list was not unique by now, just collected as "mention" list SORT lt_items DESCENDING. " Default key - type, name, pkg, ... DELETE ADJACENT DUPLICATES FROM lt_items COMPARING obj_type obj_name. lt_items_by_obj = lt_items. " Process new remote files (marked above with empty SHA1) process_remote( EXPORTING it_local = it_local it_unprocessed_remote = lt_remote it_state_idx = lt_state_by_file it_items_idx = lt_items_by_obj CHANGING ct_results = rt_results ). SORT rt_results BY obj_type ASCENDING obj_name ASCENDING filename ASCENDING path ASCENDING. ENDMETHOD. METHOD check_local_remote_consistency. IF is_remote-sha1 IS INITIAL. IF is_local-file-filename = zcl_abapgit_filename_logic=>c_package_file. zcx_abapgit_exception=>raise( |Package name conflict { is_local-item-obj_type } { is_local-item-obj_name }. | && |Rename package or use FULL folder logic| ). ELSE. zcx_abapgit_exception=>raise( |Checksum conflict { is_local-item-obj_type } { is_local-item-obj_name }. | && |Please create an issue on Github| ). ENDIF. ENDIF. ENDMETHOD. METHOD constructor. mv_root_package = iv_root_package. mo_dot = io_dot. ENDMETHOD. METHOD ensure_state. FIELD-SYMBOLS LIKE LINE OF rt_state. FIELD-SYMBOLS LIKE LINE OF it_local. IF lines( it_cur_state ) = 0. " Empty state is usually not expected. Maybe for new repos. " In this case suppose the local state is unchanged LOOP AT it_local ASSIGNING . APPEND INITIAL LINE TO rt_state ASSIGNING . MOVE-CORRESPONDING -file TO . ENDLOOP. ELSE. rt_state = it_cur_state. ENDIF. ENDMETHOD. METHOD get_object_package. DATA: lv_name TYPE devclass, li_package TYPE REF TO zif_abapgit_sap_package. rv_devclass = zcl_abapgit_factory=>get_tadir( )->get_object_package( iv_object = iv_object iv_obj_name = iv_obj_name ). IF rv_devclass IS INITIAL AND iv_object = 'DEVC' AND iv_obj_name(1) = '$'. " local packages usually have no tadir entry lv_name = iv_obj_name. li_package = zcl_abapgit_factory=>get_sap_package( lv_name ). IF li_package->exists( ) = abap_true. rv_devclass = lv_name. ENDIF. ENDIF. ENDMETHOD. METHOD process_items. DATA: ls_item LIKE LINE OF ct_items, lv_is_xml TYPE abap_bool, lv_is_json TYPE abap_bool, lv_sub_fetched TYPE abap_bool, lt_sub_packages TYPE SORTED TABLE OF devclass WITH UNIQUE KEY table_line. FIELD-SYMBOLS LIKE LINE OF it_unprocessed_remote. LOOP AT it_unprocessed_remote ASSIGNING . zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = -filename iv_path = -path io_dot = mo_dot iv_devclass = mv_root_package IMPORTING es_item = ls_item ev_is_xml = lv_is_xml ev_is_json = lv_is_json ). CHECK lv_is_xml = abap_true OR lv_is_json = 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 ls_item-devclass IS NOT INITIAL AND mv_root_package <> ls_item-devclass. IF lv_sub_fetched = abap_false. lt_sub_packages = zcl_abapgit_factory=>get_sap_package( mv_root_package )->list_subpackages( ). lv_sub_fetched = abap_true. 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. IF sy-subrc <> 0 AND ls_item-obj_type = 'DEVC'. CLEAR ls_item-devclass. ENDIF. ENDIF. APPEND ls_item TO ct_items. ENDLOOP. ENDMETHOD. METHOD process_local. 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 CHECK mo_dot->is_ignored( iv_path = -file-path iv_filename = -file-filename ) = abap_false. IF -item IS NOT INITIAL AND zcl_abapgit_filename_logic=>is_obj_definition_file( -file-filename ) = abap_true. " Collect for item index APPEND -item TO ct_items. ENDIF. APPEND INITIAL LINE TO ct_results ASSIGNING . " Find a match in remote READ TABLE ct_remote ASSIGNING WITH KEY file_path COMPONENTS path = -file-path filename = -file-filename. IF sy-subrc = 0. " Both local and remote exist check_local_remote_consistency( is_local = is_remote = ). = build_existing( is_local = is_remote = it_state = it_state_idx ). CLEAR -sha1. " Mark as processed ELSE. " Only local exists = build_new_local( ). " Check if same file exists in different location READ TABLE ct_remote ASSIGNING WITH KEY file COMPONENTS filename = -file-filename. IF sy-subrc = 0 AND -file-sha1 = -sha1. " If yes, then it was probably moved -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. 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. ENDLOOP. ENDMETHOD. METHOD process_remote. FIELD-SYMBOLS: LIKE LINE OF it_unprocessed_remote, LIKE LINE OF ct_results, LIKE LINE OF it_local. LOOP AT it_unprocessed_remote ASSIGNING . APPEND INITIAL LINE TO ct_results ASSIGNING . = build_new_remote( is_remote = it_items_idx = it_items_idx it_state_idx = it_state_idx ). " Check if same file exists in different location (not for generic package files) READ TABLE it_local ASSIGNING WITH KEY file-filename = -filename. IF sy-subrc = 0 AND -filename <> zcl_abapgit_filename_logic=>c_package_file. -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. ELSE. " Check if file existed before and was deleted locally READ TABLE it_state_idx TRANSPORTING NO FIELDS WITH KEY path = -path filename = -filename. IF sy-subrc = 0. -match = abap_false. -lstate = zif_abapgit_definitions=>c_state-deleted. ENDIF. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_srv IMPLEMENTATION. METHOD add. DATA li_repo LIKE LINE OF mt_list. DATA lo_repo TYPE REF TO zcl_abapgit_repo. LOOP AT mt_list INTO li_repo. IF li_repo->ms_data-key = ii_repo->ms_data-key. IF li_repo = ii_repo. RETURN. ENDIF. zcx_abapgit_exception=>raise( 'identical keys' ). ENDIF. ENDLOOP. lo_repo ?= ii_repo. " TODO, refactor later lo_repo->bind_listener( me ). APPEND ii_repo TO mt_list. ENDMETHOD. METHOD determine_branch_name. DATA lo_branch_list TYPE REF TO zcl_abapgit_git_branch_list. rv_name = iv_name. IF rv_name IS INITIAL. ASSERT NOT iv_url IS INITIAL. lo_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). rv_name = lo_branch_list->get_head_symref( ). ELSEIF -1 = find( val = rv_name sub = zif_abapgit_git_definitions=>c_git_branch-heads_prefix ). " Assume short branch name was received rv_name = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && rv_name. ENDIF. ENDMETHOD. METHOD get_instance. IF gi_ref IS INITIAL. CREATE OBJECT gi_ref TYPE zcl_abapgit_repo_srv. ENDIF. ri_srv = gi_ref. ENDMETHOD. METHOD inject_instance. gi_ref = ii_srv. ENDMETHOD. METHOD instantiate_and_add. IF is_repo_meta-offline = abap_false. CREATE OBJECT ri_repo TYPE zcl_abapgit_repo_online EXPORTING is_data = is_repo_meta. ELSE. CREATE OBJECT ri_repo TYPE zcl_abapgit_repo_offline EXPORTING is_data = is_repo_meta. ENDIF. add( ri_repo ). ENDMETHOD. METHOD refresh_all. DATA: lt_list TYPE zif_abapgit_persistence=>ty_repos. FIELD-SYMBOLS: LIKE LINE OF lt_list. CLEAR mt_list. lt_list = zcl_abapgit_persist_factory=>get_repo( )->list( ). LOOP AT lt_list ASSIGNING . instantiate_and_add( ). ENDLOOP. mv_init = abap_true. mv_only_favorites = abap_false. ENDMETHOD. METHOD refresh_favorites. DATA: lt_list TYPE zif_abapgit_persistence=>ty_repos, lt_user_favorites TYPE zif_abapgit_persist_user=>ty_favorites. DATA li_repo TYPE REF TO zif_abapgit_repo. DATA lv_repo_index TYPE i. DATA lo_repo_db TYPE REF TO zif_abapgit_persist_repo. FIELD-SYMBOLS: LIKE LINE OF lt_list. lo_repo_db = zcl_abapgit_persist_factory=>get_repo( ). lt_user_favorites = zcl_abapgit_persistence_user=>get_instance( )->get_favorites( ). lt_list = lo_repo_db->list_by_keys( lt_user_favorites ). SORT lt_list BY package. LOOP AT mt_list INTO li_repo. lv_repo_index = sy-tabix. READ TABLE lt_list TRANSPORTING NO FIELDS WITH KEY package = li_repo->get_package( ). IF sy-subrc = 0. DELETE lt_list INDEX sy-tabix. CONTINUE. " Leave the repo be ELSEIF lo_repo_db->exists( li_repo->get_key( ) ) = abap_false. " Not a fav, and also does not exist, probably uninstalled DELETE mt_list INDEX lv_repo_index. ENDIF. ENDLOOP. " Create remaining (new) favs LOOP AT lt_list ASSIGNING . instantiate_and_add( ). ENDLOOP. mv_init = abap_true. mv_only_favorites = abap_true. ENDMETHOD. METHOD reinstantiate_repo. DATA li_repo TYPE REF TO zif_abapgit_repo. DATA ls_full_meta TYPE zif_abapgit_persistence=>ty_repo. li_repo = zif_abapgit_repo_srv~get( iv_key ). DELETE TABLE mt_list FROM li_repo. ASSERT sy-subrc IS INITIAL. MOVE-CORRESPONDING is_meta TO ls_full_meta. ls_full_meta-key = iv_key. instantiate_and_add( ls_full_meta ). ENDMETHOD. METHOD validate_sub_super_packages. DATA: ls_repo LIKE LINE OF it_repos, li_package TYPE REF TO zif_abapgit_sap_package, lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt, li_repo TYPE REF TO zif_abapgit_repo. LOOP AT it_repos INTO ls_repo. li_repo = zif_abapgit_repo_srv~get( ls_repo-key ). li_package = zcl_abapgit_factory=>get_sap_package( ls_repo-package ). IF li_package->exists( ) = abap_false. " Skip dangling repository CONTINUE. ENDIF. CLEAR lt_packages. IF li_repo->get_local_settings( )-ignore_subpackages = abap_false. APPEND LINES OF li_package->list_subpackages( ) TO lt_packages. READ TABLE lt_packages TRANSPORTING NO FIELDS WITH KEY table_line = iv_package. IF sy-subrc = 0. ei_repo = li_repo. ev_reason = |Repository { li_repo->get_name( ) } already contains { iv_package } |. RETURN. ENDIF. ENDIF. IF iv_ign_subpkg = abap_false. APPEND LINES OF li_package->list_superpackages( ) TO lt_packages. READ TABLE lt_packages TRANSPORTING NO FIELDS WITH KEY table_line = iv_package. IF sy-subrc = 0. ei_repo = li_repo. ev_reason = |Repository { li_repo->get_name( ) } already contains subpackage of { iv_package } |. RETURN. ENDIF. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_repo_listener~on_meta_change. DATA li_persistence TYPE REF TO zif_abapgit_persist_repo. li_persistence = zcl_abapgit_persist_factory=>get_repo( ). li_persistence->update_metadata( iv_key = iv_key is_meta = is_meta is_change_mask = is_change_mask ). " Recreate repo instance if type changed " Instances in mt_list are of *_online and *_offline type " If type is changed object should be recreated from the proper class " TODO refactor, e.g. unify repo logic in one class IF is_change_mask-offline = abap_true. reinstantiate_repo( iv_key = iv_key is_meta = is_meta ). ENDIF. ENDMETHOD. METHOD zif_abapgit_repo_srv~delete. zcl_abapgit_persist_factory=>get_repo( )->delete( ii_repo->get_key( ) ). zcl_abapgit_persist_factory=>get_repo_cs( )->delete( ii_repo->get_key( ) ). " If favorite, remove it IF zcl_abapgit_persistence_user=>get_instance( )->is_favorite_repo( ii_repo->get_key( ) ) = abap_true. zcl_abapgit_persistence_user=>get_instance( )->toggle_favorite( ii_repo->get_key( ) ). ENDIF. DELETE TABLE mt_list FROM ii_repo. ASSERT sy-subrc = 0. ENDMETHOD. METHOD zif_abapgit_repo_srv~get. FIELD-SYMBOLS: LIKE LINE OF mt_list. ASSERT iv_key IS NOT INITIAL. IF mv_init = abap_false. refresh_all( ). ENDIF. DO 2 TIMES. " Repo might have been created in another session. Try again after refresh IF sy-index = 2. refresh_all( ). ENDIF. LOOP AT mt_list ASSIGNING . IF ->ms_data-key = iv_key. ri_repo = . RETURN. ENDIF. ENDLOOP. ENDDO. zcx_abapgit_exception=>raise( |Repository not found in database. Key: REPO, { iv_key }| ). ENDMETHOD. METHOD zif_abapgit_repo_srv~get_label_list. DATA: lt_repo TYPE zif_abapgit_repo_srv=>ty_repo_list, ls_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings, lt_labels TYPE string_table, ls_label LIKE LINE OF rt_labels. FIELD-SYMBOLS: TYPE REF TO zif_abapgit_repo, TYPE LINE OF string_table. lt_repo = zif_abapgit_repo_srv~list( ). LOOP AT lt_repo ASSIGNING . ls_local_settings = ->get_local_settings( ). lt_labels = zcl_abapgit_repo_labels=>split( ls_local_settings-labels ). LOOP AT lt_labels ASSIGNING . ls_label-label = . INSERT ls_label INTO TABLE rt_labels. ENDLOOP. ENDLOOP. SORT rt_labels. DELETE ADJACENT DUPLICATES FROM rt_labels. ENDMETHOD. METHOD zif_abapgit_repo_srv~get_repo_from_package. DATA: lt_repos TYPE zif_abapgit_persistence=>ty_repos, lv_name TYPE zif_abapgit_persistence=>ty_local_settings-display_name, lv_owner TYPE zif_abapgit_persistence=>ty_local_settings-display_name. FIELD-SYMBOLS: LIKE LINE OF lt_repos. " check if package is already in use for a different repository lt_repos = zcl_abapgit_persist_factory=>get_repo( )->list( ). READ TABLE lt_repos WITH KEY package = iv_package ASSIGNING . IF sy-subrc = 0. ei_repo = get_instance( )->get( -key ). lv_name = ei_repo->get_name( ). lv_owner = -created_by. ev_reason = |Package { iv_package } already versioned as { lv_name } by { lv_owner }|. ELSE. " check if package is include as sub-package in a different repo validate_sub_super_packages( EXPORTING iv_package = iv_package it_repos = lt_repos iv_ign_subpkg = iv_ign_subpkg IMPORTING ei_repo = ei_repo ev_reason = ev_reason ). ENDIF. ENDMETHOD. METHOD zif_abapgit_repo_srv~get_repo_from_url. DATA: lt_repos TYPE zif_abapgit_persistence=>ty_repos, lv_current_repo_address TYPE string, lv_check_repo_address TYPE string, lv_repo_path TYPE string, lv_name TYPE zif_abapgit_persistence=>ty_local_settings-display_name, lv_owner TYPE zif_abapgit_persistence=>ty_local_settings-display_name. FIELD-SYMBOLS: LIKE LINE OF lt_repos. CLEAR: ei_repo, ev_reason. lv_current_repo_address = zcl_abapgit_url=>url_address( iv_url ). " check if url is already in use for a different package lt_repos = zcl_abapgit_persist_factory=>get_repo( )->list( ). LOOP AT lt_repos ASSIGNING WHERE offline = abap_false. lv_check_repo_address = zcl_abapgit_url=>url_address( -url ). IF lv_current_repo_address = lv_check_repo_address. ei_repo = get_instance( )->get( -key ). lv_repo_path = zcl_abapgit_url=>path_name( iv_url ). lv_name = ei_repo->get_name( ). lv_owner = -created_by. ev_reason = |Repository { lv_repo_path } already versioned as { lv_name } by { lv_owner }|. RETURN. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_repo_srv~init. CLEAR mv_init. ENDMETHOD. METHOD zif_abapgit_repo_srv~is_repo_installed. DATA: lt_repo TYPE zif_abapgit_repo_srv=>ty_repo_list, li_repo TYPE REF TO zif_abapgit_repo, lv_url TYPE string, lv_package TYPE devclass, lo_repo_online TYPE REF TO zcl_abapgit_repo_online, lv_err TYPE string. lt_repo = zif_abapgit_repo_srv~list( ). LOOP AT lt_repo INTO li_repo. CHECK li_repo->is_offline( ) = abap_false. lo_repo_online ?= li_repo. lv_url = lo_repo_online->get_url( ). lv_package = lo_repo_online->get_package( ). CHECK to_upper( lv_url ) = to_upper( iv_url ). " Validate bindings "TODO refactor: move this message out of this method IF iv_target_package IS NOT INITIAL AND iv_target_package <> lv_package. lv_err = |Installation to package { lv_package } detected. | && |Cancelling installation|. zcx_abapgit_exception=>raise( lv_err ). ENDIF. rv_installed = abap_true. EXIT. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_repo_srv~list. DATA li_repo TYPE REF TO zif_abapgit_repo. IF mv_init = abap_false OR mv_only_favorites = abap_true. refresh_all( ). ENDIF. LOOP AT mt_list INTO li_repo. IF iv_offline = abap_undefined OR li_repo->is_offline( ) = iv_offline. INSERT li_repo INTO TABLE rt_list. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_repo_srv~list_favorites. DATA lt_user_favorites TYPE zif_abapgit_persist_user=>ty_favorites. DATA li_repo TYPE REF TO zif_abapgit_repo. lt_user_favorites = zcl_abapgit_persistence_user=>get_instance( )->get_favorites( ). SORT lt_user_favorites BY table_line. IF mv_init = abap_false OR mv_only_favorites = abap_false. refresh_favorites( ). ENDIF. LOOP AT mt_list INTO li_repo. READ TABLE lt_user_favorites TRANSPORTING NO FIELDS WITH KEY table_line = li_repo->get_key( ). IF sy-subrc = 0 AND ( iv_offline = abap_undefined OR li_repo->is_offline( ) = iv_offline ). APPEND li_repo TO rt_list. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_repo_srv~new_offline. DATA: ls_repo TYPE zif_abapgit_persistence=>ty_repo, lv_key TYPE zif_abapgit_persistence=>ty_repo-key, lo_repo TYPE REF TO zcl_abapgit_repo_offline, lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit. IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-create_repo ) = abap_false. zcx_abapgit_exception=>raise( 'Not authorized' ). ENDIF. zif_abapgit_repo_srv~validate_package( iv_package = iv_package iv_ign_subpkg = iv_ign_subpkg ). IF iv_name IS INITIAL. zcx_abapgit_exception=>raise( 'Missing name for repository' ). ENDIF. " Repo Settings lo_dot_abapgit = zcl_abapgit_dot_abapgit=>build_default( ). lo_dot_abapgit->set_folder_logic( iv_folder_logic ). lo_dot_abapgit->set_name( iv_name ). lo_dot_abapgit->set_abap_language_version( iv_abap_lang_vers ). lv_key = zcl_abapgit_persist_factory=>get_repo( )->add( iv_package = iv_package iv_offline = abap_true is_dot_abapgit = lo_dot_abapgit->get_data( ) ). TRY. ls_repo = zcl_abapgit_persist_factory=>get_repo( )->read( lv_key ). CATCH zcx_abapgit_not_found. zcx_abapgit_exception=>raise( 'new_offline not found' ). ENDTRY. lo_repo ?= instantiate_and_add( ls_repo ). " Local Settings IF ls_repo-local_settings-ignore_subpackages <> iv_ign_subpkg. ls_repo-local_settings-ignore_subpackages = iv_ign_subpkg. ENDIF. ls_repo-local_settings-main_language_only = iv_main_lang_only. ls_repo-local_settings-labels = iv_labels. lo_repo->set_local_settings( ls_repo-local_settings ). ri_repo = lo_repo. ENDMETHOD. METHOD zif_abapgit_repo_srv~new_online. DATA: ls_repo TYPE zif_abapgit_persistence=>ty_repo, lo_repo TYPE REF TO zcl_abapgit_repo_online, lv_branch_name LIKE iv_branch_name, lv_key TYPE zif_abapgit_persistence=>ty_repo-key, lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit, lv_url TYPE string. ASSERT NOT iv_url IS INITIAL AND NOT iv_package IS INITIAL. lv_url = condense( iv_url ). IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-create_repo ) = abap_false. zcx_abapgit_exception=>raise( 'Not authorized' ). ENDIF. zif_abapgit_repo_srv~validate_package( iv_package = iv_package iv_ign_subpkg = iv_ign_subpkg ). zif_abapgit_repo_srv~validate_url( lv_url ). lv_branch_name = determine_branch_name( iv_name = iv_branch_name iv_url = lv_url ). " Repo Settings lo_dot_abapgit = zcl_abapgit_dot_abapgit=>build_default( ). lo_dot_abapgit->set_folder_logic( iv_folder_logic ). lo_dot_abapgit->set_name( iv_name ). lo_dot_abapgit->set_abap_language_version( iv_abap_lang_vers ). lv_key = zcl_abapgit_persist_factory=>get_repo( )->add( iv_url = lv_url iv_branch_name = lv_branch_name " local ! iv_display_name = iv_display_name iv_package = iv_package iv_offline = abap_false is_dot_abapgit = lo_dot_abapgit->get_data( ) ). TRY. ls_repo = zcl_abapgit_persist_factory=>get_repo( )->read( lv_key ). CATCH zcx_abapgit_not_found. zcx_abapgit_exception=>raise( 'new_online not found' ). ENDTRY. lo_repo ?= instantiate_and_add( ls_repo ). " Local Settings IF ls_repo-local_settings-ignore_subpackages <> iv_ign_subpkg. ls_repo-local_settings-ignore_subpackages = iv_ign_subpkg. ENDIF. ls_repo-local_settings-main_language_only = iv_main_lang_only. ls_repo-local_settings-labels = iv_labels. lo_repo->set_local_settings( ls_repo-local_settings ). lo_repo->refresh( ). lo_repo->find_remote_dot_abapgit( ). ri_repo = lo_repo. ENDMETHOD. METHOD zif_abapgit_repo_srv~purge. * uninstalls all objects, no UI or popups in this class * todo, this should be a method on the repo instead? DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. DATA: lx_error TYPE REF TO zcx_abapgit_exception. DATA lo_repo TYPE REF TO zcl_abapgit_repo. lo_repo ?= ii_repo. " TODO, remove later ri_log = lo_repo->create_new_log( 'Uninstall Log' ). IF ii_repo->get_local_settings( )-write_protected = abap_true. zcx_abapgit_exception=>raise( 'Cannot purge. Local code is write-protected by repo config' ). ELSEIF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-uninstall ) = abap_false. zcx_abapgit_exception=>raise( 'Not authorized' ). ENDIF. lt_tadir = lo_repo->get_tadir_objects( ). TRY. zcl_abapgit_objects=>delete( it_tadir = lt_tadir is_checks = is_checks ii_log = ri_log ). CATCH zcx_abapgit_exception INTO lx_error. " If uninstall fails, repo needs a refresh to show which objects where deleted and which not ii_repo->refresh( iv_drop_log = abap_false ). RAISE EXCEPTION lx_error. ENDTRY. IF iv_keep_repo = abap_true. ii_repo->refresh( ). ii_repo->checksums( )->rebuild( ). ELSE. zif_abapgit_repo_srv~delete( ii_repo ). ENDIF. ENDMETHOD. METHOD zif_abapgit_repo_srv~validate_package. DATA: lv_as4user TYPE usnam, li_repo TYPE REF TO zif_abapgit_repo, lv_reason TYPE string. zcl_abapgit_factory=>get_sap_package( iv_package )->validate_name( ). " Check if package owned by SAP is allowed (new packages are ok, since they are created automatically) lv_as4user = zcl_abapgit_factory=>get_sap_package( iv_package )->read_responsible( ). IF sy-subrc = 0 AND lv_as4user = 'SAP' AND zcl_abapgit_factory=>get_environment( )->is_sap_object_allowed( ) = abap_false. zcx_abapgit_exception=>raise( |Package { iv_package } not allowed, responsible user = 'SAP'| ). ENDIF. " Check if package is already used in another repo IF iv_chk_exists = abap_true. zif_abapgit_repo_srv~get_repo_from_package( EXPORTING iv_package = iv_package iv_ign_subpkg = iv_ign_subpkg IMPORTING ei_repo = li_repo ev_reason = lv_reason ). IF li_repo IS BOUND. zcx_abapgit_exception=>raise( lv_reason ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_repo_srv~validate_url. DATA: li_repo TYPE REF TO zif_abapgit_repo, lv_reason TYPE string. zcl_abapgit_url=>validate( iv_url ). IF iv_chk_exists = abap_true. zif_abapgit_repo_srv~get_repo_from_url( EXPORTING iv_url = iv_url IMPORTING ei_repo = li_repo ev_reason = lv_reason ). IF li_repo IS BOUND. zcx_abapgit_exception=>raise( lv_reason ). ENDIF. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_online IMPLEMENTATION. METHOD fetch_remote. DATA: li_progress TYPE REF TO zif_abapgit_progress, ls_pull TYPE zcl_abapgit_git_porcelain=>ty_pull_result. IF mv_request_remote_refresh = abap_false. RETURN. ENDIF. li_progress = zcl_abapgit_progress=>get_instance( 1 ). li_progress->show( iv_current = 1 iv_text = 'Fetch remote files' ). IF get_selected_commit( ) IS INITIAL. ls_pull = zcl_abapgit_git_porcelain=>pull_by_branch( iv_url = get_url( ) iv_branch_name = get_selected_branch( ) ). ELSE. ls_pull = zcl_abapgit_git_porcelain=>pull_by_commit( iv_url = get_url( ) iv_commit_hash = get_selected_commit( ) ). ENDIF. set_files_remote( ls_pull-files ). set_objects( ls_pull-objects ). mv_current_commit = ls_pull-commit. ENDMETHOD. METHOD get_objects. fetch_remote( ). rt_objects = mt_objects. ENDMETHOD. METHOD handle_stage_ignore. DATA: lv_add TYPE abap_bool, lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit, lt_stage TYPE zif_abapgit_definitions=>ty_stage_tt. FIELD-SYMBOLS: LIKE LINE OF lt_stage. lo_dot_abapgit = get_dot_abapgit( ). lt_stage = io_stage->get_all( ). LOOP AT lt_stage ASSIGNING WHERE method = zif_abapgit_definitions=>c_method-ignore. lo_dot_abapgit->add_ignore( iv_path = -file-path iv_filename = -file-filename ). " remove it from the staging object, as the action is handled here io_stage->reset( iv_path = -file-path iv_filename = -file-filename ). lv_add = abap_true. ENDLOOP. IF lv_add = abap_true. io_stage->add( iv_path = zif_abapgit_definitions=>c_root_dir iv_filename = zif_abapgit_definitions=>c_dot_abapgit iv_data = lo_dot_abapgit->serialize( ) ). set_dot_abapgit( lo_dot_abapgit ). ENDIF. ENDMETHOD. METHOD raise_error_if_branch_exists. DATA: lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, lv_display_name TYPE string. lt_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( get_url( ) )->get_branches_only( ). READ TABLE lt_branches WITH TABLE KEY name_key COMPONENTS name = iv_name TRANSPORTING NO FIELDS. IF sy-subrc = 0. lv_display_name = zcl_abapgit_git_branch_list=>get_display_name( iv_name ). zcx_abapgit_exception=>raise( |Branch '{ lv_display_name }' already exists| ). ENDIF. ENDMETHOD. METHOD set_objects. mt_objects = it_objects. ENDMETHOD. METHOD zif_abapgit_repo_online~check_for_valid_branch. DATA: lo_branch_list TYPE REF TO zcl_abapgit_git_branch_list, lx_error TYPE REF TO zcx_abapgit_exception, lv_branch TYPE string, lv_head TYPE string, lv_msg TYPE string. lv_branch = get_selected_branch( ). IF lv_branch IS NOT INITIAL. lo_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( get_url( ) ). TRY. lo_branch_list->find_by_name( lv_branch ). CATCH zcx_abapgit_exception INTO lx_error. " branch does not exist, fallback to head lv_head = lo_branch_list->get_head_symref( ). lv_msg = |{ lx_error->get_text( ) }. Switched to { lo_branch_list->get_display_name( lv_head ) }|. MESSAGE lv_msg TYPE 'S'. select_branch( lv_head ). ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_repo_online~create_branch. DATA: lv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1. ASSERT iv_name CP zif_abapgit_git_definitions=>c_git_branch-heads. IF iv_from IS INITIAL. lv_sha1 = get_current_remote( ). ELSE. lv_sha1 = iv_from. ENDIF. raise_error_if_branch_exists( iv_name ). zcl_abapgit_git_porcelain=>create_branch( iv_url = get_url( ) iv_name = iv_name iv_from = lv_sha1 ). " automatically switch to new branch select_branch( iv_name ). ENDMETHOD. METHOD zif_abapgit_repo_online~get_current_remote. fetch_remote( ). rv_sha1 = mv_current_commit. ENDMETHOD. METHOD zif_abapgit_repo_online~get_selected_branch. rv_name = ms_data-branch_name. ENDMETHOD. METHOD zif_abapgit_repo_online~get_selected_commit. rv_selected_commit = ms_data-selected_commit. ENDMETHOD. METHOD zif_abapgit_repo_online~get_switched_origin. rv_switched_origin = ms_data-switched_origin. ENDMETHOD. METHOD zif_abapgit_repo_online~get_url. rv_url = ms_data-url. ENDMETHOD. METHOD zif_abapgit_repo_online~push. * assumption: PUSH is done on top of the currently selected branch DATA: ls_push TYPE zcl_abapgit_git_porcelain=>ty_push_result, lv_text TYPE string, lv_parent TYPE zif_abapgit_git_definitions=>ty_sha1. IF ms_data-branch_name CP zif_abapgit_git_definitions=>c_git_branch-tags. lv_text = |You're working on a tag. Currently it's not | && |possible to push on tags. Consider creating a branch instead|. zcx_abapgit_exception=>raise( lv_text ). ENDIF. IF ms_data-selected_commit IS NOT INITIAL. lv_text = 'You are currently checked out in a commit.'. lv_text = |{ lv_text } You must be on a branch to push|. zcx_abapgit_exception=>raise( lv_text ). ENDIF. IF ms_data-local_settings-block_commit = abap_true AND zcl_abapgit_factory=>get_code_inspector( get_package( ) )->is_successful( ) = abap_false. zcx_abapgit_exception=>raise( |A successful code inspection is required| ). ENDIF. handle_stage_ignore( io_stage ). IF get_selected_commit( ) IS INITIAL. lv_parent = get_current_remote( ). ELSE. lv_parent = get_selected_commit( ). ENDIF. ls_push = zcl_abapgit_git_porcelain=>push( is_comment = is_comment io_stage = io_stage iv_branch_name = get_selected_branch( ) iv_url = get_url( ) iv_parent = lv_parent it_old_objects = get_objects( ) ). set_objects( ls_push-new_objects ). set_files_remote( ls_push-new_files ). mv_current_commit = ls_push-branch. zif_abapgit_repo~checksums( )->update( ls_push-updated_files ). ENDMETHOD. METHOD zif_abapgit_repo_online~select_branch. reset_remote( ). set( iv_branch_name = iv_branch_name iv_selected_commit = space ). ENDMETHOD. METHOD zif_abapgit_repo_online~select_commit. reset_remote( ). set( iv_selected_commit = iv_selected_commit ). ENDMETHOD. METHOD zif_abapgit_repo_online~set_url. reset_remote( ). set( iv_url = iv_url ). ENDMETHOD. METHOD zif_abapgit_repo_online~switch_origin. DATA lv_offs TYPE i. " For repo settings page IF iv_overwrite = abap_true. set( iv_switched_origin = iv_url ). RETURN. ENDIF. IF iv_url IS INITIAL. IF ms_data-switched_origin IS INITIAL. RETURN. ELSE. lv_offs = find( val = reverse( ms_data-switched_origin ) sub = '@' ). IF lv_offs = -1. zcx_abapgit_exception=>raise( 'Incorrect format of switched origin' ). ENDIF. lv_offs = strlen( ms_data-switched_origin ) - lv_offs - 1. set_url( substring( val = ms_data-switched_origin len = lv_offs ) ). select_branch( substring( val = ms_data-switched_origin off = lv_offs + 1 ) ). set( iv_switched_origin = '' ). ENDIF. ELSEIF ms_data-switched_origin IS INITIAL. set( iv_switched_origin = ms_data-url && '@' && ms_data-branch_name ). set_url( iv_url ). select_branch( iv_branch ). ELSE. zcx_abapgit_exception=>raise( 'Cannot switch origin twice' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_repo~get_files_remote. fetch_remote( ). rt_files = super->get_files_remote( ii_obj_filter = ii_obj_filter iv_ignore_files = iv_ignore_files ). ENDMETHOD. METHOD zif_abapgit_repo~get_name. rv_name = super->get_name( ). IF rv_name IS INITIAL. TRY. rv_name = zcl_abapgit_url=>name( ms_data-url ). rv_name = cl_http_utility=>unescape_url( rv_name ). CATCH zcx_abapgit_exception. rv_name = 'New online repo'. "unlikely fallback ENDTRY. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_offline IMPLEMENTATION. METHOD reset_remote. DATA lt_backup LIKE mt_remote. " online repo has online source to renew data from, offline does not " so offline repo preserves the remote " in case of partial pull failure the user will immediately see the new difference " UI will detect "pullable" content based on mt_status " in the uniform way both for online and offline repos " for more details see discussion in 2096 and 1953 lt_backup = mt_remote. super->reset_remote( ). set_files_remote( lt_backup ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_REPO_CS_MIGRATION IMPLEMENTATION. METHOD clear_repo_metadata. DATA lo_repo_persistence TYPE REF TO zcl_abapgit_persistence_repo. lo_repo_persistence ?= zcl_abapgit_persist_factory=>get_repo( ). lo_repo_persistence->rewrite_repo_meta( iv_repo_key ). ENDMETHOD. METHOD convert_checksums. DATA lo_cs TYPE REF TO zcl_abapgit_repo_checksums. DATA lv_xml TYPE zif_abapgit_persistence=>ty_content-data_str. DATA: BEGIN OF ls_repo_extract, local_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt, END OF ls_repo_extract. lv_xml = zcl_abapgit_persistence_db=>get_instance( )->read( iv_type = zcl_abapgit_persistence_db=>c_type_repo iv_value = iv_repo_key ). REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_REPO_--29>' IN lv_xml WITH ''. REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. CALL TRANSFORMATION id OPTIONS value_handling = 'accept_data_loss' SOURCE XML lv_xml RESULT repo = ls_repo_extract. IF lines( ls_repo_extract-local_checksums ) = 0. RETURN. ENDIF. CREATE OBJECT lo_cs EXPORTING iv_repo_key = iv_repo_key. lo_cs->force_write( ls_repo_extract-local_checksums ). ENDMETHOD. METHOD get_unconverted_repo_ids. DATA lt_cs_ids TYPE ty_repo_ids. DATA lv_repo_id LIKE LINE OF rt_repo_ids. DATA lv_index TYPE i. SELECT value FROM (zcl_abapgit_persistence_db=>c_tabname) INTO TABLE rt_repo_ids WHERE type = zcl_abapgit_persistence_db=>c_type_repo. SELECT value FROM (zcl_abapgit_persistence_db=>c_tabname) INTO TABLE lt_cs_ids WHERE type = zcl_abapgit_persistence_db=>c_type_repo_csum. LOOP AT rt_repo_ids INTO lv_repo_id. lv_index = sy-tabix. READ TABLE lt_cs_ids TRANSPORTING NO FIELDS WITH KEY table_line = lv_repo_id. IF sy-subrc = 0. " Already converted DELETE rt_repo_ids INDEX lv_index. ENDIF. ENDLOOP. ENDMETHOD. METHOD run. DATA lt_repo_ids TYPE ty_repo_ids. DATA lv_repo_id LIKE LINE OF lt_repo_ids. lt_repo_ids = get_unconverted_repo_ids( ). LOOP AT lt_repo_ids INTO lv_repo_id. convert_checksums( lv_repo_id ). clear_repo_metadata( lv_repo_id ). ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_content_list IMPLEMENTATION. METHOD build_folders. DATA: lv_index TYPE i, lt_subitems LIKE ct_repo_items, ls_subitem LIKE LINE OF ct_repo_items, ls_folder LIKE LINE OF ct_repo_items. DATA lo_state TYPE REF TO zcl_abapgit_repo_item_state. FIELD-SYMBOLS LIKE LINE OF ct_repo_items. LOOP AT ct_repo_items ASSIGNING . lv_index = sy-tabix. CHECK -path <> iv_cur_dir. " files in target dir - just leave them be IF zcl_abapgit_path=>is_subdir( iv_path = -path iv_parent = iv_cur_dir ) = abap_true. ls_subitem-changes = -changes. ls_subitem-path = -path. ls_subitem-lstate = -lstate. ls_subitem-rstate = -rstate. APPEND ls_subitem TO lt_subitems. ENDIF. DELETE ct_repo_items INDEX lv_index. ENDLOOP. SORT lt_subitems BY path ASCENDING. LOOP AT lt_subitems ASSIGNING . AT NEW path. CLEAR ls_folder. ls_folder-path = -path. ls_folder-sortkey = c_sortkey-dir. " Directory ls_folder-is_dir = abap_true. CREATE OBJECT lo_state. ENDAT. ls_folder-changes = ls_folder-changes + -changes. lo_state->sum_with_repo_item( ). AT END OF path. ls_folder-lstate = lo_state->local( ). ls_folder-rstate = lo_state->remote( ). APPEND ls_folder TO ct_repo_items. ENDAT. ENDLOOP. ENDMETHOD. METHOD build_repo_items. DATA: lo_state TYPE REF TO zcl_abapgit_repo_item_state, ls_file TYPE zif_abapgit_definitions=>ty_repo_file, lt_status TYPE zif_abapgit_definitions=>ty_results_tt, ls_item TYPE zif_abapgit_definitions=>ty_item, ls_previous LIKE ls_item, lv_changed_by TYPE string. FIELD-SYMBOLS: LIKE LINE OF lt_status, LIKE LINE OF rt_repo_items. lt_status = zcl_abapgit_repo_status=>calculate( ii_repo = mo_repo ii_log = mi_log ). LOOP AT lt_status ASSIGNING . AT NEW obj_name. "obj_type + obj_name APPEND INITIAL LINE TO rt_repo_items ASSIGNING . -obj_type = -obj_type. -obj_name = -obj_name. -inactive = -inactive. -sortkey = c_sortkey-default. " Default sort key -changes = 0. -path = -path. -srcsystem = -srcsystem. CREATE OBJECT lo_state. ENDAT. IF -filename IS NOT INITIAL. MOVE-CORRESPONDING TO ls_file. ls_file-is_changed = boolc( -match = abap_false ). " TODO refactor APPEND ls_file TO -files. IF -inactive = abap_true AND -sortkey > c_sortkey-changed. -sortkey = c_sortkey-inactive. ENDIF. IF ls_file-is_changed = abap_true. -sortkey = c_sortkey-changed. " Changed files -changes = -changes + 1. lo_state->sum_with_status_item( ). ENDIF. ENDIF. IF -changes > 0 AND -obj_type IS NOT INITIAL. MOVE-CORRESPONDING TO ls_item. IF ls_previous = ls_item. -changed_by = lv_changed_by. ELSEIF zcl_abapgit_objects=>exists( ls_item ) = abap_true. -changed_by = zcl_abapgit_objects=>changed_by( ls_item ). ls_previous = ls_item. lv_changed_by = -changed_by. ENDIF. CLEAR ls_item. ENDIF. AT END OF obj_name. "obj_type + obj_name IF -obj_type IS INITIAL. -sortkey = c_sortkey-orphan. "Virtual objects ENDIF. -lstate = lo_state->local( ). -rstate = lo_state->remote( ). -packmove = lo_state->is_reassigned( ). ENDAT. ENDLOOP. ENDMETHOD. METHOD check_repo_size. CONSTANTS lc_new_repo_size TYPE i VALUE 10. DATA lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt. lt_remote = mo_repo->get_files_remote( ). IF lines( lt_remote ) > lc_new_repo_size. " Less files means it's a new repo (with just readme and license, for example) which is ok READ TABLE lt_remote TRANSPORTING NO FIELDS WITH KEY file_path COMPONENTS path = zif_abapgit_definitions=>c_root_dir filename = zif_abapgit_definitions=>c_dot_abapgit. IF sy-subrc <> 0. mi_log->add_warning( |Cannot find .abapgit.xml - Is this an abapGit repository?| ). ENDIF. ENDIF. ENDMETHOD. METHOD constructor. mo_repo = io_repo. CREATE OBJECT mi_log TYPE zcl_abapgit_log. ENDMETHOD. METHOD determine_transports. DATA ls_item TYPE zif_abapgit_definitions=>ty_item. FIELD-SYMBOLS LIKE LINE OF ct_repo_items. LOOP AT ct_repo_items ASSIGNING . ls_item-obj_type = -obj_type. ls_item-obj_name = -obj_name. TRY. -transport = zcl_abapgit_factory=>get_cts_api( )->get_transport_for_object( ls_item ). CATCH zcx_abapgit_exception ##NO_HANDLER. " Ignore errors related to object check when trying to get transport ENDTRY. ENDLOOP. ENDMETHOD. METHOD filter_changes. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_repo_item. DELETE ct_repo_items WHERE changes = 0 AND inactive = abap_false. LOOP AT ct_repo_items ASSIGNING WHERE inactive = abap_false. DELETE -files WHERE is_changed = abap_false. ENDLOOP. ENDMETHOD. METHOD get_log. DATA li_repo_log TYPE REF TO zif_abapgit_log. DATA lt_repo_msg TYPE zif_abapgit_log=>ty_log_outs. DATA lr_repo_msg TYPE REF TO zif_abapgit_log=>ty_log_out. ri_log = mi_log. "add warning and error messages from repo log li_repo_log = mo_repo->get_log( ). IF li_repo_log IS BOUND. lt_repo_msg = li_repo_log->get_messages( ). LOOP AT lt_repo_msg REFERENCE INTO lr_repo_msg WHERE type CA 'EW'. CASE lr_repo_msg->type. WHEN 'E'. ri_log->add_error( lr_repo_msg->text ). WHEN 'W'. ri_log->add_warning( lr_repo_msg->text ). WHEN OTHERS. CONTINUE. ENDCASE. ENDLOOP. ENDIF. ENDMETHOD. METHOD list. FIELD-SYMBOLS LIKE LINE OF rt_repo_items. mi_log->clear( ). rt_repo_items = build_repo_items( ). check_repo_size( ). IF mo_repo->has_remote_source( ) = abap_false. " If there's no remote source, ignore the item state LOOP AT rt_repo_items ASSIGNING . CLEAR: -changes, -lstate, -rstate. ENDLOOP. ENDIF. IF iv_by_folders = abap_true. build_folders( EXPORTING iv_cur_dir = iv_path CHANGING ct_repo_items = rt_repo_items ). ENDIF. IF iv_changes_only = abap_true. " There are never changes for offline repositories filter_changes( CHANGING ct_repo_items = rt_repo_items ). ENDIF. IF iv_transports = abap_true. determine_transports( CHANGING ct_repo_items = rt_repo_items ). ENDIF. SORT rt_repo_items BY sortkey ASCENDING path ASCENDING obj_name ASCENDING. ENDMETHOD. ENDCLASS. CLASS kHGwlIAZUQfihQNtbCZJXaTWQDiHod DEFINITION DEFERRED. CLASS kHGwlIAZUQfihQNtbCZJprVxXPzzzh DEFINITION DEFERRED. * renamed: zcl_abapgit_repo_checksums :: lcl_checksum_serializer CLASS kHGwlIAZUQfihQNtbCZJprVxXPzzzh DEFINITION FINAL CREATE PUBLIC . PUBLIC SECTION. CONSTANTS c_splitter TYPE string VALUE `|`. CONSTANTS c_root TYPE string VALUE `@`. CLASS-METHODS serialize IMPORTING it_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt RETURNING VALUE(rv_string) TYPE string. CLASS-METHODS deserialize IMPORTING iv_string TYPE string RETURNING VALUE(rt_checksums) TYPE zif_abapgit_persistence=>ty_local_checksum_tt. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS kHGwlIAZUQfihQNtbCZJprVxXPzzzh IMPLEMENTATION. METHOD deserialize. DATA lt_buf_tab TYPE string_table. DATA lv_buf TYPE string. DATA lt_checksums LIKE rt_checksums. FIELD-SYMBOLS LIKE LINE OF lt_checksums. FIELD-SYMBOLS LIKE LINE OF -files. SPLIT iv_string AT |\n| INTO TABLE lt_buf_tab. LOOP AT lt_buf_tab INTO lv_buf. CHECK lv_buf IS NOT INITIAL. " In fact this is a bug ... it cannot be empty, maybe raise IF lv_buf+0(1) = '/'. IF IS NOT ASSIGNED. " Incorrect checksums structure, maybe raise, though it is not critical for execution RETURN. ENDIF. APPEND INITIAL LINE TO -files ASSIGNING . SPLIT lv_buf AT c_splitter INTO -path -filename -sha1. IF -path IS INITIAL OR -filename IS INITIAL OR -sha1 IS INITIAL. " Incorrect checksums structure, maybe raise, though it is not critical for execution RETURN. ENDIF. ELSEIF lv_buf = c_root. " Root APPEND INITIAL LINE TO lt_checksums ASSIGNING . " Empty item ELSE. APPEND INITIAL LINE TO lt_checksums ASSIGNING . SPLIT lv_buf AT c_splitter INTO -item-obj_type -item-obj_name -item-devclass. IF -item-obj_type IS INITIAL OR -item-obj_name IS INITIAL OR -item-devclass IS INITIAL. " Incorrect checksums structure, maybe raise, though it is not critical for execution RETURN. ENDIF. ENDIF. ENDLOOP. rt_checksums = lt_checksums. ENDMETHOD. METHOD serialize. DATA lt_buf_tab TYPE string_table. DATA lv_buf TYPE string. DATA lt_checksums_sorted TYPE zif_abapgit_persistence=>ty_local_checksum_by_item_tt. FIELD-SYMBOLS LIKE LINE OF it_checksums. FIELD-SYMBOLS LIKE LINE OF -files. lt_checksums_sorted = it_checksums. LOOP AT lt_checksums_sorted ASSIGNING . IF lines( -files ) = 0. CONTINUE. ENDIF. IF -item-obj_type IS NOT INITIAL. CONCATENATE -item-obj_type -item-obj_name -item-devclass INTO lv_buf SEPARATED BY c_splitter. ELSE. lv_buf = c_root. ENDIF. APPEND lv_buf TO lt_buf_tab. LOOP AT -files ASSIGNING . CONCATENATE -path -filename -sha1 INTO lv_buf SEPARATED BY c_splitter. APPEND lv_buf TO lt_buf_tab. ENDLOOP. ENDLOOP. rv_string = concat_lines_of( table = lt_buf_tab sep = |\n| ). ENDMETHOD. ENDCLASS. ********************************************************************** * UPDATE CALCULATOR ********************************************************************** * renamed: zcl_abapgit_repo_checksums :: lcl_update_calculator CLASS kHGwlIAZUQfihQNtbCZJXaTWQDiHod DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. CLASS-METHODS calculate_updated IMPORTING it_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt it_current_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt it_local_files TYPE zif_abapgit_definitions=>ty_files_item_tt RETURNING VALUE(rt_checksums) TYPE zif_abapgit_persistence=>ty_local_checksum_tt. PRIVATE SECTION. CLASS-METHODS process_updated_files CHANGING ct_update_index TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts ct_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_by_item_tt. CLASS-METHODS add_new_files IMPORTING it_local TYPE zif_abapgit_definitions=>ty_files_item_tt it_update_index TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts CHANGING ct_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_by_item_tt. ENDCLASS. CLASS kHGwlIAZUQfihQNtbCZJXaTWQDiHod IMPLEMENTATION. METHOD calculate_updated. DATA lt_update_index TYPE zif_abapgit_git_definitions=>ty_file_signatures_ts. DATA lt_checksums_sorted TYPE zif_abapgit_persistence=>ty_local_checksum_by_item_tt. lt_checksums_sorted = it_current_checksums. lt_update_index = it_updated_files. process_updated_files( CHANGING ct_update_index = lt_update_index ct_checksums = lt_checksums_sorted ). add_new_files( EXPORTING it_update_index = lt_update_index it_local = it_local_files CHANGING ct_checksums = lt_checksums_sorted ). rt_checksums = lt_checksums_sorted. ENDMETHOD. METHOD process_updated_files. DATA lv_cs_row TYPE i. DATA lv_file_row TYPE i. FIELD-SYMBOLS LIKE LINE OF ct_checksums. FIELD-SYMBOLS LIKE LINE OF -files. FIELD-SYMBOLS LIKE LINE OF ct_update_index. " Loop through current checksum state, update sha1 for common files LOOP AT ct_checksums ASSIGNING . lv_cs_row = sy-tabix. LOOP AT -files ASSIGNING . lv_file_row = sy-tabix. READ TABLE ct_update_index ASSIGNING WITH KEY path = -path filename = -filename. IF sy-subrc <> 0. CONTINUE. " Missing in updated files -> nothing to update, skip ENDIF. IF -sha1 IS INITIAL. " Empty input sha1 is a deletion marker DELETE -files INDEX lv_file_row. ELSE. -sha1 = -sha1. " Update sha1 CLEAR -sha1. " Mark as processed ENDIF. ENDLOOP. IF lines( -files ) = 0. " Remove empty objects DELETE ct_checksums INDEX lv_cs_row. ENDIF. ENDLOOP. DELETE ct_update_index WHERE sha1 IS INITIAL. " Remove processed ENDMETHOD. METHOD add_new_files. DATA lt_local_sorted TYPE zif_abapgit_definitions=>ty_files_item_by_file_tt. DATA ls_checksum LIKE LINE OF ct_checksums. FIELD-SYMBOLS LIKE LINE OF ct_checksums. FIELD-SYMBOLS LIKE LINE OF it_update_index. FIELD-SYMBOLS LIKE LINE OF lt_local_sorted. lt_local_sorted = it_local. " Add new files - not deleted and not marked as processed LOOP AT it_update_index ASSIGNING . READ TABLE lt_local_sorted ASSIGNING WITH KEY file-path = -path file-filename = -filename. IF sy-subrc <> 0. " The file should be in locals, however: " if the deserialization fails, the local file might not be there " in this case no new CS added, and the file will appear to be remote+new CONTINUE. ENDIF. READ TABLE ct_checksums ASSIGNING WITH KEY item-obj_type = -item-obj_type item-obj_name = -item-obj_name. IF sy-subrc <> 0. MOVE-CORRESPONDING -item TO ls_checksum-item. INSERT ls_checksum INTO TABLE ct_checksums ASSIGNING . ENDIF. APPEND TO -files. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_REPO_CHECKSUMS IMPLEMENTATION. METHOD add_meta. DATA lv_meta_str TYPE string. lv_meta_str = |#repo_name#{ mi_repo->get_name( ) }|. cv_cs_blob = lv_meta_str && |\n| && cv_cs_blob. ENDMETHOD. METHOD build_checksums_from_files. DATA ls_last_item TYPE zif_abapgit_definitions=>ty_item. FIELD-SYMBOLS: LIKE LINE OF rt_checksums, LIKE LINE OF it_local, LIKE LINE OF -files. " This method is run at repo creation moment or manually by user " In the first case it assumes that the local state is the CURRENT state " Thus the idea is to copy local state to checksums " The second case is an exception, when we acknowledge that the state is unknown " Thus copying the local to checksums is the "best guess" LOOP AT it_local ASSIGNING . IF ls_last_item <> -item OR sy-tabix = 1. " First or New item reached ? APPEND INITIAL LINE TO rt_checksums ASSIGNING . MOVE-CORRESPONDING -item TO -item. ls_last_item = -item. ENDIF. APPEND INITIAL LINE TO -files ASSIGNING . MOVE-CORRESPONDING -file TO . ENDLOOP. ENDMETHOD. METHOD constructor. ASSERT iv_repo_key IS NOT INITIAL. mv_repo_key = iv_repo_key. mi_repo = zcl_abapgit_repo_srv=>get_instance( )->get( mv_repo_key ). " Should be safe as repo_srv is supposed to be single source of repo instances ENDMETHOD. METHOD extract_meta. DATA lv_meta_str TYPE string. IF cv_cs_blob+0(1) <> '#'. RETURN. " No meta ? just ignore it ENDIF. SPLIT cv_cs_blob AT |\n| INTO lv_meta_str cv_cs_blob. " Just remove the header meta string - this is OK for now. " There is just repo name for the moment - needed to for DB util and potential debug ENDMETHOD. METHOD force_write. " for migration only for the moment save_checksums( it_checksums ). ENDMETHOD. METHOD remove_non_code_related_files. DELETE ct_local_files WHERE item IS INITIAL AND NOT ( file-path = zif_abapgit_definitions=>c_root_dir AND file-filename = zif_abapgit_definitions=>c_dot_abapgit ). ENDMETHOD. METHOD save_checksums. DATA lv_cs_blob TYPE string. lv_cs_blob = kHGwlIAZUQfihQNtbCZJprVxXPzzzh=>serialize( it_checksums ). add_meta( CHANGING cv_cs_blob = lv_cs_blob ). zcl_abapgit_persist_factory=>get_repo_cs( )->update( iv_key = mv_repo_key iv_cs_blob = lv_cs_blob ). ENDMETHOD. METHOD zif_abapgit_repo_checksums~get. DATA lv_cs_blob TYPE string. TRY. lv_cs_blob = zcl_abapgit_persist_factory=>get_repo_cs( )->read( mv_repo_key ). CATCH zcx_abapgit_exception zcx_abapgit_not_found. " Ignore currently, it's not critical for execution, just return empty RETURN. ENDTRY. IF lv_cs_blob IS NOT INITIAL. extract_meta( CHANGING cv_cs_blob = lv_cs_blob ). rt_checksums = kHGwlIAZUQfihQNtbCZJprVxXPzzzh=>deserialize( lv_cs_blob ). ENDIF. ENDMETHOD. METHOD zif_abapgit_repo_checksums~get_checksums_per_file. DATA lt_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt. FIELD-SYMBOLS LIKE LINE OF lt_checksums. lt_checksums = zif_abapgit_repo_checksums~get( ). LOOP AT lt_checksums ASSIGNING . APPEND LINES OF -files TO rt_checksums. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_repo_checksums~rebuild. DATA lt_local TYPE ty_local_files_by_item_tt. DATA lt_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt. lt_local = mi_repo->get_files_local( ). remove_non_code_related_files( CHANGING ct_local_files = lt_local ). lt_checksums = build_checksums_from_files( lt_local ). save_checksums( lt_checksums ). ENDMETHOD. METHOD zif_abapgit_repo_checksums~update. DATA lt_checksums TYPE zif_abapgit_persistence=>ty_local_checksum_tt. DATA lt_local_files TYPE zif_abapgit_definitions=>ty_files_item_tt. lt_checksums = zif_abapgit_repo_checksums~get( ). lt_local_files = mi_repo->get_files_local( ). lt_checksums = kHGwlIAZUQfihQNtbCZJXaTWQDiHod=>calculate_updated( it_current_checksums = lt_checksums it_local_files = lt_local_files it_updated_files = it_updated_files ). save_checksums( lt_checksums ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo IMPLEMENTATION. METHOD bind_listener. mi_listener = ii_listener. ENDMETHOD. METHOD check_abap_language_version. DATA lo_abapgit_abap_language_vers TYPE REF TO zcl_abapgit_abap_language_vers. DATA lv_text TYPE string. CREATE OBJECT lo_abapgit_abap_language_vers EXPORTING io_dot_abapgit = get_dot_abapgit( ). IF lo_abapgit_abap_language_vers->is_import_allowed( ms_data-package ) = abap_false. lv_text = |Repository cannot be imported. | && |ABAP Language Version of linked package is not compatible with repository settings.|. zcx_abapgit_exception=>raise( lv_text ). ENDIF. ENDMETHOD. METHOD check_language. DATA: lv_main_language TYPE spras, lv_error_message TYPE string, lv_error_longtext TYPE string. " for deserialize, assumes find_remote_dot_abapgit has been called before (or language won't be defined) lv_main_language = get_dot_abapgit( )->get_main_language( ). IF lv_main_language <> sy-langu. lv_error_message = |Current login language | && |'{ zcl_abapgit_convert=>conversion_exit_isola_output( sy-langu ) }'| && | does not match main language | && |'{ zcl_abapgit_convert=>conversion_exit_isola_output( lv_main_language ) }'.|. " Feature open in main language only exists if abapGit tcode is present IF zcl_abapgit_services_abapgit=>get_abapgit_tcode( ) IS INITIAL. lv_error_message = lv_error_message && | Please logon in main language and retry.|. lv_error_longtext = |For the Advanced menu option 'Open in Main Language' to be available a transaction code| && | must be assigned to report { sy-cprog }.|. ELSE. lv_error_message = lv_error_message && | Select 'Advanced' > 'Open in Main Language'|. ENDIF. zcx_abapgit_exception=>raise( iv_text = lv_error_message iv_longtext = lv_error_longtext ). ENDIF. ENDMETHOD. METHOD check_write_protect. IF get_local_settings( )-write_protected = abap_true. zcx_abapgit_exception=>raise( 'Cannot deserialize. Local code is write-protected by repo config' ). ENDIF. ENDMETHOD. METHOD constructor. ASSERT NOT is_data-key IS INITIAL. ms_data = is_data. mv_request_remote_refresh = abap_true. ENDMETHOD. METHOD create_new_log. CREATE OBJECT mi_log TYPE zcl_abapgit_log. mi_log->set_title( iv_title ). ri_log = mi_log. ENDMETHOD. METHOD delete_checks. DATA: li_package TYPE REF TO zif_abapgit_sap_package. check_write_protect( ). check_language( ). li_package = zcl_abapgit_factory=>get_sap_package( get_package( ) ). rs_checks-transport-required = li_package->are_changes_recorded_in_tr_req( ). ENDMETHOD. METHOD deserialize_data. DATA: lt_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt, lt_result TYPE zif_abapgit_data_deserializer=>ty_results. "Deserialize data lt_result = zcl_abapgit_data_factory=>get_deserializer( )->deserialize( ii_config = get_data_config( ) it_files = get_files_remote( ) ). "Save deserialized data to DB and add entries to transport requests lt_updated_files = zcl_abapgit_data_factory=>get_deserializer( )->actualize( it_result = lt_result is_checks = is_checks ). INSERT LINES OF lt_updated_files INTO TABLE ct_files. ENDMETHOD. METHOD deserialize_dot_abapgit. INSERT get_dot_abapgit( )->get_signature( ) INTO TABLE ct_files. ENDMETHOD. METHOD deserialize_objects. DATA: lt_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt, lx_error TYPE REF TO zcx_abapgit_exception. TRY. lt_updated_files = zcl_abapgit_objects=>deserialize( io_repo = me is_checks = is_checks ii_log = ii_log ). CATCH zcx_abapgit_exception INTO lx_error. " Ensure to reset default transport request task zcl_abapgit_factory=>get_default_transport( )->reset( ). refresh( iv_drop_log = abap_false ). RAISE EXCEPTION lx_error. ENDTRY. INSERT LINES OF lt_updated_files INTO TABLE ct_files. ENDMETHOD. METHOD find_remote_dot_apack. FIELD-SYMBOLS: LIKE LINE OF mt_remote. get_files_remote( ). READ TABLE mt_remote ASSIGNING WITH KEY file_path COMPONENTS path = zif_abapgit_definitions=>c_root_dir filename = zif_abapgit_apack_definitions=>c_dot_apack_manifest. IF sy-subrc = 0. ro_dot = zcl_abapgit_apack_reader=>deserialize( iv_package_name = ms_data-package iv_xstr = -data ). set_dot_apack( ro_dot ). ENDIF. ENDMETHOD. METHOD get_data_config. FIELD-SYMBOLS: LIKE LINE OF mt_remote. IF mi_data_config IS BOUND. ri_config = mi_data_config. RETURN. ENDIF. CREATE OBJECT ri_config TYPE zcl_abapgit_data_config. mi_data_config = ri_config. " Assume remote data has been loaded already READ TABLE mt_remote ASSIGNING WITH KEY file_path COMPONENTS path = zif_abapgit_data_config=>c_default_path. IF sy-subrc = 0. ri_config->from_json( mt_remote ). ENDIF. ENDMETHOD. METHOD get_dot_apack. IF mo_apack_reader IS NOT BOUND. mo_apack_reader = zcl_abapgit_apack_reader=>create_instance( ms_data-package ). ENDIF. ro_dot_apack = mo_apack_reader. ENDMETHOD. METHOD get_log. ri_log = mi_log. ENDMETHOD. METHOD get_unsupported_objects_local. DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, lt_supported_types TYPE zcl_abapgit_objects=>ty_types_tt. FIELD-SYMBOLS: LIKE LINE OF lt_tadir, LIKE LINE OF rt_objects. lt_tadir = get_tadir_objects( ). lt_supported_types = zcl_abapgit_objects=>supported_list( ). LOOP AT lt_tadir ASSIGNING . READ TABLE lt_supported_types WITH KEY table_line = -object TRANSPORTING NO FIELDS. IF sy-subrc <> 0. APPEND INITIAL LINE TO rt_objects ASSIGNING . MOVE-CORRESPONDING TO . -obj_type = -object. ENDIF. ENDLOOP. ENDMETHOD. METHOD normalize_local_settings. cs_local_settings-labels = zcl_abapgit_repo_labels=>normalize( cs_local_settings-labels ). " TODO: more validation and normalization ? ENDMETHOD. METHOD notify_listener. DATA ls_meta_slug TYPE zif_abapgit_persistence=>ty_repo_xml. IF mi_listener IS BOUND. MOVE-CORRESPONDING ms_data TO ls_meta_slug. mi_listener->on_meta_change( iv_key = ms_data-key is_meta = ls_meta_slug is_change_mask = is_change_mask ). ENDIF. ENDMETHOD. METHOD refresh_local_object. DATA: ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, lt_new_local_files TYPE zif_abapgit_definitions=>ty_files_item_tt, lo_serialize TYPE REF TO zcl_abapgit_serialize. lt_tadir = get_tadir_objects( ). DELETE mt_local WHERE item-obj_type = iv_obj_type AND item-obj_name = iv_obj_name. READ TABLE lt_tadir INTO ls_tadir WITH KEY object = iv_obj_type obj_name = iv_obj_name. IF sy-subrc <> 0 OR ls_tadir-delflag = abap_true. " object doesn't exist anymore, nothing todo here RETURN. ENDIF. CLEAR lt_tadir. INSERT ls_tadir INTO TABLE lt_tadir. CREATE OBJECT lo_serialize. lt_new_local_files = lo_serialize->serialize( iv_package = ms_data-package it_tadir = lt_tadir ). INSERT LINES OF lt_new_local_files INTO TABLE mt_local. ENDMETHOD. METHOD refresh_local_objects. mv_request_local_refresh = abap_true. get_files_local( ). ENDMETHOD. METHOD remove_ignored_files. DATA lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. DATA lv_index TYPE sy-index. FIELD-SYMBOLS LIKE LINE OF ct_files. lo_dot = get_dot_abapgit( ). " Skip ignored files LOOP AT ct_files ASSIGNING . lv_index = sy-tabix. IF lo_dot->is_ignored( iv_path = -path iv_filename = -filename ) = abap_true. DELETE ct_files INDEX lv_index. ENDIF. ENDLOOP. ENDMETHOD. METHOD reset_remote. CLEAR mt_remote. mv_request_remote_refresh = abap_true. ENDMETHOD. METHOD set. * TODO: refactor, maybe use zcl_abapgit_string_map ? DATA: ls_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask. ASSERT iv_url IS SUPPLIED OR iv_branch_name IS SUPPLIED OR iv_selected_commit IS SUPPLIED OR iv_head_branch IS SUPPLIED OR iv_offline IS SUPPLIED OR is_dot_abapgit IS SUPPLIED OR is_local_settings IS SUPPLIED OR iv_deserialized_by IS SUPPLIED OR iv_deserialized_at IS SUPPLIED OR iv_switched_origin IS SUPPLIED. IF iv_url IS SUPPLIED. ms_data-url = iv_url. ls_mask-url = abap_true. ENDIF. IF iv_branch_name IS SUPPLIED. ms_data-branch_name = iv_branch_name. ls_mask-branch_name = abap_true. ENDIF. IF iv_selected_commit IS SUPPLIED. ms_data-selected_commit = iv_selected_commit. ls_mask-selected_commit = abap_true. ENDIF. IF iv_head_branch IS SUPPLIED. ms_data-head_branch = iv_head_branch. ls_mask-head_branch = abap_true. ENDIF. IF iv_offline IS SUPPLIED. ms_data-offline = iv_offline. ls_mask-offline = abap_true. ENDIF. IF is_dot_abapgit IS SUPPLIED. ms_data-dot_abapgit = is_dot_abapgit. ls_mask-dot_abapgit = abap_true. ENDIF. IF is_local_settings IS SUPPLIED. ms_data-local_settings = is_local_settings. ls_mask-local_settings = abap_true. normalize_local_settings( CHANGING cs_local_settings = ms_data-local_settings ). ENDIF. IF iv_deserialized_at IS SUPPLIED OR iv_deserialized_by IS SUPPLIED. ms_data-deserialized_at = iv_deserialized_at. ms_data-deserialized_by = iv_deserialized_by. ls_mask-deserialized_at = abap_true. ls_mask-deserialized_by = abap_true. ENDIF. IF iv_switched_origin IS SUPPLIED. ms_data-switched_origin = iv_switched_origin. ls_mask-switched_origin = abap_true. ENDIF. notify_listener( ls_mask ). ENDMETHOD. METHOD set_dot_apack. get_dot_apack( ). mo_apack_reader->set_manifest_descriptor( io_dot_apack->get_manifest_descriptor( ) ). ENDMETHOD. METHOD set_files_remote. mt_remote = it_files. mv_request_remote_refresh = abap_false. ENDMETHOD. METHOD set_local_settings. set( is_local_settings = is_settings ). ENDMETHOD. METHOD switch_repo_type. IF iv_offline = ms_data-offline. zcx_abapgit_exception=>raise( |Cannot switch_repo_type, offline already = "{ ms_data-offline }"| ). ENDIF. IF iv_offline = abap_true. " On-line -> OFFline set( iv_url = zcl_abapgit_url=>name( ms_data-url ) iv_branch_name = '' iv_selected_commit = '' iv_head_branch = '' iv_offline = abap_true ). ELSE. " OFFline -> On-line set( iv_offline = abap_false ). ENDIF. ENDMETHOD. METHOD update_last_deserialize. DATA: lv_deserialized_at TYPE zif_abapgit_persistence=>ty_repo-deserialized_at, lv_deserialized_by TYPE zif_abapgit_persistence=>ty_repo-deserialized_by. GET TIME STAMP FIELD lv_deserialized_at. lv_deserialized_by = sy-uname. set( iv_deserialized_at = lv_deserialized_at iv_deserialized_by = lv_deserialized_by ). ENDMETHOD. METHOD zif_abapgit_repo~checksums. CREATE OBJECT ri_checksums TYPE zcl_abapgit_repo_checksums EXPORTING iv_repo_key = ms_data-key. ENDMETHOD. METHOD zif_abapgit_repo~deserialize. DATA lt_updated_files TYPE zif_abapgit_git_definitions=>ty_file_signatures_tt. find_remote_dot_abapgit( ). find_remote_dot_apack( ). check_write_protect( ). check_language( ). IF is_checks-requirements-met = zif_abapgit_definitions=>c_no AND is_checks-requirements-decision IS INITIAL. zcx_abapgit_exception=>raise( 'Requirements not met and undecided' ). ENDIF. IF is_checks-dependencies-met = zif_abapgit_definitions=>c_no AND is_checks-dependencies-decision IS INITIAL. zcx_abapgit_exception=>raise( 'APACK dependencies not met and undecided' ). ENDIF. IF is_checks-transport-required = abap_true AND is_checks-transport-transport IS INITIAL. zcx_abapgit_exception=>raise( |No transport request was supplied| ). ENDIF. deserialize_dot_abapgit( CHANGING ct_files = lt_updated_files ). deserialize_objects( EXPORTING is_checks = is_checks ii_log = ii_log CHANGING ct_files = lt_updated_files ). deserialize_data( EXPORTING is_checks = is_checks CHANGING ct_files = lt_updated_files ). CLEAR mt_local. " Should be before CS update which uses NEW local zif_abapgit_repo~checksums( )->update( lt_updated_files ). update_last_deserialize( ). COMMIT WORK AND WAIT. ENDMETHOD. METHOD zif_abapgit_repo~deserialize_checks. DATA: lt_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt, lt_dependencies TYPE zif_abapgit_apack_definitions=>ty_dependencies. find_remote_dot_abapgit( ). find_remote_dot_apack( ). check_write_protect( ). check_language( ). check_abap_language_version( ). rs_checks = zcl_abapgit_objects=>deserialize_checks( me ). lt_requirements = get_dot_abapgit( )->get_data( )-requirements. rs_checks-requirements-met = zcl_abapgit_repo_requirements=>is_requirements_met( lt_requirements ). lt_dependencies = get_dot_apack( )->get_manifest_descriptor( )-dependencies. rs_checks-dependencies-met = zcl_abapgit_apack_helper=>are_dependencies_met( lt_dependencies ). rs_checks-customizing = zcl_abapgit_data_factory=>get_deserializer( )->deserialize_check( io_repo = me ii_config = get_data_config( ) ). ENDMETHOD. METHOD zif_abapgit_repo~find_remote_dot_abapgit. FIELD-SYMBOLS: LIKE LINE OF mt_remote. get_files_remote( ). READ TABLE mt_remote ASSIGNING WITH KEY file_path COMPONENTS path = zif_abapgit_definitions=>c_root_dir filename = zif_abapgit_definitions=>c_dot_abapgit. IF sy-subrc = 0. ro_dot = zcl_abapgit_dot_abapgit=>deserialize( -data ). set_dot_abapgit( ro_dot ). COMMIT WORK AND WAIT. " to release lock ENDIF. ENDMETHOD. METHOD zif_abapgit_repo~get_dot_abapgit. CREATE OBJECT ro_dot_abapgit EXPORTING is_data = ms_data-dot_abapgit. ENDMETHOD. METHOD zif_abapgit_repo~get_files_local. DATA lo_serialize TYPE REF TO zcl_abapgit_serialize. " Serialization happened before and no refresh request IF lines( mt_local ) > 0 AND mv_request_local_refresh = abap_false. rt_files = mt_local. RETURN. ENDIF. CREATE OBJECT lo_serialize EXPORTING io_dot_abapgit = get_dot_abapgit( ) is_local_settings = get_local_settings( ). rt_files = lo_serialize->files_local( iv_package = get_package( ) ii_data_config = get_data_config( ) ii_log = ii_log ). mt_local = rt_files. mv_request_local_refresh = abap_false. " Fulfill refresh ENDMETHOD. METHOD zif_abapgit_repo~get_files_local_filtered. DATA lo_serialize TYPE REF TO zcl_abapgit_serialize. DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. CREATE OBJECT lo_serialize EXPORTING io_dot_abapgit = get_dot_abapgit( ) is_local_settings = get_local_settings( ). lt_filter = ii_obj_filter->get_filter( ). rt_files = lo_serialize->files_local( iv_package = get_package( ) ii_data_config = get_data_config( ) ii_log = ii_log it_filter = lt_filter ). ENDMETHOD. METHOD zif_abapgit_repo~get_files_remote. DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. DATA lr_filter TYPE REF TO zcl_abapgit_repo_filter. rt_files = mt_remote. "Filter Ignored Files prior to Applying a Filter IF iv_ignore_files = abap_true. remove_ignored_files( CHANGING ct_files = rt_files ). ENDIF. IF ii_obj_filter IS NOT INITIAL. lt_filter = ii_obj_filter->get_filter( ). CREATE OBJECT lr_filter. lr_filter->apply_object_filter( EXPORTING it_filter = lt_filter io_dot = get_dot_abapgit( ) iv_devclass = get_package( ) CHANGING ct_files = rt_files ). ENDIF. ENDMETHOD. METHOD zif_abapgit_repo~get_key. rv_key = ms_data-key. ENDMETHOD. METHOD zif_abapgit_repo~get_local_settings. rs_settings = ms_data-local_settings. ENDMETHOD. METHOD zif_abapgit_repo~get_name. " Local display name has priority over official name rv_name = ms_data-local_settings-display_name. IF rv_name IS INITIAL. rv_name = ms_data-dot_abapgit-name. ENDIF. ENDMETHOD. METHOD zif_abapgit_repo~get_package. rv_package = ms_data-package. ENDMETHOD. METHOD zif_abapgit_repo~get_tadir_objects. rt_tadir = zcl_abapgit_factory=>get_tadir( )->read( iv_package = get_package( ) iv_ignore_subpackages = get_local_settings( )-ignore_subpackages iv_only_local_objects = get_local_settings( )-only_local_objects io_dot = get_dot_abapgit( ) ). ENDMETHOD. METHOD zif_abapgit_repo~has_remote_source. rv_yes = boolc( lines( mt_remote ) > 0 ). ENDMETHOD. METHOD zif_abapgit_repo~is_offline. rv_offline = ms_data-offline. ENDMETHOD. METHOD zif_abapgit_repo~refresh. mv_request_local_refresh = abap_true. reset_remote( ). IF iv_drop_log = abap_true. CLEAR mi_log. ENDIF. IF iv_drop_cache = abap_true. CLEAR mt_local. ENDIF. get_dot_apack( )->refresh( ). ENDMETHOD. METHOD zif_abapgit_repo~set_dot_abapgit. set( is_dot_abapgit = io_dot_abapgit->get_data( ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_dot_abapgit IMPLEMENTATION. METHOD add_ignore. DATA: lv_name TYPE string. FIELD-SYMBOLS: LIKE LINE OF ms_data-ignore. lv_name = iv_path && iv_filename. READ TABLE ms_data-ignore FROM lv_name TRANSPORTING NO FIELDS. IF sy-subrc = 0. RETURN. ENDIF. APPEND INITIAL LINE TO ms_data-ignore ASSIGNING . = lv_name. ENDMETHOD. METHOD build_default. DATA: ls_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit. ls_data-master_language = sy-langu. ls_data-starting_folder = '/src/'. ls_data-folder_logic = zif_abapgit_dot_abapgit=>c_folder_logic-prefix. CREATE OBJECT ro_dot_abapgit EXPORTING is_data = ls_data. ENDMETHOD. METHOD constructor. ms_data = is_data. ENDMETHOD. METHOD deserialize. DATA: lv_xml TYPE string, ls_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit. lv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( iv_xstr ). ls_data = from_xml( lv_xml ). CREATE OBJECT ro_dot_abapgit EXPORTING is_data = ls_data. ENDMETHOD. METHOD determine_i18n_parameters. rs_i18n_params-main_language = get_main_language( ). rs_i18n_params-use_lxe = use_lxe( ). rs_i18n_params-main_language_only = iv_main_language_only. rs_i18n_params-translation_languages = zcl_abapgit_lxe_texts=>get_translation_languages( iv_main_language = get_main_language( ) it_i18n_languages = get_i18n_languages( ) ). ENDMETHOD. METHOD from_xml. DATA: lv_xml TYPE string. lv_xml = iv_xml. CALL TRANSFORMATION id OPTIONS value_handling = 'accept_data_loss' SOURCE XML lv_xml RESULT data = rs_data. * downward compatibility IF rs_data-folder_logic IS INITIAL. rs_data-folder_logic = zif_abapgit_dot_abapgit=>c_folder_logic-prefix. ENDIF. ENDMETHOD. METHOD get_abap_language_version. rv_abap_language_version = ms_data-abap_language_version. ENDMETHOD. METHOD get_data. rs_data = ms_data. ENDMETHOD. METHOD get_folder_logic. rv_logic = ms_data-folder_logic. ENDMETHOD. METHOD get_i18n_languages. rt_languages = ms_data-i18n_languages. ENDMETHOD. METHOD get_main_language. rv_language = ms_data-master_language. IF rv_language IS INITIAL. rv_language = sy-langu. ENDIF. ENDMETHOD. METHOD get_name. rv_name = ms_data-name. ENDMETHOD. METHOD get_original_system. rv_original_system = ms_data-original_system. ENDMETHOD. METHOD get_requirements. rt_requirements = ms_data-requirements. ENDMETHOD. METHOD get_signature. rs_signature-path = zif_abapgit_definitions=>c_root_dir. rs_signature-filename = zif_abapgit_definitions=>c_dot_abapgit. rs_signature-sha1 = zcl_abapgit_hash=>sha1_blob( serialize( ) ). ENDMETHOD. METHOD get_starting_folder. rv_path = ms_data-starting_folder. ENDMETHOD. METHOD get_version_constant. rv_version_constant = ms_data-version_constant. ENDMETHOD. METHOD is_ignored. DATA: lv_name TYPE string, lv_starting TYPE string, lv_dot TYPE string, lv_ignore TYPE string. lv_name = iv_path && iv_filename. CONCATENATE ms_data-starting_folder '*' INTO lv_starting. " Always allow .abapgit.xml and .apack-manifest.xml CONCATENATE '/' zif_abapgit_definitions=>c_dot_abapgit INTO lv_dot. IF lv_name = lv_dot. RETURN. ENDIF. CONCATENATE '/' zif_abapgit_apack_definitions=>c_dot_apack_manifest INTO lv_dot. IF lv_name = lv_dot. RETURN. ENDIF. " Ignore all files matching pattern in ignore list LOOP AT ms_data-ignore INTO lv_ignore. IF lv_name CP lv_ignore. rv_ignored = abap_true. RETURN. ENDIF. ENDLOOP. " Ignore all files outside of starting folder tree IF ms_data-starting_folder <> '/' AND NOT lv_name CP lv_starting. rv_ignored = abap_true. ENDIF. IF iv_path = zif_abapgit_data_config=>c_default_path. rv_ignored = abap_false. ENDIF. ENDMETHOD. METHOD remove_ignore. DATA: lv_name TYPE string. lv_name = iv_path && iv_filename. DELETE TABLE ms_data-ignore FROM lv_name. ENDMETHOD. METHOD serialize. DATA lv_xml TYPE string. lv_xml = to_xml( ms_data ). rv_xstr = zcl_abapgit_convert=>string_to_xstring_utf8_bom( lv_xml ). ENDMETHOD. METHOD set_abap_language_version. ms_data-abap_language_version = iv_abap_language_version. ENDMETHOD. METHOD set_folder_logic. ms_data-folder_logic = iv_logic. ENDMETHOD. METHOD set_i18n_languages. ms_data-i18n_languages = it_languages. ENDMETHOD. METHOD set_name. ms_data-name = iv_name. ENDMETHOD. METHOD set_original_system. ms_data-original_system = iv_original_system. ENDMETHOD. METHOD set_requirements. ms_data-requirements = it_requirements. ENDMETHOD. METHOD set_starting_folder. ms_data-starting_folder = iv_path. ENDMETHOD. METHOD set_version_constant. ms_data-version_constant = iv_version_constant. ENDMETHOD. METHOD to_file. rs_file-path = zif_abapgit_definitions=>c_root_dir. rs_file-filename = zif_abapgit_definitions=>c_dot_abapgit. rs_file-data = serialize( ). rs_file-sha1 = zcl_abapgit_hash=>sha1_blob( rs_file-data ). ENDMETHOD. METHOD to_xml. CALL TRANSFORMATION id OPTIONS initial_components = 'suppress' SOURCE data = is_data RESULT XML rv_xml. rv_xml = zcl_abapgit_xml_pretty=>print( rv_xml ). REPLACE FIRST OCCURRENCE OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' IN rv_xml WITH ''. ASSERT sy-subrc = 0. ENDMETHOD. METHOD use_lxe. IF iv_yes <> abap_undefined. ms_data-use_lxe = iv_yes. ENDIF. rv_yes = ms_data-use_lxe. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_zip IMPLEMENTATION. METHOD encode_files. DATA: lo_zip TYPE REF TO cl_abap_zip, lv_filename TYPE string. FIELD-SYMBOLS: LIKE LINE OF it_files. CREATE OBJECT lo_zip. LOOP AT it_files ASSIGNING . CONCATENATE -file-path+1 -file-filename INTO lv_filename. lo_zip->add( name = lv_filename content = -file-data ). ENDLOOP. rv_xstr = lo_zip->save( ). ENDMETHOD. METHOD export. DATA li_log TYPE REF TO zif_abapgit_log. DATA lt_zip TYPE zif_abapgit_definitions=>ty_files_item_tt. DATA lo_serialize TYPE REF TO zcl_abapgit_serialize. CREATE OBJECT li_log TYPE zcl_abapgit_log. li_log->set_title( 'Zip Export Log' ). IF zcl_abapgit_factory=>get_sap_package( iv_package )->exists( ) = abap_false. zcx_abapgit_exception=>raise( |Package { iv_package } doesn't exist| ). ENDIF. CREATE OBJECT lo_serialize EXPORTING io_dot_abapgit = io_dot_abapgit is_local_settings = is_local_settings. lt_zip = lo_serialize->files_local( iv_package = iv_package ii_log = li_log it_filter = it_filter ). FREE lo_serialize. IF li_log->count( ) > 0 AND iv_show_log = abap_true. zcl_abapgit_log_viewer=>show_log( li_log ). ENDIF. rv_xstr = encode_files( lt_zip ). ENDMETHOD. METHOD export_object. DATA: ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, lv_folder TYPE string, lv_fullpath TYPE string, lv_sep TYPE c LENGTH 1, ls_files_item TYPE zif_abapgit_objects=>ty_serialization, lo_frontend_serv TYPE REF TO zif_abapgit_frontend_services. FIELD-SYMBOLS: LIKE LINE OF ls_files_item-files. ls_tadir = zcl_abapgit_factory=>get_tadir( )->read_single( iv_object = iv_object_type iv_obj_name = iv_object_name ). IF ls_tadir IS INITIAL. zcx_abapgit_exception=>raise( 'Object could not be found' ). ENDIF. ls_files_item-item-obj_type = ls_tadir-object. ls_files_item-item-obj_name = ls_tadir-obj_name. ls_files_item-item-abap_language_version = '*'. "any ls_files_item = zcl_abapgit_objects=>serialize( is_item = ls_files_item-item io_i18n_params = zcl_abapgit_i18n_params=>new( iv_main_language_only = iv_main_language_only iv_main_language = sy-langu ) ). IF lines( ls_files_item-files ) = 0. zcx_abapgit_exception=>raise( 'Empty' ). ENDIF. lo_frontend_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). lo_frontend_serv->directory_browse( CHANGING cv_selected_folder = lv_folder ). IF lv_folder IS INITIAL. RAISE EXCEPTION TYPE zcx_abapgit_cancel. ENDIF. lo_frontend_serv->get_file_separator( CHANGING cv_file_separator = lv_sep ). LOOP AT ls_files_item-files ASSIGNING . lv_fullpath = |{ lv_folder }{ lv_sep }{ -filename }|. save_binstring_to_localfile( iv_filename = lv_fullpath iv_binstring = -data ). ENDLOOP. ENDMETHOD. METHOD export_package. DATA: ls_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings, lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit, lo_frontend_serv TYPE REF TO zif_abapgit_frontend_services, lv_default TYPE string, lv_package_escaped TYPE string, lv_path TYPE string, lv_zip_xstring TYPE xstring. ls_local_settings-main_language_only = iv_main_lang_only. ls_local_settings-ignore_subpackages = iv_ign_subpkg. lo_dot_abapgit = zcl_abapgit_dot_abapgit=>build_default( ). lo_dot_abapgit->set_folder_logic( iv_folder_logic ). lo_frontend_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). lv_package_escaped = iv_package. REPLACE ALL OCCURRENCES OF '/' IN lv_package_escaped WITH '#'. lv_default = |{ lv_package_escaped }_{ sy-datlo }_{ sy-timlo }.zip|. lv_zip_xstring = export( is_local_settings = ls_local_settings iv_package = iv_package io_dot_abapgit = lo_dot_abapgit ). lv_path = lo_frontend_serv->show_file_save_dialog( iv_title = 'Package Export' iv_extension = 'zip' iv_default_filename = lv_default ). lo_frontend_serv->file_download( iv_path = lv_path iv_xstr = lv_zip_xstring ). ENDMETHOD. METHOD filename. IF iv_str CA '/'. FIND REGEX '(.*/)(.*)' IN iv_str SUBMATCHES ev_path ev_filename. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Malformed path' ). ENDIF. IF ev_path <> '/'. CONCATENATE '/' ev_path INTO ev_path. ENDIF. ELSE. ev_path = '/'. ev_filename = iv_str. ENDIF. TRANSLATE ev_filename TO LOWER CASE. ENDMETHOD. METHOD load. rt_files = unzip_file( iv_xstr ). ENDMETHOD. METHOD normalize_path. * removes first folder from path if needed DATA: lt_split TYPE TABLE OF string, lv_needed TYPE abap_bool, lv_length TYPE i, lv_split LIKE LINE OF lt_split. FIELD-SYMBOLS: LIKE LINE OF ct_files. READ TABLE ct_files INDEX 1 ASSIGNING . IF sy-subrc <> 0. RETURN. ENDIF. SPLIT -path AT '/' INTO TABLE lt_split. IF sy-subrc <> 0. RETURN. ENDIF. READ TABLE lt_split INDEX 2 INTO lv_split. IF sy-subrc <> 0 OR strlen( lv_split ) = 0. RETURN. ENDIF. CONCATENATE '/' lv_split '/*' INTO lv_split. lv_needed = abap_true. LOOP AT ct_files ASSIGNING . IF NOT -path CP lv_split. lv_needed = abap_false. EXIT. " current loop ENDIF. ENDLOOP. IF lv_needed = abap_true. lv_length = strlen( lv_split ) - 2. LOOP AT ct_files ASSIGNING . -path = -path+lv_length. ENDLOOP. ENDIF. ENDMETHOD. METHOD save_binstring_to_localfile. zcl_abapgit_ui_factory=>get_frontend_services( )->file_download( iv_path = iv_filename iv_xstr = iv_binstring ). ENDMETHOD. METHOD unzip_file. DATA: lo_zip TYPE REF TO cl_abap_zip, lv_data TYPE xstring. FIELD-SYMBOLS: LIKE LINE OF lo_zip->files, LIKE LINE OF rt_files. CREATE OBJECT lo_zip. lo_zip->load( EXPORTING zip = iv_xstr EXCEPTIONS zip_parse_error = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from zip' ). ENDIF. LOOP AT lo_zip->files ASSIGNING . lo_zip->get( EXPORTING name = -name IMPORTING content = lv_data EXCEPTIONS zip_index_error = 1 zip_decompression_error = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from zip get' ). ENDIF. APPEND INITIAL LINE TO rt_files ASSIGNING . filename( EXPORTING iv_str = -name IMPORTING ev_path = -path ev_filename = -filename ). -data = lv_data. -sha1 = zcl_abapgit_hash=>sha1_blob( -data ). ENDLOOP. DELETE rt_files WHERE filename IS INITIAL. normalize_path( CHANGING ct_files = rt_files ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_version IMPLEMENTATION. METHOD check_dependant_version. CONSTANTS: lc_message TYPE string VALUE 'Current version is older than required'. IF is_dependant-major > is_current-major. zcx_abapgit_exception=>raise( lc_message ). ELSEIF is_dependant-major < is_current-major. RETURN. ENDIF. IF is_dependant-minor > is_current-minor. zcx_abapgit_exception=>raise( lc_message ). ELSEIF is_dependant-minor < is_current-minor. RETURN. ENDIF. IF is_dependant-patch > is_current-patch. zcx_abapgit_exception=>raise( lc_message ). ELSEIF is_dependant-patch < is_current-patch. RETURN. ENDIF. IF is_current-prerelase IS INITIAL. RETURN. ENDIF. CASE is_current-prerelase. WHEN 'rc'. IF is_dependant-prerelase = ''. zcx_abapgit_exception=>raise( lc_message ). ENDIF. WHEN 'beta'. IF is_dependant-prerelase = '' OR is_dependant-prerelase = 'rc'. zcx_abapgit_exception=>raise( lc_message ). ENDIF. WHEN 'alpha'. IF is_dependant-prerelase = '' OR is_dependant-prerelase = 'rc' OR is_dependant-prerelase = 'beta'. zcx_abapgit_exception=>raise( lc_message ). ENDIF. ENDCASE. IF is_dependant-prerelase = is_current-prerelase AND is_dependant-prerelase_patch > is_current-prerelase_patch. zcx_abapgit_exception=>raise( lc_message ). ENDIF. ENDMETHOD. METHOD compare. DATA: ls_version_a TYPE zif_abapgit_definitions=>ty_version, ls_version_b TYPE zif_abapgit_definitions=>ty_version. TRY. IF is_a IS NOT INITIAL. ls_version_a = is_a. ELSE. ls_version_a = conv_str_to_version( iv_a ). ENDIF. IF is_b IS NOT INITIAL. ls_version_b = is_b. ELSE. ls_version_b = conv_str_to_version( iv_b ). ENDIF. CATCH zcx_abapgit_exception. rv_result = 0. RETURN. ENDTRY. IF ls_version_a = ls_version_b. rv_result = 0. ELSE. TRY. check_dependant_version( is_current = ls_version_a is_dependant = ls_version_b ). rv_result = 1. CATCH zcx_abapgit_exception. rv_result = -1. RETURN. ENDTRY. ENDIF. ENDMETHOD. METHOD conv_str_to_version. DATA: lt_segments TYPE STANDARD TABLE OF string, lt_parts TYPE STANDARD TABLE OF string, lv_segment TYPE string. SPLIT iv_version AT '-' INTO TABLE lt_segments. READ TABLE lt_segments INTO lv_segment INDEX 1. " Version IF sy-subrc <> 0. " No version RETURN. ENDIF. SPLIT lv_segment AT '.' INTO TABLE lt_parts. LOOP AT lt_parts INTO lv_segment. TRY. CASE sy-tabix. WHEN 1. rs_version-major = lv_segment. WHEN 2. rs_version-minor = lv_segment. WHEN 3. rs_version-patch = lv_segment. ENDCASE. CATCH cx_sy_conversion_no_number. zcx_abapgit_exception=>raise( 'Incorrect format for Semantic Version' ). ENDTRY. ENDLOOP. READ TABLE lt_segments INTO lv_segment INDEX 2. " Pre-release Version IF sy-subrc <> 0. " No version RETURN. ENDIF. SPLIT lv_segment AT '.' INTO TABLE lt_parts. LOOP AT lt_parts INTO lv_segment. CASE sy-tabix. WHEN 1. rs_version-prerelase = lv_segment. TRANSLATE rs_version-prerelase TO LOWER CASE. WHEN 2. rs_version-prerelase_patch = lv_segment. ENDCASE. ENDLOOP. IF rs_version-prerelase <> 'rc' AND rs_version-prerelase <> 'beta' AND rs_version-prerelase <> 'alpha'. zcx_abapgit_exception=>raise( 'Incorrect format for Semantic Version' ). ENDIF. ENDMETHOD. METHOD get_version_constant_value. DATA: lv_version_class TYPE seoclsname, lv_version_component TYPE string. FIELD-SYMBOLS: TYPE string. IF iv_version_constant NP '*=>*'. zcx_abapgit_exception=>raise( 'Version constant needs to use the format CLASS/INTERFACE=>CONSTANT' ). ENDIF. SPLIT iv_version_constant AT '=>' INTO lv_version_class lv_version_component. IF sy-subrc <> 0 OR lv_version_class IS INITIAL OR lv_version_component IS INITIAL. zcx_abapgit_exception=>raise( 'Version constant cannot be parsed' ). ENDIF. " You should remember that accessing a class or an interface with syntax errors " gives us a shortdump. Therefore we do a syntax check here. zcl_abapgit_oo_factory=>get_by_name( lv_version_class )->syntax_check( lv_version_class ). ASSIGN (lv_version_class)=>(lv_version_component) TO . IF sy-subrc = 0. rv_version = . ELSE. zcx_abapgit_exception=>raise( |Could not access version at class { lv_version_class } component | && |{ lv_version_component }| ). ENDIF. ENDMETHOD. METHOD normalize. " Internal program version should be in format "XXX.XXX.XXX" or "vXXX.XXX.XXX" CONSTANTS: lc_version_pattern TYPE string VALUE '^v?(\d{1,3}\.\d{1,3}\.\d{1,3})\s*$', lc_prerelease_pattern TYPE string VALUE '^((rc|beta|alpha)\.\d{1,3})\s*$'. DATA: lv_version TYPE string, lv_prerelease TYPE string, lv_version_n TYPE string, lv_prerelease_n TYPE string. SPLIT iv_version AT '-' INTO lv_version lv_prerelease. FIND FIRST OCCURRENCE OF REGEX lc_version_pattern IN lv_version SUBMATCHES lv_version_n. IF lv_prerelease IS NOT INITIAL. FIND FIRST OCCURRENCE OF REGEX lc_prerelease_pattern IN lv_prerelease SUBMATCHES lv_prerelease_n. ENDIF. IF lv_version_n IS INITIAL. RETURN. ENDIF. rv_version = lv_version_n. IF lv_prerelease_n IS NOT INITIAL. CONCATENATE rv_version '-' lv_prerelease_n INTO rv_version. ENDIF. ENDMETHOD. METHOD version_to_numeric. DATA: lv_major TYPE n LENGTH 4, lv_minor TYPE n LENGTH 4, lv_release TYPE n LENGTH 4. SPLIT iv_version AT '.' INTO lv_major lv_minor lv_release. " Calculated value of version number, empty version will become 0 which is OK rv_version = lv_major * 1000000 + lv_minor * 1000 + lv_release. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_requirements IMPLEMENTATION. METHOD get_cvers. IF gt_cvers IS NOT INITIAL. rt_cvers = gt_cvers. RETURN. ENDIF. SELECT * FROM cvers INTO TABLE rt_cvers ORDER BY PRIMARY KEY. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error reading installed components| ). ENDIF. ENDMETHOD. METHOD get_requirement_met_status. DATA: lt_installed TYPE ty_cvers. FIELD-SYMBOLS: TYPE zif_abapgit_dot_abapgit=>ty_requirement, TYPE ty_requirement_status, TYPE cvers. lt_installed = get_cvers( ). LOOP AT it_requirements ASSIGNING . APPEND INITIAL LINE TO rt_status ASSIGNING . -component = -component. -required_release = -min_release. -required_patch = -min_patch. READ TABLE lt_installed WITH KEY component = -component ASSIGNING . IF sy-subrc = 0. " Component is installed, requirement is met if the installed version is greater or equal " to the required one. -installed_release = -release. -installed_patch = -extrelease. SELECT SINGLE desc_text FROM cvers_ref INTO -description WHERE component = -component AND langu = sy-langu ##SUBRC_OK. -met = is_version_greater_or_equal( ). ELSE. " Component is not installed at all -met = abap_false. ENDIF. UNASSIGN . ENDLOOP. ENDMETHOD. METHOD inject_cvers. " For testing only gt_cvers = it_cvers. ENDMETHOD. METHOD is_requirements_met. DATA: lt_met_status TYPE ty_requirement_status_tt. lt_met_status = get_requirement_met_status( it_requirements ). READ TABLE lt_met_status TRANSPORTING NO FIELDS WITH KEY met = abap_false. IF sy-subrc = 0. rv_status = zif_abapgit_definitions=>c_no. ELSE. rv_status = zif_abapgit_definitions=>c_yes. ENDIF. ENDMETHOD. METHOD is_version_greater_or_equal. DATA: lv_installed_release TYPE n LENGTH 4, lv_installed_patch TYPE n LENGTH 4, lv_required_release TYPE n LENGTH 4, lv_required_patch TYPE n LENGTH 4. TRY. MOVE EXACT: is_status-installed_release TO lv_installed_release, is_status-installed_patch TO lv_installed_patch, is_status-required_release TO lv_required_release, is_status-required_patch TO lv_required_patch. CATCH cx_sy_conversion_error. " Cannot compare by number, assume requirement not fulfilled (user can force install " anyways if this was an error) rv_true = abap_false. RETURN. ENDTRY. " Versions are comparable by number, compare release and if necessary patch level IF lv_installed_release > lv_required_release OR ( lv_installed_release = lv_required_release AND ( lv_required_patch = 0 OR lv_installed_patch >= lv_required_patch ) ). rv_true = abap_true. ENDIF. ENDMETHOD. METHOD requirements_popup. DATA: lt_met_status TYPE ty_requirement_status_tt, lv_answer TYPE c LENGTH 1. lt_met_status = get_requirement_met_status( it_requirements ). show_requirement_popup( lt_met_status ). lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = 'Warning' iv_text_question = 'The project has unmet requirements. Do you want to continue?' ). IF lv_answer <> '1'. zcx_abapgit_exception=>raise( 'Cancelling because of unmet requirements.' ). ENDIF. ENDMETHOD. METHOD show_requirement_popup. TYPES: BEGIN OF ty_color_line, color TYPE lvc_t_scol. INCLUDE TYPE ty_requirement_status. TYPES: END OF ty_color_line. TYPES: ty_color_tab TYPE STANDARD TABLE OF ty_color_line WITH DEFAULT KEY. DATA: lo_alv TYPE REF TO cl_salv_table, lo_column TYPE REF TO cl_salv_column, lo_columns TYPE REF TO cl_salv_columns_table, lt_color_table TYPE ty_color_tab, lt_color_negative TYPE lvc_t_scol, lt_color_positive TYPE lvc_t_scol, ls_color TYPE lvc_s_scol, ls_position TYPE zif_abapgit_popups=>ty_popup_position, lx_ex TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE ty_color_line, LIKE LINE OF it_requirements. ls_color-color-col = col_negative. APPEND ls_color TO lt_color_negative. ls_color-color-col = col_positive. APPEND ls_color TO lt_color_positive. CLEAR ls_color. LOOP AT it_requirements ASSIGNING . APPEND INITIAL LINE TO lt_color_table ASSIGNING . MOVE-CORRESPONDING TO . ENDLOOP. LOOP AT lt_color_table ASSIGNING . IF -met = abap_false. -color = lt_color_negative. ELSE. -color = lt_color_positive. ENDIF. ENDLOOP. UNASSIGN . TRY. cl_salv_table=>factory( IMPORTING r_salv_table = lo_alv CHANGING t_table = lt_color_table ). lo_columns = lo_alv->get_columns( ). lo_columns->get_column( 'MET' )->set_short_text( 'Met' ). lo_columns->set_color_column( 'COLOR' ). lo_columns->set_optimize( ). lo_column = lo_columns->get_column( 'REQUIRED_RELEASE' ). lo_column->set_short_text( 'Req. Rel.' ). lo_column = lo_columns->get_column( 'REQUIRED_PATCH' ). lo_column->set_short_text( 'Req. SP L.' ). ls_position = zcl_abapgit_popups=>center( iv_width = 70 iv_height = 10 ). lo_alv->set_screen_popup( start_column = ls_position-start_column end_column = ls_position-end_column start_line = ls_position-start_row end_line = ls_position-end_row ). lo_alv->get_display_settings( )->set_list_header( 'Requirements' ). lo_alv->display( ). CATCH cx_salv_msg cx_salv_not_found cx_salv_data_error INTO lx_ex. zcx_abapgit_exception=>raise( lx_ex->get_text( ) ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_news IMPLEMENTATION. METHOD constructor. DATA: lt_lines TYPE string_table, lv_string TYPE string, ls_log_line LIKE LINE OF mt_log. " Validate params mv_current_version = zcl_abapgit_version=>normalize( iv_current_version ). mv_lastseen_version = zcl_abapgit_version=>normalize( iv_lastseen_version ). IF mv_current_version IS INITIAL. RETURN. " Internal format of program version is not correct -> abort parsing ENDIF. lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( iv_rawdata ). lt_lines = zcl_abapgit_convert=>split_string( lv_string ). mt_log = parse( it_lines = lt_lines iv_current_version = mv_current_version ). READ TABLE mt_log INTO ls_log_line INDEX 1. mv_latest_version = ls_log_line-version. " Empty if not found ENDMETHOD. METHOD create. CONSTANTS: " TODO refactor lc_log_path TYPE string VALUE '/', lc_log_filename TYPE string VALUE 'changelog*', lc_log_filename_up TYPE string VALUE 'CHANGELOG*'. DATA: lo_apack TYPE REF TO zcl_abapgit_apack_reader, lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt, lv_version TYPE string, lv_last_seen TYPE string, lv_url TYPE string, lo_repo_online TYPE REF TO zcl_abapgit_repo_online, lv_version_constant TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit-version_constant. FIELD-SYMBOLS LIKE LINE OF lt_remote. IF io_repo->is_offline( ) = abap_true. RETURN. ENDIF. lo_repo_online ?= io_repo. lv_url = lo_repo_online->get_url( ). lo_apack = io_repo->get_dot_apack( ). IF lo_apack IS BOUND. lv_version = lo_apack->get_manifest_descriptor( )-version. ENDIF. IF lv_version IS INITIAL. TRY. lv_version_constant = io_repo->get_dot_abapgit( )->get_version_constant( ). IF lv_version_constant IS NOT INITIAL. lv_version = zcl_abapgit_version=>get_version_constant_value( lv_version_constant ). ENDIF. CATCH zcx_abapgit_exception. CLEAR lv_version. ENDTRY. ENDIF. IF lv_version IS INITIAL. RETURN. ENDIF. lv_last_seen = zcl_abapgit_persistence_user=>get_instance( )->get_repo_last_change_seen( lv_url ). TRY. " Find changelog lt_remote = io_repo->get_files_remote( ). CATCH zcx_abapgit_exception. RETURN. ENDTRY. LOOP AT lt_remote ASSIGNING WHERE path = lc_log_path AND ( filename CP lc_log_filename OR filename CP lc_log_filename_up ). CREATE OBJECT ro_instance EXPORTING iv_rawdata = -data iv_current_version = lv_version iv_lastseen_version = zcl_abapgit_version=>normalize( lv_last_seen ). EXIT. ENDLOOP. IF ro_instance IS BOUND AND lv_last_seen <> ro_instance->latest_version( ). zcl_abapgit_persistence_user=>get_instance( )->set_repo_last_change_seen( iv_url = lv_url iv_version = ro_instance->latest_version( ) ). ENDIF. ENDMETHOD. METHOD get_log. rt_log = mt_log. ENDMETHOD. METHOD has_important. READ TABLE mt_log WITH KEY is_important = abap_true TRANSPORTING NO FIELDS. rv_boolean = boolc( sy-subrc IS INITIAL ). ENDMETHOD. METHOD has_news. rv_boolean = boolc( lines( mt_log ) > 0 ). ENDMETHOD. METHOD has_unseen. rv_boolean = boolc( zcl_abapgit_version=>compare( iv_a = mv_latest_version iv_b = mv_lastseen_version ) > 0 ). ENDMETHOD. METHOD has_updates. rv_boolean = boolc( zcl_abapgit_version=>compare( iv_a = mv_latest_version iv_b = mv_current_version ) > 0 ). ENDMETHOD. METHOD latest_version. rv_version = mv_latest_version. ENDMETHOD. METHOD parse. DATA: lv_tail TYPE i, lv_first_version_found TYPE abap_bool, lv_version TYPE string, ls_log LIKE LINE OF rt_log. FIELD-SYMBOLS: LIKE LINE OF it_lines. LOOP AT it_lines ASSIGNING . ls_log = parse_line( iv_line = iv_current_version = iv_current_version ). " Skip until first version head and Skip empty lines CHECK ls_log IS NOT INITIAL AND ( lv_first_version_found = abap_true OR ls_log-version IS NOT INITIAL ). IF lv_first_version_found = abap_false. lv_first_version_found = abap_true. IF zcl_abapgit_version=>compare( iv_a = ls_log-version iv_b = iv_current_version ) <= 0. lv_tail = c_tail_length. " Display some last versions if no updates ENDIF. ENDIF. IF ls_log-is_header = abap_true. "Skip everything below current version or show tail news IF zcl_abapgit_version=>compare( iv_a = ls_log-version iv_b = iv_current_version ) <= 0. IF lv_tail > 0. lv_tail = lv_tail - 1. ELSE. EXIT. ENDIF. ENDIF. lv_version = ls_log-version. " Save to fill news lines ELSE. ls_log-version = lv_version. ENDIF. APPEND ls_log TO rt_log. ENDLOOP. ENDMETHOD. METHOD parse_line. CONSTANTS: lc_header_pattern TYPE string VALUE '^\d{4}-\d{2}-\d{2}\s+v(\d{1,3}\.\d{1,3}\.\d{1,3})\s*$'. DATA: lv_version TYPE string. IF iv_line IS INITIAL OR iv_line CO ' -='. RETURN. " Skip empty and markup lines ENDIF. " Check if line is a header line FIND FIRST OCCURRENCE OF REGEX lc_header_pattern IN iv_line SUBMATCHES lv_version. IF sy-subrc IS INITIAL. lv_version = zcl_abapgit_version=>normalize( lv_version ). rs_log-version = lv_version. rs_log-is_header = abap_true. rs_log-pos_to_cur = zcl_abapgit_version=>compare( iv_a = lv_version iv_b = iv_current_version ). ELSE. FIND FIRST OCCURRENCE OF REGEX '^\s*!' IN iv_line. rs_log-is_important = boolc( sy-subrc IS INITIAL ). " Change is important ENDIF. rs_log-text = iv_line. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_labels IMPLEMENTATION. METHOD class_constructor. gv_regex = |^[{ c_allowed_chars }]*$|. " Must start with - ENDMETHOD. METHOD normalize. DATA lt_labels TYPE string_table. DATA lt_normalized TYPE string_table. FIELD-SYMBOLS LIKE LINE OF lt_labels. lt_labels = split( iv_labels ). LOOP AT lt_labels ASSIGNING . FIND REGEX gv_regex IN . IF sy-subrc = 0. APPEND TO lt_normalized. ENDIF. ENDLOOP. SORT lt_normalized. DELETE ADJACENT DUPLICATES FROM lt_normalized. rv_labels = concat_lines_of( table = lt_normalized sep = `, ` ). ENDMETHOD. METHOD normalize_colors. DATA lt_colors TYPE ty_label_colors. DATA lt_normalized TYPE ty_label_colors. DATA lt_pairs TYPE string_table. DATA lv_pair TYPE string. FIELD-SYMBOLS LIKE LINE OF lt_colors. lt_colors = split_colors( iv_config ). LOOP AT lt_colors ASSIGNING . TRY. validate_one_label_color( ). APPEND TO lt_normalized. CATCH zcx_abapgit_exception. ENDTRY. ENDLOOP. SORT lt_normalized BY label. DELETE ADJACENT DUPLICATES FROM lt_normalized COMPARING label. LOOP AT lt_normalized ASSIGNING . lv_pair = -label && `:` && -color. APPEND lv_pair TO lt_pairs. ENDLOOP. rv_config = concat_lines_of( table = lt_pairs sep = `, ` ). ENDMETHOD. METHOD parse_color. DATA lv_tmp TYPE string. IF iv_color IS INITIAL. RETURN. ENDIF. IF iv_color+0(1) = '#'. lv_tmp = iv_color+1. SPLIT lv_tmp AT '/' INTO rs_parsed-fg rs_parsed-bg rs_parsed-border. ELSE. rs_parsed-cls = iv_color. ENDIF. ENDMETHOD. METHOD split. FIELD-SYMBOLS LIKE LINE OF rt_labels. SPLIT iv_labels AT ',' INTO TABLE rt_labels. LOOP AT rt_labels ASSIGNING . CONDENSE . ENDLOOP. DELETE rt_labels WHERE table_line IS INITIAL. ENDMETHOD. METHOD split_colors. DATA lt_pairs TYPE string_table. DATA lv_clean_config LIKE iv_config. DATA ls_c LIKE LINE OF rt_label_colors. FIELD-SYMBOLS LIKE LINE OF lt_pairs. lv_clean_config = replace( val = iv_config sub = cl_abap_char_utilities=>newline with = ` ` ). " text area ends with LF SPLIT lv_clean_config AT ',' INTO TABLE lt_pairs. LOOP AT lt_pairs ASSIGNING . CONDENSE . IF IS NOT INITIAL. SPLIT AT ':' INTO ls_c-label ls_c-color. CONDENSE ls_c-label. CONDENSE ls_c-color. APPEND ls_c TO rt_label_colors. ENDIF. ENDLOOP. ENDMETHOD. METHOD split_colors_into_map. DATA lt_colors TYPE ty_label_colors. FIELD-SYMBOLS LIKE LINE OF lt_colors. lt_colors = split_colors( iv_config ). ro_map = zcl_abapgit_string_map=>create( ). LOOP AT lt_colors ASSIGNING . TRY. ro_map->set( iv_key = -label iv_val = -color ). CATCH zcx_abapgit_exception. ENDTRY. ENDLOOP. ENDMETHOD. METHOD validate. DATA lt_labels TYPE string_table. FIELD-SYMBOLS LIKE LINE OF lt_labels. lt_labels = split( iv_labels ). LOOP AT lt_labels ASSIGNING . FIND REGEX gv_regex IN . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Disallowed chars in label #{ sy-tabix }| ). ENDIF. " TODO: maybe also limit length ? ENDLOOP. ENDMETHOD. METHOD validate_colors. DATA lt_colors TYPE ty_label_colors. FIELD-SYMBOLS LIKE LINE OF lt_colors. lt_colors = split_colors( iv_config ). LOOP AT lt_colors ASSIGNING . validate_one_label_color( is_lc = iv_index = sy-tabix ). ENDLOOP. ENDMETHOD. METHOD validate_one_label_color. DATA ls_parsed_color TYPE ty_color. IF is_lc-label IS INITIAL. zcx_abapgit_exception=>raise( |Label is empty in pair #{ iv_index }| ). ENDIF. IF is_lc-color IS INITIAL. zcx_abapgit_exception=>raise( |Color is empty in pair #{ iv_index }| ). ENDIF. FIND REGEX gv_regex IN is_lc-label. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Disallowed chars in label in pair #{ iv_index }| ). ENDIF. ls_parsed_color = parse_color( is_lc-color ). IF ls_parsed_color-cls IS NOT INITIAL. FIND REGEX '^[-_A-Za-z]+$' IN ls_parsed_color-cls. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Disallowed chars in color in pair #{ iv_index }| ). ENDIF. ENDIF. IF ls_parsed_color-fg IS NOT INITIAL. validate_rgb_color( ls_parsed_color-fg ). ENDIF. IF ls_parsed_color-bg IS NOT INITIAL. validate_rgb_color( ls_parsed_color-bg ). ENDIF. IF ls_parsed_color-border IS NOT INITIAL. validate_rgb_color( ls_parsed_color-border ). ENDIF. ENDMETHOD. METHOD validate_rgb_color. DATA lv_len TYPE i. IF iv_color IS NOT INITIAL. FIND REGEX '^[0-9A-Fa-f]+$' IN iv_color. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Disallowed chars in color in pair #{ iv_index }| ). ENDIF. lv_len = strlen( iv_color ). IF NOT ( lv_len = 3 OR lv_len = 6 ). zcx_abapgit_exception=>raise( |Incorrect color in pair #{ iv_index }| ). ENDIF. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_item_state IMPLEMENTATION. METHOD is_reassigned. rv_is_reassigned = mv_is_reassigned. ENDMETHOD. METHOD is_unchanged. rv_is_unchanged = boolc( mv_is_reassigned = abap_false AND mv_lstate = zif_abapgit_definitions=>c_state-unchanged AND mv_rstate = zif_abapgit_definitions=>c_state-unchanged ). ENDMETHOD. METHOD local. rv_state = mv_lstate. ENDMETHOD. METHOD reduce. rv_new = iv_prev. IF rv_new = iv_cur OR iv_cur IS INITIAL. RETURN. " No change ELSEIF rv_new IS INITIAL. rv_new = iv_cur. ELSE. rv_new = zif_abapgit_definitions=>c_state-mixed. ENDIF. ENDMETHOD. METHOD remote. rv_state = mv_rstate. ENDMETHOD. METHOD sum_with_repo_item. mv_lstate = reduce( iv_prev = mv_lstate iv_cur = is_repo_item-lstate ). mv_rstate = reduce( iv_prev = mv_rstate iv_cur = is_repo_item-rstate ). mv_is_reassigned = boolc( mv_is_reassigned = abap_true OR is_repo_item-packmove = abap_true ). ENDMETHOD. METHOD sum_with_status_item. mv_lstate = reduce( iv_prev = mv_lstate iv_cur = is_status_item-lstate ). mv_rstate = reduce( iv_prev = mv_rstate iv_cur = is_status_item-rstate ). mv_is_reassigned = boolc( mv_is_reassigned = abap_true OR is_status_item-packmove = abap_true ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_stage_logic IMPLEMENTATION. METHOD remove_identical. DATA: lv_index TYPE i, ls_remote LIKE LINE OF cs_files-remote. FIELD-SYMBOLS: LIKE LINE OF cs_files-local. SORT cs_files-remote BY path filename. LOOP AT cs_files-local ASSIGNING . lv_index = sy-tabix. READ TABLE cs_files-remote INTO ls_remote WITH KEY path = -file-path filename = -file-filename BINARY SEARCH. IF sy-subrc = 0. DELETE cs_files-remote INDEX sy-tabix. IF ls_remote-sha1 = -file-sha1. DELETE cs_files-local INDEX lv_index. ENDIF. ENDIF. ENDLOOP. ENDMETHOD. METHOD remove_ignored. DATA: lv_index TYPE i. FIELD-SYMBOLS: LIKE LINE OF cs_files-remote, LIKE LINE OF cs_files-local. LOOP AT cs_files-remote ASSIGNING . lv_index = sy-tabix. IF io_repo->get_dot_abapgit( )->is_ignored( iv_path = -path iv_filename = -filename ) = abap_true. DELETE cs_files-remote INDEX lv_index. ELSEIF -path = zif_abapgit_definitions=>c_root_dir AND -filename = zif_abapgit_definitions=>c_dot_abapgit. " Remove .abapgit from remotes - it cannot be removed or ignored DELETE cs_files-remote INDEX lv_index. ENDIF. ENDLOOP. LOOP AT cs_files-local ASSIGNING . lv_index = sy-tabix. IF io_repo->get_dot_abapgit( )->is_ignored( iv_path = -file-path iv_filename = -file-filename ) = abap_true. DELETE cs_files-local INDEX lv_index. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_stage_logic~get. " Getting REMOTE before LOCAL is critical to ensure that DATA config is loaded first rs_files-remote = io_repo->get_files_remote( ii_obj_filter ). IF ii_obj_filter IS INITIAL. rs_files-local = io_repo->get_files_local( ). ELSE. rs_files-local = io_repo->get_files_local_filtered( ii_obj_filter ). ENDIF. rs_files-status = zcl_abapgit_repo_status=>calculate( ii_repo = io_repo ii_obj_filter = ii_obj_filter ). remove_identical( CHANGING cs_files = rs_files ). remove_ignored( EXPORTING io_repo = io_repo CHANGING cs_files = rs_files ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_stage IMPLEMENTATION. METHOD add. append( iv_path = iv_path iv_filename = iv_filename iv_method = zif_abapgit_definitions=>c_method-add is_status = is_status iv_data = iv_data ). ENDMETHOD. METHOD append. DATA: ls_stage LIKE LINE OF mt_stage. FIELD-SYMBOLS: LIKE LINE OF mt_stage. READ TABLE mt_stage WITH KEY file-path = iv_path file-filename = iv_filename ASSIGNING . IF sy-subrc = 0. -file-data = iv_data. -method = iv_method. ELSE. ls_stage-file-path = iv_path. ls_stage-file-filename = iv_filename. ls_stage-file-data = iv_data. ls_stage-method = iv_method. ls_stage-status = is_status. INSERT ls_stage INTO TABLE mt_stage. ENDIF. ENDMETHOD. METHOD constructor. mv_merge_source = iv_merge_source. ENDMETHOD. METHOD count. rv_count = lines( mt_stage ). ENDMETHOD. METHOD get_all. rt_stage = mt_stage. ENDMETHOD. METHOD get_merge_source. rv_source = mv_merge_source. ENDMETHOD. METHOD ignore. append( iv_path = iv_path iv_filename = iv_filename iv_method = zif_abapgit_definitions=>c_method-ignore ). ENDMETHOD. METHOD method_description. CASE iv_method. WHEN zif_abapgit_definitions=>c_method-add. rv_description = 'add'. WHEN zif_abapgit_definitions=>c_method-rm. rv_description = 'remove'. WHEN zif_abapgit_definitions=>c_method-ignore. rv_description = 'ignore'. WHEN OTHERS. zcx_abapgit_exception=>raise( 'unknown staging method type' ). ENDCASE. ENDMETHOD. METHOD reset. DELETE mt_stage WHERE file-path = iv_path AND file-filename = iv_filename. ASSERT sy-subrc = 0. ENDMETHOD. METHOD rm. append( iv_path = iv_path iv_filename = iv_filename is_status = is_status iv_method = zif_abapgit_definitions=>c_method-rm ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_merge IMPLEMENTATION. METHOD all_files. APPEND LINES OF ms_merge-stree TO rt_files. APPEND LINES OF ms_merge-ttree TO rt_files. APPEND LINES OF ms_merge-ctree TO rt_files. SORT rt_files BY path DESCENDING name ASCENDING. DELETE ADJACENT DUPLICATES FROM rt_files COMPARING path name. ENDMETHOD. METHOD calculate_result. DATA: lt_files TYPE zif_abapgit_git_definitions=>ty_expanded_tt, lv_found_source TYPE abap_bool, lv_found_target TYPE abap_bool, lv_found_common TYPE abap_bool. FIELD-SYMBOLS: LIKE LINE OF lt_files, LIKE LINE OF lt_files, LIKE LINE OF lt_files, LIKE LINE OF lt_files, LIKE LINE OF ms_merge-result, LIKE LINE OF mt_objects, LIKE LINE OF mt_conflicts. lt_files = all_files( ). CREATE OBJECT ms_merge-stage EXPORTING iv_merge_source = ms_merge-source-sha1. LOOP AT lt_files ASSIGNING . UNASSIGN . UNASSIGN . UNASSIGN . READ TABLE ms_merge-stree ASSIGNING WITH KEY path_name COMPONENTS path = -path name = -name. "#EC CI_SUBRC READ TABLE ms_merge-ttree ASSIGNING WITH KEY path_name COMPONENTS path = -path name = -name. "#EC CI_SUBRC READ TABLE ms_merge-ctree ASSIGNING WITH KEY path_name COMPONENTS path = -path name = -name. "#EC CI_SUBRC lv_found_source = boolc( IS ASSIGNED ). lv_found_target = boolc( IS ASSIGNED ). lv_found_common = boolc( IS ASSIGNED ). IF lv_found_source = abap_false AND lv_found_target = abap_false. * deleted in source and target, skip CONTINUE. ELSEIF lv_found_source = abap_false AND lv_found_common = abap_true AND -sha1 = -sha1. * deleted in source, skip ms_merge-stage->rm( iv_path = -path iv_filename = -name ). CONTINUE. ELSEIF lv_found_target = abap_false AND lv_found_common = abap_true AND -sha1 = -sha1. * deleted in target, skip CONTINUE. ENDIF. APPEND INITIAL LINE TO ms_merge-result ASSIGNING . -path = -path. -name = -name. IF lv_found_target = abap_false. * added in source READ TABLE mt_objects ASSIGNING WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-blob sha1 = -sha1. ASSERT sy-subrc = 0. ms_merge-stage->add( iv_path = -path iv_filename = -name iv_data = -data ). -sha1 = -sha1. CONTINUE. ELSEIF lv_found_source = abap_false. * added in target -sha1 = -sha1. ELSEIF lv_found_common = abap_false AND -sha1 = -sha1. * added in source and target -sha1 = -sha1. ELSEIF lv_found_common = abap_false AND -sha1 <> -sha1. INSERT INITIAL LINE INTO TABLE mt_conflicts ASSIGNING . -path = -path. -filename = -name. -source_sha1 = -sha1. READ TABLE mt_objects ASSIGNING WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-blob sha1 = -sha1. -source_data = -data. -target_sha1 = -sha1. READ TABLE mt_objects ASSIGNING WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-blob sha1 = -sha1. -target_data = -data. * added in source and target, but different, merge conflict must be resolved ms_merge-conflict = |{ -name } merge conflict|. CONTINUE. ENDIF. IF lv_found_source = abap_false OR lv_found_target = abap_false OR lv_found_common = abap_false. ms_merge-conflict = |{ -name } merge conflict, not found anywhere|. CONTINUE. ENDIF. IF -sha1 = -sha1. * target and source match -sha1 = -sha1. ELSEIF -sha1 = -sha1. * changed in source READ TABLE mt_objects ASSIGNING WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-blob sha1 = -sha1. ASSERT sy-subrc = 0. ms_merge-stage->add( iv_path = -path iv_filename = -name iv_data = -data ). -sha1 = -sha1. ELSEIF -sha1 = -sha1. * changed in target -sha1 = -sha1. ELSE. * changed in source and target, conflict * conflict must be resolved before merge INSERT INITIAL LINE INTO TABLE mt_conflicts ASSIGNING . -path = -path. -filename = -name. -source_sha1 = -sha1. READ TABLE mt_objects ASSIGNING WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-blob sha1 = -sha1. -source_data = -data. -target_sha1 = -sha1. READ TABLE mt_objects ASSIGNING WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-blob sha1 = -sha1. -target_data = -data. ms_merge-conflict = |{ -name } merge conflict, changed in source and target branch|. ENDIF. ENDLOOP. ENDMETHOD. METHOD constructor. IF iv_source_branch = io_repo->get_selected_branch( ). zcx_abapgit_exception=>raise( 'source = target' ). ENDIF. mo_repo = io_repo. mv_source_branch = iv_source_branch. ENDMETHOD. METHOD fetch_git. DATA: lo_branch_list TYPE REF TO zcl_abapgit_git_branch_list, lt_upload TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. lo_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( ms_merge-repo->get_url( ) ). ms_merge-source = lo_branch_list->find_by_name( zcl_abapgit_git_branch_list=>complete_heads_branch_name( mv_source_branch ) ). ms_merge-target = lo_branch_list->find_by_name( zcl_abapgit_git_branch_list=>complete_heads_branch_name( mo_repo->get_selected_branch( ) ) ). APPEND ms_merge-source TO lt_upload. APPEND ms_merge-target TO lt_upload. zcl_abapgit_git_transport=>upload_pack_by_branch( EXPORTING iv_url = ms_merge-repo->get_url( ) iv_branch_name = ms_merge-repo->get_selected_branch( ) iv_deepen_level = 0 it_branches = lt_upload IMPORTING et_objects = rt_objects ). ENDMETHOD. METHOD find_ancestors. DATA: ls_commit TYPE zcl_abapgit_git_pack=>ty_commit, lt_visit TYPE ty_visit_tt, lv_commit LIKE LINE OF lt_visit. FIELD-SYMBOLS: LIKE LINE OF rt_ancestors, LIKE LINE OF mt_objects. APPEND iv_commit TO lt_visit. LOOP AT lt_visit INTO lv_commit. READ TABLE mt_objects ASSIGNING WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-commit sha1 = lv_commit. ASSERT sy-subrc = 0. ls_commit = zcl_abapgit_git_pack=>decode_commit( -data ). visit( EXPORTING iv_parent = ls_commit-parent CHANGING ct_visit = lt_visit ). visit( EXPORTING iv_parent = ls_commit-parent2 CHANGING ct_visit = lt_visit ). APPEND INITIAL LINE TO rt_ancestors ASSIGNING . -commit = lv_commit. -tree = ls_commit-tree. -body = ls_commit-body. -time = ls_commit-author. "Strip Author entry of all but the time component REPLACE ALL OCCURRENCES OF REGEX '[a-zA-Z<>@.-]*' IN -time WITH ''. CONDENSE -time. ENDLOOP. SORT rt_ancestors BY time DESCENDING. ENDMETHOD. METHOD find_first_common. FIELD-SYMBOLS: LIKE LINE OF it_list1, LIKE LINE OF it_list2. LOOP AT it_list1 ASSIGNING . LOOP AT it_list2 ASSIGNING . IF -tree = -tree. rs_common = . RETURN. ENDIF. ENDLOOP. ENDLOOP. zcx_abapgit_exception=>raise( 'error finding common ancestor' ). ENDMETHOD. METHOD visit. IF NOT iv_parent IS INITIAL. READ TABLE ct_visit FROM iv_parent TRANSPORTING NO FIELDS. IF sy-subrc <> 0. APPEND iv_parent TO ct_visit. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_merge~get_conflicts. rt_conflicts = mt_conflicts. ENDMETHOD. METHOD zif_abapgit_merge~get_result. rs_merge = ms_merge. ENDMETHOD. METHOD zif_abapgit_merge~get_source_branch. rv_source_branch = mv_source_branch. ENDMETHOD. METHOD zif_abapgit_merge~has_conflicts. rv_conflicts_exists = boolc( lines( mt_conflicts ) > 0 ). ENDMETHOD. METHOD zif_abapgit_merge~resolve_conflict. FIELD-SYMBOLS: TYPE zif_abapgit_merge=>ty_merge_conflict, LIKE LINE OF ms_merge-result. IF is_conflict-result_sha1 IS NOT INITIAL AND is_conflict-result_data IS NOT INITIAL. READ TABLE mt_conflicts ASSIGNING WITH KEY path = is_conflict-path filename = is_conflict-filename. IF sy-subrc = 0. READ TABLE ms_merge-result ASSIGNING WITH KEY path_name COMPONENTS path = is_conflict-path name = is_conflict-filename. IF sy-subrc = 0. -sha1 = is_conflict-result_sha1. ms_merge-stage->add( iv_path = -path iv_filename = -filename iv_data = is_conflict-result_data ). DELETE mt_conflicts WHERE path = is_conflict-path AND filename = is_conflict-filename. ENDIF. READ TABLE ms_merge-result ASSIGNING WITH KEY sha1 = space. IF sy-subrc = 0. ms_merge-conflict = |{ -name } merge conflict, changed in source and target branch|. ELSE. CLEAR ms_merge-conflict. ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_merge~run. DATA: lt_asource TYPE ty_ancestor_tt, lt_atarget TYPE ty_ancestor_tt. CLEAR: ms_merge, mt_objects, mt_conflicts. ms_merge-repo = mo_repo. mt_objects = fetch_git( ). lt_asource = find_ancestors( ms_merge-source-sha1 ). lt_atarget = find_ancestors( ms_merge-target-sha1 ). ms_merge-common = find_first_common( it_list1 = lt_asource it_list2 = lt_atarget ). ms_merge-stree = zcl_abapgit_git_porcelain=>full_tree( it_objects = mt_objects iv_parent = ms_merge-source-sha1 ). ms_merge-ttree = zcl_abapgit_git_porcelain=>full_tree( it_objects = mt_objects iv_parent = ms_merge-target-sha1 ). ms_merge-ctree = zcl_abapgit_git_porcelain=>full_tree( it_objects = mt_objects iv_parent = ms_merge-common-commit ). calculate_result( ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_repo_filter IMPLEMENTATION. METHOD apply. DATA: lt_filter TYPE SORTED TABLE OF zif_abapgit_definitions=>ty_tadir WITH NON-UNIQUE KEY object obj_name, lv_index TYPE i. FIELD-SYMBOLS: LIKE LINE OF ct_tadir. filter_generated_tadir( CHANGING ct_tadir = ct_tadir ). IF lines( it_filter ) = 0. RETURN. ENDIF. lt_filter = it_filter. * this is another loop at TADIR, but typically the filter is blank LOOP AT ct_tadir ASSIGNING . lv_index = sy-tabix. READ TABLE lt_filter TRANSPORTING NO FIELDS WITH KEY object = -object obj_name = -obj_name BINARY SEARCH. IF sy-subrc <> 0. DELETE ct_tadir INDEX lv_index. ENDIF. ENDLOOP. ENDMETHOD. METHOD apply_object_filter. DATA lr_file TYPE REF TO zif_abapgit_git_definitions=>ty_file. DATA ls_item TYPE zif_abapgit_definitions=>ty_item. DATA ls_tadir TYPE zif_abapgit_definitions=>ty_tadir. DATA lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. DATA lt_filter TYPE SORTED TABLE OF zif_abapgit_definitions=>ty_tadir WITH NON-UNIQUE KEY object obj_name. lt_filter = it_filter. LOOP AT ct_files REFERENCE INTO lr_file. IF lr_file->filename = zif_abapgit_definitions=>c_dot_abapgit. CONTINUE. ENDIF. zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = lr_file->filename iv_path = lr_file->path iv_devclass = iv_devclass io_dot = io_dot IMPORTING es_item = ls_item ). CLEAR lt_tadir. CLEAR ls_tadir. ls_tadir-object = ls_item-obj_type. ls_tadir-obj_name = ls_item-obj_name. ls_tadir-devclass = ls_item-devclass. INSERT ls_tadir INTO TABLE lt_tadir. filter_generated_tadir( CHANGING ct_tadir = lt_tadir ). IF lt_tadir IS INITIAL. DELETE ct_files. CONTINUE. ENDIF. READ TABLE lt_filter TRANSPORTING NO FIELDS WITH KEY object = ls_tadir-object obj_name = ls_tadir-obj_name BINARY SEARCH. IF sy-subrc <> 0. DELETE ct_files. ENDIF. ENDLOOP. ENDMETHOD. METHOD filter_generated_tadir. DATA: ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, ls_tadir_gen TYPE zif_abapgit_definitions=>ty_tadir, lv_cd_object TYPE cdobjectcl, lt_cd_names TYPE STANDARD TABLE OF cdnames, ls_cd_names TYPE cdnames, lt_tcdrs TYPE STANDARD TABLE OF tcdrs, ls_tcdrs TYPE tcdrs. LOOP AT ct_tadir INTO ls_tadir WHERE pgmid = 'R3TR' AND object = 'CHDO'. CLEAR: lv_cd_object, lt_cd_names, ls_tadir_gen, lt_tcdrs, ls_tcdrs. lv_cd_object = ls_tadir-obj_name. CALL FUNCTION 'CDNAMES_GET' EXPORTING iv_object = lv_cd_object TABLES it_names = lt_cd_names it_tcdrs = lt_tcdrs EXCEPTIONS object_space = 1 object_not_found = 2 OTHERS = 3. IF sy-subrc <> 0. CONTINUE. ENDIF. LOOP AT lt_cd_names INTO ls_cd_names. DELETE ct_tadir WHERE pgmid = 'R3TR' AND ( ( object = 'PROG' AND ( obj_name = ls_cd_names-repnamec OR obj_name = ls_cd_names-repnamet OR obj_name = ls_cd_names-repnamefix OR obj_name = ls_cd_names-repnamevar ) ) OR object = 'FUGR' AND obj_name = ls_cd_names-fgrp ). ENDLOOP. LOOP AT lt_tcdrs INTO ls_tcdrs. DELETE ct_tadir WHERE pgmid = 'R3TR' AND object = 'TABL' AND obj_name = ls_tcdrs-tabname. ENDLOOP. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_filter_tran IMPLEMENTATION. METHOD adjust_local_filter. DATA lt_e071_filter TYPE ty_e071_filter_tt. DATA lr_e071_filter TYPE REF TO ty_e071_filter. DATA ls_filter TYPE zif_abapgit_definitions=>ty_tadir. DATA lv_trobj_name_new TYPE trobj_name. DATA lv_trobj_type_new TYPE tadir-object. DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. DATA lr_cts_api TYPE REF TO zif_abapgit_cts_api. lt_e071_filter = it_e071_filter. LOOP AT lt_e071_filter REFERENCE INTO lr_e071_filter. IF lr_e071_filter->pgmid = 'LIMU'. "Get Main Object from LIMU Object (Example the Class (R3TR) of a Method (LIMU)) lr_cts_api = zcl_abapgit_factory=>get_cts_api( ). TRY. lr_cts_api->get_r3tr_obj_for_limu_obj( EXPORTING iv_object = lr_e071_filter->object iv_obj_name = lr_e071_filter->obj_name IMPORTING ev_object = lv_trobj_type_new ev_obj_name = lv_trobj_name_new ). CATCH zcx_abapgit_exception. CONTINUE. ENDTRY. CLEAR ls_filter. ls_filter-pgmid = 'R3TR'. ls_filter-object = lv_trobj_type_new. ls_filter-obj_name = lv_trobj_name_new. ELSE. ls_filter-pgmid = lr_e071_filter->pgmid. ls_filter-object = lr_e071_filter->object. ls_filter-obj_name = lr_e071_filter->obj_name. ENDIF. INSERT ls_filter INTO TABLE rt_filter. ENDLOOP. IF iv_package IS NOT INITIAL. ls_filter-pgmid = 'R3TR'. ls_filter-object = 'DEVC'. ls_filter-obj_name = iv_package. INSERT ls_filter INTO TABLE rt_filter. lt_filter = get_all_sub_packages( iv_package ). INSERT LINES OF lt_filter INTO TABLE rt_filter. ENDIF. SORT rt_filter. DELETE ADJACENT DUPLICATES FROM rt_filter. IF rt_filter IS INITIAL. zcx_abapgit_exception=>raise( 'No objects found for transport filter' ). ENDIF. ENDMETHOD. METHOD generate_local_filter. DATA lt_e071_filter TYPE ty_e071_filter_tt. SELECT DISTINCT pgmid object obj_name INTO CORRESPONDING FIELDS OF TABLE lt_e071_filter FROM e071 WHERE trkorr IN it_r_trkorr ORDER BY pgmid object obj_name. IF sy-subrc <> 0. CLEAR lt_e071_filter. ENDIF. rt_filter = adjust_local_filter( iv_package = iv_package it_e071_filter = lt_e071_filter ). ENDMETHOD. METHOD get_all_sub_packages. DATA li_package TYPE REF TO zif_abapgit_sap_package. DATA lt_list TYPE zif_abapgit_sap_package=>ty_devclass_tt. DATA lr_list TYPE REF TO devclass. DATA ls_filter TYPE zif_abapgit_definitions=>ty_tadir. li_package = zcl_abapgit_factory=>get_sap_package( iv_package ). lt_list = li_package->list_subpackages( ). LOOP AT lt_list REFERENCE INTO lr_list. ls_filter-pgmid = 'R3TR'. ls_filter-object = 'DEVC'. ls_filter-obj_name = lr_list->*. INSERT ls_filter INTO TABLE rt_filter. ENDLOOP. ENDMETHOD. METHOD get_filter_values. et_r_trkorr = mt_r_trkorr. ev_package = mv_package. ENDMETHOD. METHOD init. CLEAR mt_filter. CLEAR mt_r_trkorr. CLEAR mv_package. ENDMETHOD. METHOD set_filter_values. init( ). mt_r_trkorr = it_r_trkorr. mv_package = iv_package. IF it_r_trkorr IS NOT INITIAL. mt_filter = generate_local_filter( iv_package = mv_package it_r_trkorr = mt_r_trkorr ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object_filter~get_filter. rt_filter = mt_filter. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_persistence_user IMPLEMENTATION. METHOD constructor. mv_user = iv_user. read( ). ENDMETHOD. METHOD from_xml. DATA: lv_xml TYPE string. lv_xml = iv_xml. * fix downward compatibility REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_USER_--29>' IN lv_xml WITH ''. REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. CALL TRANSFORMATION id OPTIONS value_handling = 'accept_data_loss' SOURCE XML lv_xml RESULT user = rs_user. ENDMETHOD. METHOD get_instance. IF iv_user = sy-uname ##USER_OK. IF gi_current_user IS NOT BOUND. CREATE OBJECT gi_current_user TYPE zcl_abapgit_persistence_user. ENDIF. ri_user = gi_current_user. ELSE. CREATE OBJECT ri_user TYPE zcl_abapgit_persistence_user EXPORTING iv_user = iv_user. ENDIF. ENDMETHOD. METHOD read. DATA: lv_xml TYPE string. TRY. lv_xml = zcl_abapgit_persistence_db=>get_instance( )->read( iv_type = zcl_abapgit_persistence_db=>c_type_user iv_value = mv_user ). CATCH zcx_abapgit_not_found. RETURN. ENDTRY. ms_user = from_xml( lv_xml ). ENDMETHOD. METHOD read_repo_config. DATA lv_url TYPE string. lv_url = to_lower( iv_url ). READ TABLE ms_user-repo_config INTO rs_repo_config WITH KEY url = lv_url. ENDMETHOD. METHOD to_xml. CALL TRANSFORMATION id SOURCE user = is_user RESULT XML rv_xml. ENDMETHOD. METHOD update. DATA: lv_xml TYPE string. lv_xml = to_xml( ms_user ). zcl_abapgit_persistence_db=>get_instance( )->modify( iv_type = zcl_abapgit_persistence_db=>c_type_user iv_value = mv_user iv_data = lv_xml ). COMMIT WORK AND WAIT. ENDMETHOD. METHOD update_repo_config. DATA: lv_key TYPE string. FIELD-SYMBOLS TYPE ty_repo_config. lv_key = to_lower( iv_url ). READ TABLE ms_user-repo_config ASSIGNING WITH KEY url = lv_key. IF sy-subrc IS NOT INITIAL. APPEND INITIAL LINE TO ms_user-repo_config ASSIGNING . ENDIF. = is_repo_config. -url = lv_key. update( ). ENDMETHOD. METHOD zif_abapgit_persist_user~get_changes_only. rv_changes_only = ms_user-changes_only. ENDMETHOD. METHOD zif_abapgit_persist_user~get_default_git_user_email. rv_email = ms_user-default_git_user-email. ENDMETHOD. METHOD zif_abapgit_persist_user~get_default_git_user_name. rv_username = ms_user-default_git_user-name. ENDMETHOD. METHOD zif_abapgit_persist_user~get_diff_first. rv_diff_first = ms_user-diff_first. ENDMETHOD. METHOD zif_abapgit_persist_user~get_diff_unified. rv_diff_unified = ms_user-diff_unified. ENDMETHOD. METHOD zif_abapgit_persist_user~get_favorites. rt_favorites = ms_user-favorites. ENDMETHOD. METHOD zif_abapgit_persist_user~get_hide_files. rv_hide = ms_user-hide_files. ENDMETHOD. METHOD zif_abapgit_persist_user~get_list_settings. rs_list_settings = ms_user-list_settings. IF rs_list_settings IS INITIAL. " for performance reasons, set "only favorites" as a default IF zcl_abapgit_repo_srv=>get_instance( )->list_favorites( ) IS NOT INITIAL. rs_list_settings-only_favorites = abap_true. ENDIF. rs_list_settings-order_by = |NAME|. ENDIF. ENDMETHOD. METHOD zif_abapgit_persist_user~get_order_by. rv_order_by = ms_user-order_by. ENDMETHOD. METHOD zif_abapgit_persist_user~get_order_descending. rv_order_descending = ms_user-order_descending. ENDMETHOD. METHOD zif_abapgit_persist_user~get_repo_git_user_email. rv_email = read_repo_config( iv_url )-git_user-email. ENDMETHOD. METHOD zif_abapgit_persist_user~get_repo_git_user_name. rv_username = read_repo_config( iv_url )-git_user-name. ENDMETHOD. METHOD zif_abapgit_persist_user~get_repo_last_change_seen. rv_version = read_repo_config( iv_url )-last_change_seen. ENDMETHOD. METHOD zif_abapgit_persist_user~get_repo_login. rv_login = read_repo_config( iv_url )-login. ENDMETHOD. METHOD zif_abapgit_persist_user~get_repo_show. rv_key = ms_user-repo_show. IF rv_key IS INITIAL. RETURN. ENDIF. " Check if repo exists TRY. zcl_abapgit_persistence_db=>get_instance( )->read( iv_type = zcl_abapgit_persistence_db=>c_type_repo iv_value = rv_key ). CATCH zcx_abapgit_not_found. " remove invalid key CLEAR rv_key. zif_abapgit_persist_user~set_repo_show( rv_key ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_persist_user~get_settings. rs_user_settings = ms_user-settings. ENDMETHOD. METHOD zif_abapgit_persist_user~get_show_folders. rv_folders = ms_user-show_folders. ENDMETHOD. METHOD zif_abapgit_persist_user~is_favorite_repo. READ TABLE ms_user-favorites TRANSPORTING NO FIELDS WITH KEY table_line = iv_repo_key. rv_yes = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_persist_user~set_default_git_user_email. ms_user-default_git_user-email = iv_email. update( ). ENDMETHOD. METHOD zif_abapgit_persist_user~set_default_git_user_name. ms_user-default_git_user-name = iv_username. update( ). ENDMETHOD. METHOD zif_abapgit_persist_user~set_diff_first. ms_user-diff_first = iv_diff_first. update( ). rv_diff_first = ms_user-diff_first. ENDMETHOD. METHOD zif_abapgit_persist_user~set_list_settings. ms_user-list_settings = is_list_settings. update( ). ENDMETHOD. METHOD zif_abapgit_persist_user~set_order_by. ms_user-order_by = iv_order_by. update( ). rv_order_by = ms_user-order_by. ENDMETHOD. METHOD zif_abapgit_persist_user~set_order_descending. ms_user-order_descending = iv_order_descending. update( ). rv_order_descending = ms_user-order_descending. ENDMETHOD. METHOD zif_abapgit_persist_user~set_repo_git_user_email. DATA: ls_repo_config TYPE ty_repo_config. ls_repo_config = read_repo_config( iv_url ). ls_repo_config-git_user-email = iv_email. update_repo_config( iv_url = iv_url is_repo_config = ls_repo_config ). ENDMETHOD. METHOD zif_abapgit_persist_user~set_repo_git_user_name. DATA: ls_repo_config TYPE ty_repo_config. ls_repo_config = read_repo_config( iv_url ). ls_repo_config-git_user-name = iv_username. update_repo_config( iv_url = iv_url is_repo_config = ls_repo_config ). ENDMETHOD. METHOD zif_abapgit_persist_user~set_repo_last_change_seen. DATA: ls_repo_config TYPE ty_repo_config. ls_repo_config = read_repo_config( iv_url ). ls_repo_config-last_change_seen = iv_version. update_repo_config( iv_url = iv_url is_repo_config = ls_repo_config ). ENDMETHOD. METHOD zif_abapgit_persist_user~set_repo_login. DATA: ls_repo_config TYPE ty_repo_config. ls_repo_config = read_repo_config( iv_url ). ls_repo_config-login = iv_login. update_repo_config( iv_url = iv_url is_repo_config = ls_repo_config ). ENDMETHOD. METHOD zif_abapgit_persist_user~set_repo_show. ms_user-repo_show = iv_key. update( ). ENDMETHOD. METHOD zif_abapgit_persist_user~set_settings. ms_user-settings = is_user_settings. update( ). ENDMETHOD. METHOD zif_abapgit_persist_user~toggle_changes_only. ms_user-changes_only = boolc( ms_user-changes_only = abap_false ). update( ). rv_changes_only = ms_user-changes_only. ENDMETHOD. METHOD zif_abapgit_persist_user~toggle_diff_unified. ms_user-diff_unified = boolc( ms_user-diff_unified = abap_false ). update( ). rv_diff_unified = ms_user-diff_unified. ENDMETHOD. METHOD zif_abapgit_persist_user~toggle_favorite. READ TABLE ms_user-favorites TRANSPORTING NO FIELDS WITH KEY table_line = iv_repo_key. IF sy-subrc = 0. DELETE ms_user-favorites INDEX sy-tabix. ELSE. APPEND iv_repo_key TO ms_user-favorites. ENDIF. update( ). ENDMETHOD. METHOD zif_abapgit_persist_user~toggle_hide_files. ms_user-hide_files = boolc( ms_user-hide_files = abap_false ). update( ). rv_hide = ms_user-hide_files. ENDMETHOD. METHOD zif_abapgit_persist_user~toggle_show_folders. ms_user-show_folders = boolc( ms_user-show_folders = abap_false ). update( ). rv_folders = ms_user-show_folders. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_persistence_repo IMPLEMENTATION. METHOD constructor. DATA ls_dummy_meta_mask TYPE zif_abapgit_persistence=>ty_repo_meta_mask. DATA ls_dummy_meta TYPE zif_abapgit_persistence=>ty_repo_xml. DATA lo_type_meta_mask TYPE REF TO cl_abap_structdescr. DATA lo_type_meta TYPE REF TO cl_abap_structdescr. FIELD-SYMBOLS LIKE LINE OF lo_type_meta_mask->components. " Collect actual list of fields in repo meta data (used in update_meta) lo_type_meta_mask ?= cl_abap_structdescr=>describe_by_data( ls_dummy_meta_mask ). lo_type_meta ?= cl_abap_structdescr=>describe_by_data( ls_dummy_meta ). LOOP AT lo_type_meta_mask->components ASSIGNING . APPEND -name TO mt_meta_fields. ENDLOOP. mo_db = zcl_abapgit_persistence_db=>get_instance( ). ENDMETHOD. METHOD from_xml. DATA: lv_xml TYPE string. lv_xml = iv_repo_xml_string. * fix downward compatibility REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_REPO_--29>' IN lv_xml WITH ''. REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. CALL TRANSFORMATION id OPTIONS value_handling = 'accept_data_loss' SOURCE XML lv_xml RESULT repo = rs_repo. * automatic migration of old fields * todo, keep for transition period until 2022-12-31, then remove all of these FIND FIRST OCCURRENCE OF 'X' IN lv_xml. IF sy-subrc = 0. rs_repo-local_settings-write_protected = abap_true. ENDIF. FIND FIRST OCCURRENCE OF 'X' IN lv_xml. IF sy-subrc = 0. rs_repo-local_settings-ignore_subpackages = abap_true. ENDIF. FIND FIRST OCCURRENCE OF 'X' IN lv_xml. IF sy-subrc = 0. rs_repo-local_settings-main_language_only = abap_true. ENDIF. IF rs_repo IS INITIAL. zcx_abapgit_exception=>raise( 'Inconsistent repo metadata' ). ENDIF. ENDMETHOD. METHOD get_next_id. * todo: Lock the complete persistence in order to prevent concurrent repo-creation * however the current approach will most likely work in almost all cases DATA: lt_content TYPE zif_abapgit_persistence=>ty_contents. FIELD-SYMBOLS: LIKE LINE OF lt_content. rv_next_repo_id = 1. lt_content = mo_db->list_by_type( zcl_abapgit_persistence_db=>c_type_repo ). LOOP AT lt_content ASSIGNING . IF -value >= rv_next_repo_id. rv_next_repo_id = -value + 1. ENDIF. ENDLOOP. SHIFT rv_next_repo_id RIGHT DELETING TRAILING space. TRANSLATE rv_next_repo_id USING ' 0'. ENDMETHOD. METHOD get_repo_from_content. MOVE-CORRESPONDING from_xml( is_content-data_str ) TO rs_result. IF rs_result-local_settings-write_protected = abap_false AND zcl_abapgit_factory=>get_environment( )->is_repo_object_changes_allowed( ) = abap_false. rs_result-local_settings-write_protected = abap_true. ENDIF. rs_result-key = is_content-value. ENDMETHOD. METHOD rewrite_repo_meta. DATA lv_old_blob TYPE string. DATA lv_new_blob TYPE string. DATA ls_repo_meta TYPE zif_abapgit_persistence=>ty_repo. lv_old_blob = mo_db->read( iv_type = zcl_abapgit_persistence_db=>c_type_repo iv_value = iv_repo_key ). MOVE-CORRESPONDING from_xml( lv_old_blob ) TO ls_repo_meta. lv_new_blob = to_xml( ls_repo_meta ). IF lv_new_blob <> lv_old_blob. mo_db->update( iv_type = zcl_abapgit_persistence_db=>c_type_repo iv_value = iv_repo_key iv_data = lv_new_blob ). COMMIT WORK. ENDIF. ENDMETHOD. METHOD to_xml. DATA: ls_xml TYPE zif_abapgit_persistence=>ty_repo_xml. MOVE-CORRESPONDING is_repo TO ls_xml. CALL TRANSFORMATION id SOURCE repo = ls_xml RESULT XML rv_repo_xml_string. ENDMETHOD. METHOD zif_abapgit_persist_repo_cs~delete. mo_db->delete( iv_type = zcl_abapgit_persistence_db=>c_type_repo_csum iv_value = iv_key ). ENDMETHOD. METHOD zif_abapgit_persist_repo_cs~read. rv_cs_blob = mo_db->read( iv_type = zcl_abapgit_persistence_db=>c_type_repo_csum iv_value = iv_key ). ENDMETHOD. METHOD zif_abapgit_persist_repo_cs~update. mo_db->modify( iv_type = zcl_abapgit_persistence_db=>c_type_repo_csum iv_value = iv_key iv_data = iv_cs_blob ). ENDMETHOD. METHOD zif_abapgit_persist_repo~add. DATA: ls_repo TYPE zif_abapgit_persistence=>ty_repo, lv_repo_as_xml TYPE string. ls_repo-url = iv_url. ls_repo-branch_name = iv_branch_name. ls_repo-package = iv_package. ls_repo-offline = iv_offline. ls_repo-created_by = sy-uname. GET TIME STAMP FIELD ls_repo-created_at. ls_repo-dot_abapgit = is_dot_abapgit. ls_repo-local_settings-display_name = iv_display_name. lv_repo_as_xml = to_xml( ls_repo ). rv_key = get_next_id( ). mo_db->add( iv_type = zcl_abapgit_persistence_db=>c_type_repo iv_value = rv_key iv_data = lv_repo_as_xml ). ENDMETHOD. METHOD zif_abapgit_persist_repo~delete. DATA: lo_background TYPE REF TO zcl_abapgit_persist_background. CREATE OBJECT lo_background. lo_background->delete( iv_key ). mo_db->delete( iv_type = zcl_abapgit_persistence_db=>c_type_repo iv_value = iv_key ). ENDMETHOD. METHOD zif_abapgit_persist_repo~exists. DATA lt_keys TYPE zif_abapgit_persistence=>ty_repo_keys. DATA lt_content TYPE zif_abapgit_persistence=>ty_contents. APPEND iv_key TO lt_keys. lt_content = mo_db->list_by_keys( it_keys = lt_keys iv_type = zcl_abapgit_persistence_db=>c_type_repo ). rv_yes = boolc( lines( lt_content ) > 0 ). ENDMETHOD. METHOD zif_abapgit_persist_repo~list. DATA: lt_content TYPE zif_abapgit_persistence=>ty_contents, ls_content LIKE LINE OF lt_content, ls_repo LIKE LINE OF rt_repos. lt_content = mo_db->list_by_type( zcl_abapgit_persistence_db=>c_type_repo ). LOOP AT lt_content INTO ls_content. ls_repo = get_repo_from_content( ls_content ). INSERT ls_repo INTO TABLE rt_repos. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_persist_repo~list_by_keys. DATA: lt_content TYPE zif_abapgit_persistence=>ty_contents, ls_content LIKE LINE OF lt_content, ls_repo LIKE LINE OF rt_repos. lt_content = mo_db->list_by_keys( it_keys = it_keys iv_type = zcl_abapgit_persistence_db=>c_type_repo ). LOOP AT lt_content INTO ls_content. ls_repo = get_repo_from_content( ls_content ). INSERT ls_repo INTO TABLE rt_repos. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_persist_repo~lock. mo_db->lock( iv_mode = iv_mode iv_type = zcl_abapgit_persistence_db=>c_type_repo iv_value = iv_key ). ENDMETHOD. METHOD zif_abapgit_persist_repo~read. DATA lt_repo TYPE zif_abapgit_persistence=>ty_repos. lt_repo = zif_abapgit_persist_repo~list( ). READ TABLE lt_repo INTO rs_repo WITH KEY key = iv_key. IF sy-subrc <> 0. RAISE EXCEPTION TYPE zcx_abapgit_not_found. ENDIF. ENDMETHOD. METHOD zif_abapgit_persist_repo~update_metadata. DATA: lv_blob TYPE zif_abapgit_persistence=>ty_content-data_str, ls_persistent_meta TYPE zif_abapgit_persistence=>ty_repo. FIELD-SYMBOLS LIKE LINE OF mt_meta_fields. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE abap_bool. ASSERT NOT iv_key IS INITIAL. IF is_change_mask IS INITIAL. RETURN. ENDIF. " Validations IF is_change_mask-url = abap_true AND is_meta-url IS INITIAL. zcx_abapgit_exception=>raise( 'update, url empty' ). ENDIF. ls_persistent_meta = zcl_abapgit_repo_srv=>get_instance( )->get( iv_key )->ms_data. " Update LOOP AT mt_meta_fields ASSIGNING . ASSIGN COMPONENT OF STRUCTURE is_change_mask TO . ASSERT sy-subrc = 0. CHECK = abap_true. ASSIGN COMPONENT OF STRUCTURE ls_persistent_meta TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT OF STRUCTURE is_meta TO . ASSERT sy-subrc = 0. = . ENDLOOP. lv_blob = to_xml( ls_persistent_meta ). mo_db->update( iv_type = zcl_abapgit_persistence_db=>c_type_repo iv_value = iv_key iv_data = lv_blob ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_PERSISTENCE_DB IMPLEMENTATION. METHOD add. DATA ls_table TYPE zif_abapgit_persistence=>ty_content. validate_entry_type( iv_type ). ls_table-type = iv_type. ls_table-value = iv_value. ls_table-data_str = iv_data. INSERT (c_tabname) FROM ls_table. "#EC CI_SUBRC ASSERT sy-subrc = 0. ENDMETHOD. METHOD delete. lock( iv_type = iv_type iv_value = iv_value ). " Ignore errors since record might not exist DELETE FROM (c_tabname) WHERE type = iv_type AND value = iv_value. ENDMETHOD. METHOD get_instance. IF go_db IS NOT BOUND. CREATE OBJECT go_db. ENDIF. ro_db = go_db. ENDMETHOD. METHOD get_update_function. IF mv_update_function IS INITIAL. mv_update_function = 'CALL_V1_PING'. IF zcl_abapgit_factory=>get_function_module( )->function_exists( mv_update_function ) = abap_false. mv_update_function = 'BANK_OBJ_WORKL_RELEASE_LOCKS'. ENDIF. ENDIF. rv_funcname = mv_update_function. ENDMETHOD. METHOD list. SELECT * FROM (c_tabname) INTO TABLE rt_content. "#EC CI_SUBRC ENDMETHOD. METHOD list_by_keys. FIELD-SYMBOLS: LIKE LINE OF it_keys. LOOP AT it_keys ASSIGNING . SELECT * FROM (c_tabname) APPENDING TABLE rt_contents WHERE value = AND type = iv_type. ENDLOOP. ENDMETHOD. METHOD list_by_type. SELECT * FROM (c_tabname) INTO TABLE rt_content WHERE type = iv_type ORDER BY PRIMARY KEY. "#EC CI_SUBRC ENDMETHOD. METHOD lock. DATA: lv_dummy_update_function TYPE funcname. CALL FUNCTION 'ENQUEUE_EZABAPGIT' EXPORTING mode_zabapgit = iv_mode type = iv_type value = iv_value EXCEPTIONS foreign_lock = 1 system_failure = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. lv_dummy_update_function = get_update_function( ). * trigger dummy update task to automatically release locks at commit CALL FUNCTION lv_dummy_update_function IN UPDATE TASK. ENDMETHOD. METHOD modify. DATA: ls_content TYPE zif_abapgit_persistence=>ty_content. lock( iv_type = iv_type iv_value = iv_value ). ls_content-type = iv_type. ls_content-value = iv_value. ls_content-data_str = iv_data. MODIFY (c_tabname) FROM ls_content. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'DB modify failed' ). ENDIF. ENDMETHOD. METHOD read. SELECT SINGLE data_str FROM (c_tabname) INTO rv_data WHERE type = iv_type AND value = iv_value. IF sy-subrc <> 0. RAISE EXCEPTION TYPE zcx_abapgit_not_found. ENDIF. ENDMETHOD. METHOD update. DATA lv_data LIKE iv_data. IF iv_data CS ' 0. zcx_abapgit_exception=>raise( 'DB update failed' ). ENDIF. ENDMETHOD. METHOD validate_and_unprettify_xml. rv_xml = zcl_abapgit_xml_pretty=>print( iv_xml = iv_xml iv_unpretty = abap_true iv_ignore_errors = abap_false ). ENDMETHOD. METHOD validate_entry_type. IF NOT ( iv_type = c_type_repo OR iv_type = c_type_repo_csum OR iv_type = c_type_user OR iv_type = c_type_settings OR iv_type = c_type_background OR iv_type = c_type_packages ). zcx_abapgit_exception=>raise( |Invalid DB entry type [{ iv_type }]| ). ENDIF. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_PERSIST_SETTINGS IMPLEMENTATION. METHOD zif_abapgit_persist_settings~modify. DATA: lv_settings TYPE string, ls_user_settings TYPE zif_abapgit_definitions=>ty_s_user_settings. lv_settings = io_settings->get_settings_xml( ). zcl_abapgit_persistence_db=>get_instance( )->modify( iv_type = zcl_abapgit_persistence_db=>c_type_settings iv_value = '' iv_data = lv_settings ). ls_user_settings = io_settings->get_user_settings( ). zcl_abapgit_persistence_user=>get_instance( )->set_settings( ls_user_settings ). " Settings have been modified: Update Buffered Settings IF mo_settings IS BOUND. mo_settings->set_xml_settings( lv_settings ). mo_settings->set_user_settings( ls_user_settings ). ENDIF. ENDMETHOD. METHOD zif_abapgit_persist_settings~read. IF mo_settings IS BOUND. " Return Buffered Settings ro_settings = mo_settings. RETURN. ENDIF. " Settings have changed or have not yet been loaded CREATE OBJECT ro_settings. TRY. ro_settings->set_xml_settings( zcl_abapgit_persistence_db=>get_instance( )->read( iv_type = zcl_abapgit_persistence_db=>c_type_settings iv_value = '' ) ). ro_settings->set_user_settings( zcl_abapgit_persistence_user=>get_instance( )->get_settings( ) ). CATCH zcx_abapgit_not_found zcx_abapgit_exception. ro_settings->set_defaults( ). ENDTRY. mo_settings = ro_settings. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_persist_packages IMPLEMENTATION. METHOD from_xml. DATA lo_input TYPE REF TO zif_abapgit_xml_input. CREATE OBJECT lo_input TYPE zcl_abapgit_xml_input EXPORTING iv_xml = iv_xml. lo_input->read( EXPORTING iv_name = zcl_abapgit_persistence_db=>c_type_packages CHANGING cg_data = rt_packages ). ENDMETHOD. METHOD get_instance. IF go_persist IS NOT BOUND. CREATE OBJECT go_persist. ENDIF. ro_persist = go_persist. ENDMETHOD. METHOD init. TRY. " Might have changed in another session so always get latest mt_packages = from_xml( zcl_abapgit_persistence_db=>get_instance( )->read( iv_type = zcl_abapgit_persistence_db=>c_type_packages iv_value = '' ) ). CATCH zcx_abapgit_exception zcx_abapgit_not_found ##NO_HANDLER. ENDTRY. ENDMETHOD. METHOD modify. DATA ls_package LIKE LINE OF mt_packages. FIELD-SYMBOLS LIKE LINE OF mt_packages. init( ). IF iv_component IS INITIAL AND iv_comp_posid IS INITIAL. DELETE mt_packages WHERE devclass = iv_package. ELSE. READ TABLE mt_packages ASSIGNING WITH TABLE KEY devclass = iv_package. IF sy-subrc = 0. -component = iv_component. -comp_posid = iv_comp_posid. ELSE. ls_package-devclass = iv_package. ls_package-component = iv_component. ls_package-comp_posid = iv_comp_posid. INSERT ls_package INTO TABLE mt_packages. ENDIF. ENDIF. zcl_abapgit_persistence_db=>get_instance( )->modify( iv_type = zcl_abapgit_persistence_db=>c_type_packages iv_value = '' iv_data = to_xml( mt_packages ) ). COMMIT WORK AND WAIT. ENDMETHOD. METHOD read. init( ). READ TABLE mt_packages INTO rs_package WITH TABLE KEY devclass = iv_package. IF sy-subrc <> 0. rs_package-devclass = iv_package. " no component ENDIF. ENDMETHOD. METHOD to_xml. DATA li_output TYPE REF TO zif_abapgit_xml_output. CREATE OBJECT li_output TYPE zcl_abapgit_xml_output. li_output->add( iv_name = zcl_abapgit_persistence_db=>c_type_packages ig_data = it_packages ). rv_xml = li_output->render( ). ENDMETHOD. ENDCLASS. CLASS kHGwlIgZqNOMnmtzWUhGXxcERFBDQR DEFINITION DEFERRED. CLASS kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ DEFINITION DEFERRED. * renamed: zcl_abapgit_persist_migrate :: lcl_cua_interface CLASS kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ DEFINITION INHERITING FROM zcl_abapgit_objects_program FINAL. PUBLIC SECTION. CLASS-METHODS new RETURNING VALUE(ro_instance) TYPE REF TO kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ. METHODS get_own_cua RETURNING VALUE(rs_cua) TYPE ty_cua RAISING zcx_abapgit_exception. METHODS put_own_cua IMPORTING is_cua TYPE ty_cua RAISING zcx_abapgit_exception. ENDCLASS. CLASS kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ IMPLEMENTATION. METHOD new. DATA ls_item TYPE zif_abapgit_definitions=>ty_item. SELECT SINGLE devclass object obj_name INTO (ls_item-devclass, ls_item-obj_type, ls_item-obj_name) FROM tadir WHERE pgmid = 'R3TR' AND object = 'PROG' AND obj_name = sy-cprog. CREATE OBJECT ro_instance EXPORTING iv_language = 'E' is_item = ls_item. ENDMETHOD. METHOD get_own_cua. rs_cua = serialize_cua( sy-cprog ). ENDMETHOD. METHOD put_own_cua. DATA li_log TYPE REF TO zif_abapgit_log. deserialize_cua( is_cua = is_cua iv_program_name = ms_item-obj_name ). CREATE OBJECT li_log TYPE zcl_abapgit_log. zcl_abapgit_objects_activation=>activate( li_log ). zcl_abapgit_objects_activation=>clear( ). ENDMETHOD. ENDCLASS. * renamed: zcl_abapgit_persist_migrate :: lcl_own_cua_provider CLASS kHGwlIgZqNOMnmtzWUhGXxcERFBDQR DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS get RETURNING VALUE(rs_cua) TYPE zcl_abapgit_objects_program=>ty_cua ##NEEDED. ENDCLASS. CLASS kHGwlIgZqNOMnmtzWUhGXxcERFBDQR IMPLEMENTATION. METHOD get. **************************************************** * abapmerge Pragma [include-cua] - ZABAPGIT.PROG.XML **************************************************** DATA ls_sta LIKE LINE OF rs_cua-sta. DATA ls_fun LIKE LINE OF rs_cua-fun. DATA ls_but LIKE LINE OF rs_cua-but. DATA ls_pfk LIKE LINE OF rs_cua-pfk. DATA ls_set LIKE LINE OF rs_cua-set. DATA ls_doc LIKE LINE OF rs_cua-doc. rs_cua-adm-pfkcode = '000001'. CLEAR ls_sta. ls_sta-code = 'DECIDE_DIALOG'. ls_sta-modal = 'P'. ls_sta-pfkcode = '000001'. ls_sta-butcode = '0001'. ls_sta-int_note = 'Object list decide dialog toolbar'. APPEND ls_sta TO rs_cua-sta. CLEAR ls_fun. ls_fun-code = '&ILD'. ls_fun-textno = '001'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_FILTER_UNDO'. ls_fun-icon_id = '@GD@'. ls_fun-fun_text = 'Reset filter'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_fun. ls_fun-code = '&ILT'. ls_fun-textno = '001'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_FILTER'. ls_fun-icon_id = '@4G@'. ls_fun-fun_text = 'Set Filter'. ls_fun-path = 'F'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_fun. ls_fun-code = '&ODN'. ls_fun-textno = '001'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_SORT_DOWN'. ls_fun-icon_id = '@3F@'. ls_fun-fun_text = 'Sort in Descending Order'. ls_fun-path = 'O'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_fun. ls_fun-code = '&OUP'. ls_fun-textno = '001'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_SORT_UP'. ls_fun-icon_id = '@3E@'. ls_fun-fun_text = 'Sort in Ascending Order'. ls_fun-path = 'I'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_fun. ls_fun-code = 'CANCEL'. ls_fun-textno = '001'. ls_fun-type = 'E'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_CANCEL'. ls_fun-icon_id = '@0W@'. ls_fun-fun_text = 'Cancel'. ls_fun-icon_text = 'Cancel'. ls_fun-path = 'A'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_fun. ls_fun-code = 'OK'. ls_fun-textno = '001'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_OKAY'. ls_fun-icon_id = '@0V@'. ls_fun-fun_text = 'Continue'. ls_fun-icon_text = 'Continue'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_fun. ls_fun-code = 'SEL_ALL'. ls_fun-textno = '001'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_SELECT_ALL'. ls_fun-icon_id = '@4B@'. ls_fun-fun_text = 'Select All Visible'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_fun. ls_fun-code = 'SEL_CAT'. ls_fun-textno = '001'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_WD_TOOLBAR'. ls_fun-icon_id = '@TF@'. ls_fun-fun_text = 'Select category'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_fun. ls_fun-code = 'SEL_DEL'. ls_fun-textno = '001'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_DESELECT_ALL'. ls_fun-icon_id = '@4D@'. ls_fun-fun_text = 'Deselect All Visible'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_fun. ls_fun-code = 'SEL_KEY'. ls_fun-textno = '001'. ls_fun-text_type = 'S'. ls_fun-text_name = 'ICON_SELECT_BLOCK'. ls_fun-icon_id = '@4C@'. ls_fun-fun_text = 'Mark/Toggle Selected'. APPEND ls_fun TO rs_cua-fun. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '01'. ls_but-pfno = '00'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '02'. ls_but-pfno = 'S'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '03'. ls_but-pfno = '13'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '04'. ls_but-pfno = '17'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '05'. ls_but-pfno = '14'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '06'. ls_but-pfno = '16'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '07'. ls_but-pfno = 'S'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '08'. ls_but-pfno = '05'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '09'. ls_but-pfno = '06'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '10'. ls_but-pfno = '07'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '11'. ls_but-pfno = '08'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '12'. ls_but-pfno = 'S'. APPEND ls_but TO rs_cua-but. CLEAR ls_but. ls_but-pfk_code = '000001'. ls_but-code = '0001'. ls_but-no = '13'. ls_but-pfno = '12'. APPEND ls_but TO rs_cua-but. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '00'. ls_pfk-funcode = 'OK'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '05'. ls_pfk-funcode = 'SEL_ALL'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '06'. ls_pfk-funcode = 'SEL_DEL'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '07'. ls_pfk-funcode = 'SEL_KEY'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '08'. ls_pfk-funcode = 'SEL_CAT'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '11'. ls_pfk-funcode = 'OK'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '12'. ls_pfk-funcode = 'CANCEL'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '13'. ls_pfk-funcode = '&ILT'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '14'. ls_pfk-funcode = '&OUP'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '16'. ls_pfk-funcode = '&ODN'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_pfk. ls_pfk-code = '000001'. ls_pfk-pfno = '17'. ls_pfk-funcode = '&ILD'. ls_pfk-funno = '001'. APPEND ls_pfk TO rs_cua-pfk. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = '&ILD'. APPEND ls_set TO rs_cua-set. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = '&ILT'. APPEND ls_set TO rs_cua-set. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = '&ODN'. APPEND ls_set TO rs_cua-set. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = '&OUP'. APPEND ls_set TO rs_cua-set. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = 'CANCEL'. APPEND ls_set TO rs_cua-set. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = 'OK'. APPEND ls_set TO rs_cua-set. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = 'SEL_ALL'. APPEND ls_set TO rs_cua-set. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = 'SEL_CAT'. APPEND ls_set TO rs_cua-set. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = 'SEL_DEL'. APPEND ls_set TO rs_cua-set. CLEAR ls_set. ls_set-status = 'DECIDE_DIALOG'. ls_set-function = 'SEL_KEY'. APPEND ls_set TO rs_cua-set. CLEAR ls_doc. ls_doc-obj_type = 'P'. ls_doc-obj_code = '000001'. ls_doc-modal = 'P'. ls_doc-int_note = 'Object list decide dialog FK settings'. APPEND ls_doc TO rs_cua-doc. CLEAR ls_doc. ls_doc-obj_type = 'B'. ls_doc-obj_code = '000001'. ls_doc-sub_code = '0001'. ls_doc-modal = 'P'. ls_doc-int_note = 'Object list decide dialog PB settings'. APPEND ls_doc TO rs_cua-doc. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_persist_migrate IMPLEMENTATION. METHOD gui_status_create. DATA ls_cua TYPE zcl_abapgit_objects_program=>ty_cua. IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. RETURN. " No autocreation for full version ENDIF. IF gui_status_exists( ) = abap_true. RETURN. ENDIF. ls_cua = kHGwlIgZqNOMnmtzWUhGXxcERFBDQR=>get( ). IF ls_cua IS INITIAL. " Full version or something wrong with abapmerged version RETURN. ENDIF. TRY. kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ=>new( )->put_own_cua( ls_cua ). CATCH zcx_abapgit_exception. ENDTRY. ENDMETHOD. METHOD gui_status_exists. DATA ls_own_cua TYPE zcl_abapgit_objects_program=>ty_cua. DATA ls_new_cua TYPE zcl_abapgit_objects_program=>ty_cua. DATA lv_x_own TYPE xstring. DATA lv_x_new TYPE xstring. DATA lv_h_own TYPE zif_abapgit_git_definitions=>ty_sha1. DATA lv_h_new TYPE zif_abapgit_git_definitions=>ty_sha1. TRY. ls_own_cua = kHGwlIgZqNOMnmtzWUhGRLwWSccCqJ=>new( )->get_own_cua( ). CATCH zcx_abapgit_exception. ENDTRY. IF ls_own_cua IS INITIAL. rv_exists = abap_false. RETURN. ENDIF. ls_new_cua = kHGwlIgZqNOMnmtzWUhGXxcERFBDQR=>get( ). IF ls_new_cua IS INITIAL. rv_exists = abap_true. " own exists and new is not - nothing to compare with RETURN. ENDIF. EXPORT data = ls_own_cua TO DATA BUFFER lv_x_own. EXPORT data = ls_new_cua TO DATA BUFFER lv_x_new. TRY. lv_h_own = zcl_abapgit_hash=>sha1_raw( lv_x_own ). lv_h_new = zcl_abapgit_hash=>sha1_raw( lv_x_new ). CATCH zcx_abapgit_exception. rv_exists = abap_true. " own exists and some issue with calculating hash ... assume own is OK RETURN. ENDTRY. " New exists and differs from own - then it is really new, needs to be installed rv_exists = boolc( lv_h_own = lv_h_new ). ENDMETHOD. METHOD lock_create. DATA: lv_obj_name TYPE tadir-obj_name, ls_dd25v TYPE dd25v, lt_dd26e TYPE STANDARD TABLE OF dd26e WITH DEFAULT KEY, lt_dd27p TYPE STANDARD TABLE OF dd27p WITH DEFAULT KEY. FIELD-SYMBOLS: LIKE LINE OF lt_dd26e, LIKE LINE OF lt_dd27p. ls_dd25v-viewname = zcl_abapgit_persistence_db=>c_lock. ls_dd25v-aggtype = 'E'. ls_dd25v-roottab = zcl_abapgit_persistence_db=>c_tabname. ls_dd25v-ddlanguage = zif_abapgit_definitions=>c_english. ls_dd25v-ddtext = c_text. APPEND INITIAL LINE TO lt_dd26e ASSIGNING . -viewname = zcl_abapgit_persistence_db=>c_lock. -tabname = zcl_abapgit_persistence_db=>c_tabname. -tabpos = '0001'. -fortabname = zcl_abapgit_persistence_db=>c_tabname. -enqmode = 'E'. APPEND INITIAL LINE TO lt_dd27p ASSIGNING . -viewname = zcl_abapgit_persistence_db=>c_lock. -objpos = '0001'. -viewfield = 'TYPE'. -tabname = zcl_abapgit_persistence_db=>c_tabname. -fieldname = 'TYPE'. -keyflag = abap_true. APPEND INITIAL LINE TO lt_dd27p ASSIGNING . -viewname = zcl_abapgit_persistence_db=>c_lock. -objpos = '0002'. -viewfield = 'VALUE'. -tabname = zcl_abapgit_persistence_db=>c_tabname. -fieldname = 'VALUE'. -keyflag = abap_true. CALL FUNCTION 'DDIF_ENQU_PUT' EXPORTING name = zcl_abapgit_persistence_db=>c_lock dd25v_wa = ls_dd25v TABLES dd26e_tab = lt_dd26e dd27p_tab = lt_dd27p EXCEPTIONS enqu_not_found = 1 name_inconsistent = 2 enqu_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. lv_obj_name = zcl_abapgit_persistence_db=>c_lock. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_tadir_pgmid = 'R3TR' wi_tadir_object = 'ENQU' wi_tadir_obj_name = lv_obj_name wi_set_genflag = abap_true wi_test_modus = abap_false wi_tadir_devclass = '$TMP' EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'DDIF_ENQU_ACTIVATE' EXPORTING name = zcl_abapgit_persistence_db=>c_lock EXCEPTIONS not_found = 1 put_failure = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'migrate, error from DDIF_ENQU_ACTIVATE' ). ENDIF. ENDMETHOD. METHOD lock_exists. DATA: lv_viewname TYPE dd25l-viewname. SELECT SINGLE viewname FROM dd25l INTO lv_viewname WHERE viewname = zcl_abapgit_persistence_db=>c_lock. rv_exists = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD run. IF table_exists( ) = abap_false. table_create( ). ENDIF. IF lock_exists( ) = abap_false. lock_create( ). ENDIF. gui_status_create( ). ENDMETHOD. METHOD table_create. DATA: lv_rc LIKE sy-subrc, lv_obj_name TYPE tadir-obj_name, ls_dd02v TYPE dd02v, ls_dd09l TYPE dd09l, lt_dd03p TYPE STANDARD TABLE OF dd03p WITH DEFAULT KEY. FIELD-SYMBOLS: LIKE LINE OF lt_dd03p. ls_dd02v-tabname = zcl_abapgit_persistence_db=>c_tabname. ls_dd02v-ddlanguage = zif_abapgit_definitions=>c_english. ls_dd02v-tabclass = 'TRANSP'. ls_dd02v-ddtext = c_text. ls_dd02v-contflag = 'L'. ls_dd02v-exclass = '1'. ls_dd09l-tabname = zcl_abapgit_persistence_db=>c_tabname. ls_dd09l-as4local = 'A'. ls_dd09l-tabkat = '1'. ls_dd09l-tabart = 'APPL1'. ls_dd09l-bufallow = 'N'. APPEND INITIAL LINE TO lt_dd03p ASSIGNING . -tabname = zcl_abapgit_persistence_db=>c_tabname. -fieldname = 'TYPE'. -position = '0001'. -keyflag = 'X'. -datatype = 'CHAR'. -leng = '000012'. APPEND INITIAL LINE TO lt_dd03p ASSIGNING . -tabname = zcl_abapgit_persistence_db=>c_tabname. -fieldname = 'VALUE'. -position = '0002'. -keyflag = 'X'. -datatype = 'CHAR'. -leng = '000012'. APPEND INITIAL LINE TO lt_dd03p ASSIGNING . -tabname = zcl_abapgit_persistence_db=>c_tabname. -fieldname = 'DATA_STR'. -position = '0003'. -datatype = 'STRG'. CALL FUNCTION 'DDIF_TABL_PUT' EXPORTING name = zcl_abapgit_persistence_db=>c_tabname dd02v_wa = ls_dd02v dd09l_wa = ls_dd09l TABLES dd03p_tab = lt_dd03p EXCEPTIONS tabl_not_found = 1 name_inconsistent = 2 tabl_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. lv_obj_name = zcl_abapgit_persistence_db=>c_tabname. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_tadir_pgmid = 'R3TR' wi_tadir_object = 'TABL' wi_tadir_obj_name = lv_obj_name wi_set_genflag = abap_true wi_test_modus = abap_false wi_tadir_devclass = '$TMP' EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'DDIF_TABL_ACTIVATE' EXPORTING name = zcl_abapgit_persistence_db=>c_tabname auth_chk = abap_false IMPORTING rc = lv_rc EXCEPTIONS not_found = 1 put_failure = 2 OTHERS = 3. IF sy-subrc <> 0 OR lv_rc <> 0. zcx_abapgit_exception=>raise( 'migrate, error from DDIF_TABL_ACTIVATE' ). ENDIF. ENDMETHOD. METHOD table_exists. DATA: lv_tabname TYPE dd02l-tabname. SELECT SINGLE tabname FROM dd02l INTO lv_tabname WHERE tabname = zcl_abapgit_persistence_db=>c_tabname. "#EC CI_NOORDER rv_exists = boolc( sy-subrc = 0 ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_PERSIST_FACTORY IMPLEMENTATION. METHOD get_repo. IF gi_repo IS INITIAL. CREATE OBJECT gi_repo TYPE zcl_abapgit_persistence_repo. ENDIF. ri_repo = gi_repo. ENDMETHOD. METHOD get_repo_cs. IF gi_repo_cs IS INITIAL. CREATE OBJECT gi_repo_cs TYPE zcl_abapgit_persistence_repo. ENDIF. ri_repo_cs = gi_repo_cs. ENDMETHOD. METHOD get_settings. IF gi_settings IS INITIAL. CREATE OBJECT gi_settings TYPE zcl_abapgit_persist_settings. ENDIF. ri_settings = gi_settings. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_PERSIST_BACKGROUND IMPLEMENTATION. METHOD constructor. mo_db = zcl_abapgit_persistence_db=>get_instance( ). ENDMETHOD. METHOD delete. TRY. mo_db->read( iv_type = zcl_abapgit_persistence_db=>c_type_background iv_value = iv_key ). CATCH zcx_abapgit_not_found. RETURN. ENDTRY. mo_db->delete( iv_type = zcl_abapgit_persistence_db=>c_type_background iv_value = iv_key ). ENDMETHOD. METHOD exists. TRY. mo_db->read( iv_type = zcl_abapgit_persistence_db=>c_type_background iv_value = iv_key ). rv_yes = abap_true. CATCH zcx_abapgit_not_found. rv_yes = abap_false. ENDTRY. ENDMETHOD. METHOD from_xml. CALL TRANSFORMATION id OPTIONS value_handling = 'accept_data_loss' SOURCE XML iv_string RESULT data = rs_xml. ENDMETHOD. METHOD get_by_key. DATA: lt_list TYPE ty_background_keys. lt_list = list( ). READ TABLE lt_list WITH KEY key = iv_key INTO rs_data. IF sy-subrc <> 0. RAISE EXCEPTION TYPE zcx_abapgit_not_found. ENDIF. ENDMETHOD. METHOD list. DATA: lt_list TYPE zif_abapgit_persistence=>ty_contents, ls_xml TYPE ty_xml. FIELD-SYMBOLS: LIKE LINE OF lt_list, LIKE LINE OF rt_list. lt_list = mo_db->list_by_type( zcl_abapgit_persistence_db=>c_type_background ). LOOP AT lt_list ASSIGNING . ls_xml = from_xml( -data_str ). APPEND INITIAL LINE TO rt_list ASSIGNING . MOVE-CORRESPONDING ls_xml TO . -key = -value. ENDLOOP. ENDMETHOD. METHOD modify. ASSERT NOT is_data-key IS INITIAL. mo_db->modify( iv_type = zcl_abapgit_persistence_db=>c_type_background iv_value = is_data-key iv_data = to_xml( is_data ) ). ENDMETHOD. METHOD to_xml. DATA: ls_xml TYPE ty_xml. MOVE-CORRESPONDING is_background TO ls_xml. CALL TRANSFORMATION id SOURCE data = ls_xml RESULT XML rv_string. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_migrations IMPLEMENTATION. METHOD migrate_offline_repos. DATA: lt_repos TYPE zif_abapgit_repo_srv=>ty_repo_list, li_repo LIKE LINE OF lt_repos, lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. TRY. " Get offline repos only lt_repos = zcl_abapgit_repo_srv=>get_instance( )->list( abap_true ). LOOP AT lt_repos INTO li_repo. lo_dot = li_repo->get_dot_abapgit( ). " Move repo name from URL fields to .abapGit.xml IF li_repo->ms_data-url IS NOT INITIAL AND lo_dot->get_name( ) IS INITIAL. lo_dot->set_name( li_repo->ms_data-url ). li_repo->set_dot_abapgit( lo_dot ). ENDIF. ENDLOOP. CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. ENDMETHOD. METHOD run. " Migrate STDTEXT to TABLE zcl_abapgit_persist_migrate=>run( ). " Create ZIF_APACK_MANIFEST interface zcl_abapgit_apack_migration=>run( ). " Migrate checksums from repo metadata to separate DB object zcl_abapgit_repo_cs_migration=>run( ). " Migrate offline repo metadata migrate_offline_repos( ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_objects_super IMPLEMENTATION. METHOD clear_abap_language_version. " Used during serializing of objects IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. " Ignore ABAP language version CLEAR cv_abap_language_version. ELSEIF ms_item-abap_language_version <> zcl_abapgit_abap_language_vers=>c_any_abap_language_version. " Check if ABAP language version matches repository setting zcl_abapgit_abap_language_vers=>check_abap_language_version( iv_abap_language_version = cv_abap_language_version is_item = ms_item ). ENDIF. ENDMETHOD. METHOD constructor. ms_item = is_item. ASSERT NOT ms_item IS INITIAL. mv_language = iv_language. ASSERT NOT mv_language IS INITIAL. IF io_files IS NOT INITIAL. mo_files = io_files. ELSE. mo_files = zcl_abapgit_objects_files=>new( is_item ). " New file collection ENDIF. IF io_i18n_params IS NOT INITIAL. mo_i18n_params = io_i18n_params. ELSE. mo_i18n_params = zcl_abapgit_i18n_params=>new( ). " All defaults ENDIF. ENDMETHOD. METHOD corr_insert. DATA: lv_object TYPE trobj_name, lv_object_class TYPE tadir-object. IF ig_object_class IS NOT INITIAL. lv_object_class = ig_object_class. IF ig_object_class = 'DICT'. CONCATENATE ms_item-obj_type ms_item-obj_name INTO lv_object. ELSE. lv_object = ms_item-obj_name. ENDIF. ELSE. lv_object_class = ms_item-obj_type. lv_object = ms_item-obj_name. ENDIF. zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( iv_object = lv_object_class iv_obj_name = lv_object iv_package = iv_package iv_language = mv_language ). ENDMETHOD. METHOD delete_ddic. DATA: lv_objname TYPE rsedd0-ddobjname, lv_objtype TYPE rsedd0-ddobjtype. lv_objname = ms_item-obj_name. lv_objtype = iv_objtype. TRY. CALL FUNCTION 'RS_DD_DELETE_OBJ' EXPORTING no_ask = iv_no_ask objname = lv_objname objtype = lv_objtype no_ask_delete_append = iv_no_ask_delete_append EXCEPTIONS not_executed = 1 object_not_found = 2 object_not_specified = 3 permission_failure = 4 dialog_needed = 5 OTHERS = 6. CATCH cx_sy_dyn_call_param_not_found. TRY. " try to force deletion for APPENDs CALL FUNCTION 'RS_DD_DELETE_OBJ' EXPORTING no_ask = iv_no_ask objname = lv_objname objtype = lv_objtype aie_force_deletion = iv_no_ask_delete_append EXCEPTIONS not_executed = 1 object_not_found = 2 object_not_specified = 3 permission_failure = 4 dialog_needed = 5 OTHERS = 6. CATCH cx_sy_dyn_call_param_not_found. " no_ask_delete_append and aie_force_deletion not available in lower releases CALL FUNCTION 'RS_DD_DELETE_OBJ' EXPORTING no_ask = iv_no_ask objname = lv_objname objtype = lv_objtype EXCEPTIONS not_executed = 1 object_not_found = 2 object_not_specified = 3 permission_failure = 4 dialog_needed = 5 OTHERS = 6. ENDTRY. ENDTRY. IF sy-subrc = 5. zcx_abapgit_exception=>raise( |Object { ms_item-obj_type } { ms_item-obj_name } has dependencies and must be deleted manually| ). ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error deleting { ms_item-obj_type } { ms_item-obj_name }| ). ENDIF. ENDMETHOD. METHOD delete_longtexts. zcl_abapgit_factory=>get_longtexts( )->delete( iv_longtext_id = iv_longtext_id iv_object_name = ms_item-obj_name ). ENDMETHOD. METHOD deserialize_longtexts. zcl_abapgit_factory=>get_longtexts( )->deserialize( ii_xml = ii_xml iv_longtext_name = iv_longtext_name iv_object_name = ms_item-obj_name iv_longtext_id = iv_longtext_id iv_main_language = mv_language ). ENDMETHOD. METHOD exists_a_lock_entry_for. DATA: lt_lock_entries TYPE STANDARD TABLE OF seqg3. DATA: lv_argument TYPE seqg3-garg. IF iv_prefix IS INITIAL. lv_argument = iv_argument. ELSE. lv_argument = |{ iv_prefix }{ iv_argument }|. OVERLAY lv_argument WITH ' '. lv_argument = lv_argument && '*'. ENDIF. CALL FUNCTION 'ENQUEUE_READ' EXPORTING guname = '*' garg = lv_argument TABLES enq = lt_lock_entries EXCEPTIONS communication_failure = 1 system_failure = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. READ TABLE lt_lock_entries TRANSPORTING NO FIELDS WITH KEY gobj = iv_lock_object. IF sy-subrc = 0. rv_exists_a_lock_entry = abap_true. ENDIF. ENDMETHOD. METHOD get_accessed_files. rt_files = mo_files->get_accessed_files( ). ENDMETHOD. METHOD get_metadata. DATA: lv_class TYPE string. lv_class = cl_abap_classdescr=>describe_by_object_ref( me )->get_relative_name( ). REPLACE FIRST OCCURRENCE OF 'ZCL_ABAPGIT' IN lv_class WITH 'LCL'. rs_metadata-class = lv_class. rs_metadata-version = 'v1.0.0'. ENDMETHOD. METHOD is_active. rv_active = zcl_abapgit_objects_activation=>is_active( ms_item ). ENDMETHOD. METHOD serialize_longtexts. zcl_abapgit_factory=>get_longtexts( )->serialize( iv_object_name = ms_item-obj_name iv_longtext_name = iv_longtext_name iv_longtext_id = iv_longtext_id it_dokil = it_dokil io_i18n_params = mo_i18n_params ii_xml = ii_xml ). ENDMETHOD. METHOD set_abap_language_version. " Used during deserializing of objects IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. " ABAP language version is derived from object type and target package (see zcl_abapgit_objects->deserialize) cv_abap_language_version = ms_item-abap_language_version. ELSEIF ms_item-abap_language_version <> zcl_abapgit_abap_language_vers=>c_any_abap_language_version. " Check if ABAP language version matches repository setting zcl_abapgit_abap_language_vers=>check_abap_language_version( iv_abap_language_version = cv_abap_language_version is_item = ms_item ). ENDIF. ENDMETHOD. METHOD set_default_package. " In certain cases we need to set the package via ABAP memory " because we can't supply it via the APIs. " " Set default package, see function module RS_CORR_INSERT FORM get_current_devclass. " " We use ABAP memory instead the SET parameter because it is " more reliable. SET parameter doesn't work when multiple objects " are deserialized which uses the ABAP memory mechanism. " We don't need to reset the memory as it is done in above mentioned form routine. EXPORT current_devclass FROM iv_package TO MEMORY ID 'EUK'. ENDMETHOD. METHOD set_default_transport. " In certain cases we need to set the transport via ABAP memory " because we can't supply it via the APIs. " " See function module RS_CORR_INSERT EXPORT tasknr FROM iv_transport TO MEMORY ID 'EUT'. ENDMETHOD. METHOD tadir_delete. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_tadir_pgmid = 'R3TR' wi_tadir_object = ms_item-obj_type wi_tadir_obj_name = ms_item-obj_name wi_test_modus = abap_false EXCEPTIONS tadir_entry_not_existing = 1 tadir_entry_ill_type = 2 no_systemname = 3 no_systemtype = 4 original_system_conflict = 5 object_reserved_for_devclass = 6 object_exists_global = 7 object_exists_local = 8 object_is_distributed = 9 obj_specification_not_unique = 10 no_authorization_to_delete = 11 devclass_not_existing = 12 simultanious_set_remove_repair = 13 order_missing = 14 no_modification_of_head_syst = 15 pgmid_object_not_allowed = 16 masterlanguage_not_specified = 17 devclass_not_specified = 18 specify_owner_unique = 19 loc_priv_objs_no_repair = 20 gtadir_not_reached = 21 object_locked_for_order = 22 change_of_class_not_allowed = 23 no_change_from_sap_to_tmp = 24 OTHERS = 25. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD tadir_insert. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_test_modus = abap_false wi_tadir_pgmid = 'R3TR' wi_tadir_object = ms_item-obj_type wi_tadir_obj_name = ms_item-obj_name wi_tadir_author = sy-uname wi_tadir_devclass = iv_package wi_tadir_masterlang = mv_language iv_delflag = abap_false EXCEPTIONS tadir_entry_not_existing = 1 tadir_entry_ill_type = 2 no_systemname = 3 no_systemtype = 4 original_system_conflict = 5 object_reserved_for_devclass = 6 object_exists_global = 7 object_exists_local = 8 object_is_distributed = 9 obj_specification_not_unique = 10 no_authorization_to_delete = 11 devclass_not_existing = 12 simultanious_set_remove_repair = 13 order_missing = 14 no_modification_of_head_syst = 15 pgmid_object_not_allowed = 16 masterlanguage_not_specified = 17 devclass_not_specified = 18 specify_owner_unique = 19 loc_priv_objs_no_repair = 20 gtadir_not_reached = 21 object_locked_for_order = 22 change_of_class_not_allowed = 23 no_change_from_sap_to_tmp = 24 OTHERS = 25. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_objects_program IMPLEMENTATION. METHOD add_tpool. FIELD-SYMBOLS: LIKE LINE OF it_tpool, LIKE LINE OF rt_tpool. LOOP AT it_tpool ASSIGNING . APPEND INITIAL LINE TO rt_tpool ASSIGNING . MOVE-CORRESPONDING TO . IF -id = 'S'. -split = -entry. -entry = -entry+8. ENDIF. ENDLOOP. ENDMETHOD. METHOD auto_correct_cua_adm. " issue #1807 automatic correction of CUA interfaces saved incorrectly in the past (ADM was not saved in the XML) CONSTANTS: lc_num_n_space TYPE string VALUE ' 0123456789', lc_num_only TYPE string VALUE '0123456789'. FIELD-SYMBOLS: TYPE rsmpe_pfk, TYPE rsmpe_act, TYPE rsmpe_men. IF cs_adm IS NOT INITIAL AND cs_adm-actcode CO lc_num_n_space AND cs_adm-mencode CO lc_num_n_space AND cs_adm-pfkcode CO lc_num_n_space. "Check performed in form check_adm of include LSMPIF03 RETURN. ENDIF. LOOP AT is_cua-act ASSIGNING . IF -code+6(14) IS INITIAL AND -code(6) CO lc_num_only. cs_adm-actcode = -code. ENDIF. ENDLOOP. LOOP AT is_cua-men ASSIGNING . IF -code+6(14) IS INITIAL AND -code(6) CO lc_num_only. cs_adm-mencode = -code. ENDIF. ENDLOOP. LOOP AT is_cua-pfk ASSIGNING . IF -code+6(14) IS INITIAL AND -code(6) CO lc_num_only. cs_adm-pfkcode = -code. ENDIF. ENDLOOP. ENDMETHOD. METHOD deserialize_cua. DATA: ls_tr_key TYPE trkey, ls_adm TYPE rsmpe_adm. IF lines( is_cua-sta ) = 0 AND lines( is_cua-fun ) = 0 AND lines( is_cua-men ) = 0 AND lines( is_cua-mtx ) = 0 AND lines( is_cua-act ) = 0 AND lines( is_cua-but ) = 0 AND lines( is_cua-pfk ) = 0 AND lines( is_cua-set ) = 0 AND lines( is_cua-doc ) = 0 AND lines( is_cua-tit ) = 0 AND lines( is_cua-biv ) = 0. RETURN. ENDIF. SELECT SINGLE devclass INTO ls_tr_key-devclass FROM tadir WHERE pgmid = 'R3TR' AND object = ms_item-obj_type AND obj_name = ms_item-obj_name. "#EC CI_GENBUFF IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'not found in tadir' ). ENDIF. ls_tr_key-obj_type = ms_item-obj_type. ls_tr_key-obj_name = ms_item-obj_name. ls_tr_key-sub_type = 'CUAD'. ls_tr_key-sub_name = iv_program_name. ls_adm = is_cua-adm. auto_correct_cua_adm( EXPORTING is_cua = is_cua CHANGING cs_adm = ls_adm ). sy-tcode = 'SE41' ##WRITE_OK. " evil hack, workaround to handle fixes in note 2159455 CALL FUNCTION 'RS_CUA_INTERNAL_WRITE' EXPORTING program = iv_program_name language = mv_language tr_key = ls_tr_key adm = ls_adm state = c_state-inactive TABLES sta = is_cua-sta fun = is_cua-fun men = is_cua-men mtx = is_cua-mtx act = is_cua-act but = is_cua-but pfk = is_cua-pfk set = is_cua-set doc = is_cua-doc tit = is_cua-tit biv = is_cua-biv EXCEPTIONS not_found = 1 OTHERS = 2. IF sy-subrc <> 0. * if moving code from SAPlink, see https://github.com/abapGit/abapGit/issues/562 zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_objects_activation=>add( iv_type = 'CUAD' iv_name = iv_program_name ). ENDMETHOD. METHOD deserialize_dynpros. CONSTANTS lc_rpyty_force_off TYPE c LENGTH 1 VALUE '/'. DATA: lv_name TYPE dwinactiv-obj_name, lt_d020s_to_delete TYPE TABLE OF d020s, ls_d020s LIKE LINE OF lt_d020s_to_delete, ls_dynpro LIKE LINE OF it_dynpros. FIELD-SYMBOLS: TYPE rpy_dyfatc. " Delete DYNPROs which are not in the list CALL FUNCTION 'RS_SCREEN_LIST' EXPORTING dynnr = '' progname = ms_item-obj_name TABLES dynpros = lt_d020s_to_delete EXCEPTIONS not_found = 1 OTHERS = 2. IF sy-subrc = 2. zcx_abapgit_exception=>raise_t100( ). ENDIF. SORT lt_d020s_to_delete BY dnum ASCENDING. * ls_dynpro is changed by the function module, a field-symbol will cause * the program to dump since it_dynpros cannot be changed LOOP AT it_dynpros INTO ls_dynpro. READ TABLE lt_d020s_to_delete WITH KEY dnum = ls_dynpro-header-screen TRANSPORTING NO FIELDS BINARY SEARCH. IF sy-subrc = 0. DELETE lt_d020s_to_delete INDEX sy-tabix. ENDIF. " todo: kept for compatibility, remove after grace period #3680 ls_dynpro-flow_logic = uncondense_flow( it_flow = ls_dynpro-flow_logic it_spaces = ls_dynpro-spaces ). LOOP AT ls_dynpro-fields ASSIGNING . * if the DDIC element has a PARAMETER_ID and the flag "from_dict" is active * the import will enable the SET-/GET_PARAM flag. In this case: "force off" IF -param_id IS NOT INITIAL AND -from_dict = abap_true. IF -set_param IS INITIAL. -set_param = lc_rpyty_force_off. ENDIF. IF -get_param IS INITIAL. -get_param = lc_rpyty_force_off. ENDIF. ENDIF. * If the previous conditions are met the value 'F' will be taken over * during de-serialization potentially overlapping other fields in the screen, * we set the tag to the correct value 'X' IF -type = 'CHECK' AND -from_dict = abap_true AND -text IS INITIAL AND -modific IS INITIAL. -modific = 'X'. ENDIF. "fix for issue #2747: IF -foreignkey IS INITIAL. -foreignkey = lc_rpyty_force_off. ENDIF. ENDLOOP. CALL FUNCTION 'RPY_DYNPRO_INSERT' EXPORTING header = ls_dynpro-header suppress_exist_checks = abap_true suppress_generate = ls_dynpro-header-no_execute TABLES containers = ls_dynpro-containers fields_to_containers = ls_dynpro-fields flow_logic = ls_dynpro-flow_logic EXCEPTIONS cancelled = 1 already_exists = 2 program_not_exists = 3 not_executed = 4 missing_required_field = 5 illegal_field_value = 6 field_not_allowed = 7 not_generated = 8 illegal_field_position = 9 OTHERS = 10. IF sy-subrc <> 2 AND sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. * todo, RPY_DYNPRO_UPDATE? CONCATENATE ls_dynpro-header-program ls_dynpro-header-screen INTO lv_name RESPECTING BLANKS. ASSERT NOT lv_name IS INITIAL. zcl_abapgit_objects_activation=>add( iv_type = 'DYNP' iv_name = lv_name ). ENDLOOP. " Delete obsolete screens LOOP AT lt_d020s_to_delete INTO ls_d020s. CALL FUNCTION 'RS_SCRP_DELETE' EXPORTING dynnr = ls_d020s-dnum progname = ms_item-obj_name with_popup = abap_false EXCEPTIONS enqueued_by_user = 1 enqueue_system_failure = 2 not_executed = 3 not_exists = 4 no_modify_permission = 5 popup_canceled = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD deserialize_program. DATA: lv_progname TYPE reposrc-progname, lv_title TYPE rglif-title. zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( iv_object = 'ABAP' iv_obj_name = is_progdir-name iv_package = iv_package iv_language = mv_language ). lv_title = get_program_title( it_tpool ). " Check if program already exists SELECT SINGLE progname FROM reposrc INTO lv_progname WHERE progname = is_progdir-name AND r3state = c_state-active. IF sy-subrc = 0. update_program( is_progdir = is_progdir it_source = it_source iv_title = lv_title ). ELSE. insert_program( is_progdir = is_progdir it_source = it_source iv_title = lv_title iv_package = iv_package ). ENDIF. zcl_abapgit_factory=>get_sap_report( )->update_progdir( is_progdir = is_progdir iv_package = iv_package ). zcl_abapgit_objects_activation=>add( iv_type = 'REPS' iv_name = is_progdir-name ). ENDMETHOD. METHOD deserialize_textpool. DATA lv_language TYPE sy-langu. DATA lv_state TYPE c. DATA lv_delete TYPE abap_bool. IF iv_language IS INITIAL. lv_language = mv_language. ELSE. lv_language = iv_language. ENDIF. IF lv_language = mv_language. lv_state = c_state-inactive. "Textpool in main language needs to be activated ELSE. lv_state = c_state-active. "Translations are always active ENDIF. IF it_tpool IS INITIAL. IF iv_is_include = abap_false OR lv_state = c_state-active. DELETE TEXTPOOL iv_program "Remove initial description from textpool if LANGUAGE lv_language "original program does not have a textpool STATE lv_state. lv_delete = abap_true. ELSE. INSERT TEXTPOOL iv_program "In case of includes: Deletion of textpool in FROM it_tpool "main language cannot be activated because LANGUAGE lv_language "this would activate the deletion of the textpool STATE lv_state. "of the mail program -> insert empty textpool ENDIF. ELSE. INSERT TEXTPOOL iv_program FROM it_tpool LANGUAGE lv_language STATE lv_state. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from INSERT TEXTPOOL' ). ENDIF. ENDIF. IF lv_state = c_state-inactive. "Textpool in main language needs to be activated zcl_abapgit_objects_activation=>add( iv_type = 'REPT' iv_name = iv_program iv_delete = lv_delete ). ENDIF. ENDMETHOD. METHOD get_program_title. DATA ls_tpool LIKE LINE OF it_tpool. FIELD-SYMBOLS TYPE any. READ TABLE it_tpool INTO ls_tpool WITH KEY id = 'R'. IF sy-subrc = 0. " there is a bug in RPY_PROGRAM_UPDATE, the header line of TTAB is not " cleared, so the title length might be inherited from a different program. ASSIGN ('(SAPLSIFP)TTAB') TO . IF sy-subrc = 0. CLEAR . ENDIF. rv_title = ls_tpool-entry. ENDIF. ENDMETHOD. METHOD insert_program. TRY. CALL FUNCTION 'RPY_PROGRAM_INSERT' EXPORTING development_class = iv_package program_name = is_progdir-name program_type = is_progdir-subc title_string = iv_title save_inactive = c_state-inactive suppress_dialog = abap_true uccheck = is_progdir-uccheck " does not exist on lower releases TABLES source_extended = it_source EXCEPTIONS already_exists = 1 cancelled = 2 name_not_allowed = 3 permission_error = 4 OTHERS = 5. CATCH cx_sy_dyn_call_param_not_found. CALL FUNCTION 'RPY_PROGRAM_INSERT' EXPORTING development_class = iv_package program_name = is_progdir-name program_type = is_progdir-subc title_string = iv_title save_inactive = c_state-inactive suppress_dialog = abap_true TABLES source_extended = it_source EXCEPTIONS already_exists = 1 cancelled = 2 name_not_allowed = 3 permission_error = 4 OTHERS = 5. ENDTRY. IF sy-subrc = 3. " For cases that standard function does not handle (like FUGR), " we save active and inactive version of source with the given PROGRAM TYPE. " Without the active version, the code will not be visible in case of activation errors. zcl_abapgit_factory=>get_sap_report( )->insert_report( iv_name = is_progdir-name iv_package = iv_package it_source = it_source iv_state = c_state-active iv_version = is_progdir-uccheck iv_program_type = is_progdir-subc ). zcl_abapgit_factory=>get_sap_report( )->insert_report( iv_name = is_progdir-name iv_package = iv_package it_source = it_source iv_state = c_state-inactive iv_version = is_progdir-uccheck iv_program_type = is_progdir-subc ). ELSEIF sy-subrc > 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD is_any_dynpro_locked. DATA: lt_dynpros TYPE ty_dynpro_tt, lv_object TYPE seqg3-garg. FIELD-SYMBOLS: TYPE ty_dynpro. lt_dynpros = serialize_dynpros( iv_program ). LOOP AT lt_dynpros ASSIGNING . lv_object = |{ -header-screen }{ -header-program }|. IF exists_a_lock_entry_for( iv_lock_object = 'ESCRP' iv_argument = lv_object ) = abap_true. rv_is_any_dynpro_locked = abap_true. EXIT. ENDIF. ENDLOOP. ENDMETHOD. METHOD is_cua_locked. DATA: lv_object TYPE eqegraarg. lv_object = |CU{ iv_program }|. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_cua_locked = exists_a_lock_entry_for( iv_lock_object = 'ESCUAPAINT' iv_argument = lv_object ). ENDMETHOD. METHOD is_text_locked. DATA: lv_object TYPE eqegraarg. lv_object = |*{ iv_program }|. rv_is_text_locked = exists_a_lock_entry_for( iv_lock_object = 'EABAPTEXTE' iv_argument = lv_object ). ENDMETHOD. METHOD read_tpool. FIELD-SYMBOLS: LIKE LINE OF it_tpool, LIKE LINE OF rt_tpool. LOOP AT it_tpool ASSIGNING . APPEND INITIAL LINE TO rt_tpool ASSIGNING . MOVE-CORRESPONDING TO . IF -id = 'S'. CONCATENATE -split -entry INTO -entry RESPECTING BLANKS. ENDIF. ENDLOOP. ENDMETHOD. METHOD serialize_cua. CALL FUNCTION 'RS_CUA_INTERNAL_FETCH' EXPORTING program = iv_program_name language = mv_language state = c_state-active IMPORTING adm = rs_cua-adm TABLES sta = rs_cua-sta fun = rs_cua-fun men = rs_cua-men mtx = rs_cua-mtx act = rs_cua-act but = rs_cua-but pfk = rs_cua-pfk set = rs_cua-set doc = rs_cua-doc tit = rs_cua-tit biv = rs_cua-biv EXCEPTIONS not_found = 1 unknown_version = 2 OTHERS = 3. IF sy-subrc > 1. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD serialize_dynpros. DATA: ls_header TYPE rpy_dyhead, lt_containers TYPE dycatt_tab, lt_fields_to_containers TYPE dyfatc_tab, lt_flow_logic TYPE swydyflow, lt_d020s TYPE TABLE OF d020s, lt_fieldlist_int TYPE TABLE OF d021s. "internal format FIELD-SYMBOLS: LIKE LINE OF lt_d020s, TYPE scrpostyle, LIKE LINE OF lt_containers, LIKE LINE OF lt_fields_to_containers, LIKE LINE OF rt_dynpro, LIKE LINE OF lt_fieldlist_int. "#2746: relevant flag values (taken from include MSEUSBIT) CONSTANTS: lc_flg1ddf TYPE x VALUE '20', lc_flg3fku TYPE x VALUE '08', lc_flg3for TYPE x VALUE '04', lc_flg3fdu TYPE x VALUE '02'. CALL FUNCTION 'RS_SCREEN_LIST' EXPORTING dynnr = '' progname = iv_program_name TABLES dynpros = lt_d020s EXCEPTIONS not_found = 1 OTHERS = 2. IF sy-subrc = 2. zcx_abapgit_exception=>raise_t100( ). ENDIF. SORT lt_d020s BY dnum ASCENDING. * loop dynpros and skip generated selection screens LOOP AT lt_d020s ASSIGNING WHERE type <> 'S' AND type <> 'W' AND type <> 'J' AND NOT dnum IS INITIAL. CALL FUNCTION 'RPY_DYNPRO_READ' EXPORTING progname = iv_program_name dynnr = -dnum IMPORTING header = ls_header TABLES containers = lt_containers fields_to_containers = lt_fields_to_containers flow_logic = lt_flow_logic EXCEPTIONS cancelled = 1 not_found = 2 permission_error = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. "#2746: we need the dynpro fields in internal format: FREE lt_fieldlist_int. CALL FUNCTION 'RPY_DYNPRO_READ_NATIVE' EXPORTING progname = iv_program_name dynnr = -dnum TABLES fieldlist = lt_fieldlist_int. LOOP AT lt_fields_to_containers ASSIGNING . * output style is a NUMC field, the XML conversion will fail if it contains invalid value * field does not exist in all versions ASSIGN COMPONENT 'OUTPUTSTYLE' OF STRUCTURE TO . IF sy-subrc = 0 AND = ' '. CLEAR . ENDIF. "2746: we apply the same logic as in SAPLWBSCREEN "for setting or unsetting the foreignkey field: UNASSIGN . READ TABLE lt_fieldlist_int ASSIGNING WITH KEY fnam = -name. IF IS ASSIGNED. IF -flg1 O lc_flg1ddf AND -flg3 O lc_flg3for AND -flg3 Z lc_flg3fdu AND -flg3 Z lc_flg3fku. -foreignkey = 'X'. ELSE. CLEAR -foreignkey. ENDIF. ENDIF. IF -from_dict = abap_true AND -modific <> 'F' AND -modific <> 'X'. CLEAR -text. ENDIF. ENDLOOP. LOOP AT lt_containers ASSIGNING . IF -c_resize_v = abap_false. CLEAR -c_line_min. ENDIF. IF -c_resize_h = abap_false. CLEAR -c_coln_min. ENDIF. ENDLOOP. APPEND INITIAL LINE TO rt_dynpro ASSIGNING . -header = ls_header. -containers = lt_containers. -fields = lt_fields_to_containers. -flow_logic = lt_flow_logic. ENDLOOP. ENDMETHOD. METHOD serialize_program. DATA: ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, lv_program_name TYPE syrepid, lt_dynpros TYPE ty_dynpro_tt, ls_cua TYPE ty_cua, li_report TYPE REF TO zif_abapgit_sap_report, lt_source TYPE TABLE OF abaptxt255, lt_tpool TYPE textpool_table, ls_tpool LIKE LINE OF lt_tpool, li_xml TYPE REF TO zif_abapgit_xml_output. IF iv_program IS INITIAL. lv_program_name = is_item-obj_name. ELSE. lv_program_name = iv_program. ENDIF. zcl_abapgit_language=>set_current_language( mv_language ). CALL FUNCTION 'RPY_PROGRAM_READ' EXPORTING program_name = lv_program_name with_includelist = abap_false with_lowercase = abap_true TABLES source_extended = lt_source textelements = lt_tpool EXCEPTIONS cancelled = 1 not_found = 2 permission_error = 3 OTHERS = 4. IF sy-subrc = 2. zcl_abapgit_language=>restore_login_language( ). RETURN. ELSEIF sy-subrc <> 0. zcl_abapgit_language=>restore_login_language( ). zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_language=>restore_login_language( ). " If inactive version exists, then RPY_PROGRAM_READ does not return the active code li_report = zcl_abapgit_factory=>get_sap_report( ). TRY. " Raises exception if inactive version does not exist ls_progdir = li_report->read_progdir( iv_name = lv_program_name iv_state = c_state-inactive ). " Explicitly request active source code lt_source = li_report->read_report( iv_name = lv_program_name iv_state = c_state-active ). CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. ls_progdir = li_report->read_progdir( iv_name = lv_program_name iv_state = c_state-active ). clear_abap_language_version( CHANGING cv_abap_language_version = ls_progdir-uccheck ). IF io_xml IS BOUND. li_xml = io_xml. ELSE. CREATE OBJECT li_xml TYPE zcl_abapgit_xml_output. ENDIF. li_xml->add( iv_name = 'PROGDIR' ig_data = ls_progdir ). IF ls_progdir-subc = '1' OR ls_progdir-subc = 'M'. lt_dynpros = serialize_dynpros( lv_program_name ). li_xml->add( iv_name = 'DYNPROS' ig_data = lt_dynpros ). ls_cua = serialize_cua( lv_program_name ). IF NOT ls_cua IS INITIAL. li_xml->add( iv_name = 'CUA' ig_data = ls_cua ). ENDIF. ENDIF. READ TABLE lt_tpool WITH KEY id = 'R' INTO ls_tpool. IF sy-subrc = 0 AND ls_tpool-key = '' AND ls_tpool-length = 0. DELETE lt_tpool INDEX sy-tabix. ENDIF. li_xml->add( iv_name = 'TPOOL' ig_data = add_tpool( lt_tpool ) ). IF NOT io_xml IS BOUND. io_files->add_xml( iv_extra = iv_extra ii_xml = li_xml ). ENDIF. strip_generation_comments( CHANGING ct_source = lt_source ). io_files->add_abap( iv_extra = iv_extra it_abap = lt_source ). ENDMETHOD. METHOD strip_generation_comments. FIELD-SYMBOLS TYPE any. " Assuming CHAR (e.g. abaptxt255_tab) or string (FUGR) IF ms_item-obj_type <> 'FUGR'. RETURN. ENDIF. " Case 1: MV FM main prog and TOPs READ TABLE ct_source INDEX 1 ASSIGNING . IF sy-subrc = 0 AND CP '#**regenerated at *'. DELETE ct_source INDEX 1. RETURN. ENDIF. " Case 2: MV FM includes IF lines( ct_source ) < 5. " Generation header length RETURN. ENDIF. READ TABLE ct_source INDEX 1 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#*---*'. RETURN. ENDIF. READ TABLE ct_source INDEX 2 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#**'. RETURN. ENDIF. READ TABLE ct_source INDEX 3 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#**generation date:*'. RETURN. ENDIF. READ TABLE ct_source INDEX 4 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#**generator version:*'. RETURN. ENDIF. READ TABLE ct_source INDEX 5 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#*---*'. RETURN. ENDIF. DELETE ct_source INDEX 4. DELETE ct_source INDEX 3. ENDMETHOD. METHOD uncondense_flow. DATA: lv_spaces LIKE LINE OF it_spaces. FIELD-SYMBOLS: LIKE LINE OF it_flow, LIKE LINE OF rt_flow. LOOP AT it_flow ASSIGNING . APPEND INITIAL LINE TO rt_flow ASSIGNING . -line = -line. READ TABLE it_spaces INDEX sy-tabix INTO lv_spaces. IF sy-subrc = 0. SHIFT -line RIGHT BY lv_spaces PLACES IN CHARACTER MODE. ENDIF. ENDLOOP. ENDMETHOD. METHOD update_program. zcl_abapgit_language=>set_current_language( mv_language ). CALL FUNCTION 'RPY_PROGRAM_UPDATE' EXPORTING program_name = is_progdir-name title_string = iv_title save_inactive = c_state-inactive TABLES source_extended = it_source EXCEPTIONS cancelled = 1 permission_error = 2 not_found = 3 OTHERS = 4. IF sy-subrc <> 0. zcl_abapgit_language=>restore_login_language( ). IF sy-msgid = 'EU' AND sy-msgno = '510'. zcx_abapgit_exception=>raise( 'User is currently editing program' ). ELSEIF sy-msgid = 'EU' AND sy-msgno = '522'. " for generated table maintenance function groups, the author is set to SAP* instead of the user which " generates the function group. This hits some standard checks, pulling new code again sets the author " to the current user which avoids the check zcx_abapgit_exception=>raise( |Delete function group and pull again, { is_progdir-name } (EU522)| ). ELSE. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. zcl_abapgit_language=>restore_login_language( ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_objects_generic IMPLEMENTATION. METHOD after_import. DATA: lt_cts_object_entry TYPE STANDARD TABLE OF e071 WITH DEFAULT KEY, ls_cts_object_entry LIKE LINE OF lt_cts_object_entry, lt_cts_key TYPE STANDARD TABLE OF e071k WITH DEFAULT KEY. FIELD-SYMBOLS LIKE LINE OF mt_object_method. ls_cts_object_entry-pgmid = 'R3TR'. ls_cts_object_entry-object = ms_item-obj_type. ls_cts_object_entry-obj_name = ms_item-obj_name. INSERT ls_cts_object_entry INTO TABLE lt_cts_object_entry. READ TABLE mt_object_method ASSIGNING WITH KEY objectname = ms_item-obj_type objecttype = 'L' method = 'AFTER_IMP'. IF sy-subrc = 0. * client is actually optional for most AIM, but let's supply it and hope * that those client-independent-ones just ignore it CALL FUNCTION -methodname EXPORTING iv_tarclient = sy-mandt iv_is_upgrade = abap_false TABLES tt_e071 = lt_cts_object_entry tt_e071k = lt_cts_key. ENDIF. ENDMETHOD. METHOD apply_clear_logic. IF mo_field_rules IS BOUND. mo_field_rules->apply_clear_logic( EXPORTING iv_table = |{ iv_table }| CHANGING ct_data = ct_data ). ENDIF. ENDMETHOD. METHOD apply_fill_logic. IF mo_field_rules IS BOUND. mo_field_rules->apply_fill_logic( EXPORTING iv_table = |{ iv_table }| iv_package = iv_package CHANGING ct_data = ct_data ). ENDIF. ENDMETHOD. METHOD before_export. DATA: lt_cts_object_entry TYPE STANDARD TABLE OF e071 WITH DEFAULT KEY, ls_cts_object_entry LIKE LINE OF lt_cts_object_entry, lt_cts_key TYPE STANDARD TABLE OF e071k WITH DEFAULT KEY, lv_client TYPE trclient. FIELD-SYMBOLS LIKE LINE OF mt_object_method. READ TABLE mt_object_method ASSIGNING WITH KEY objectname = ms_item-obj_type objecttype = 'L' method = 'BEFORE_EXP'. IF sy-subrc = 0. lv_client = sy-mandt. ls_cts_object_entry-pgmid = 'R3TR'. ls_cts_object_entry-object = ms_item-obj_type. ls_cts_object_entry-obj_name = ms_item-obj_name. INSERT ls_cts_object_entry INTO TABLE lt_cts_object_entry. CALL FUNCTION -methodname EXPORTING iv_client = lv_client TABLES tt_e071 = lt_cts_object_entry tt_e071k = lt_cts_key. ENDIF. ENDMETHOD. METHOD constructor. CONSTANTS lc_logical_transport_object TYPE c LENGTH 1 VALUE 'L'. SELECT SINGLE * FROM objh INTO ms_object_header WHERE objectname = is_item-obj_type AND objecttype = lc_logical_transport_object. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Not found in OBJH, or not supported' ). ENDIF. " object tables SELECT * FROM objsl INTO CORRESPONDING FIELDS OF TABLE mt_object_table WHERE objectname = is_item-obj_type AND objecttype = lc_logical_transport_object AND tobject = 'TABU' ORDER BY PRIMARY KEY. IF mt_object_table IS INITIAL. zcx_abapgit_exception=>raise( |Obviously corrupted object-type { is_item-obj_type }: No tables defined| ). ENDIF. " remove duplicate table/table-key entries " same table with different keys is ok SORT mt_object_table BY tobj_name tobjkey. DELETE ADJACENT DUPLICATES FROM mt_object_table COMPARING tobj_name tobjkey. " object methods SELECT * FROM objm INTO TABLE mt_object_method WHERE objectname = is_item-obj_type AND objecttype = lc_logical_transport_object ORDER BY PRIMARY KEY. ms_item = is_item. mv_language = iv_language. mo_field_rules = io_field_rules. ENDMETHOD. METHOD corr_insert. * this will also insert into TADIR zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name iv_package = iv_package iv_language = mv_language ). ENDMETHOD. METHOD delete. DATA: lv_where TYPE string, lv_primary TYPE objsl-tobj_name. FIELD-SYMBOLS LIKE LINE OF mt_object_table. lv_primary = get_primary_table( ). LOOP AT mt_object_table ASSIGNING . lv_where = get_where_clause( -tobj_name ). ASSERT NOT lv_where IS INITIAL. DELETE FROM (-tobj_name) WHERE (lv_where). IF -tobj_name = lv_primary. ASSERT sy-dbcnt <= 1. "Just to be on the very safe side ENDIF. ENDLOOP. corr_insert( iv_package ). ENDMETHOD. METHOD deserialize. validate( io_xml ). delete( iv_package ). deserialize_data( io_xml = io_xml iv_package = iv_package ). after_import( ). corr_insert( iv_package ). ENDMETHOD. METHOD deserialize_data. DATA: lr_ref TYPE REF TO data. FIELD-SYMBOLS: TYPE STANDARD TABLE, LIKE LINE OF mt_object_table. LOOP AT mt_object_table ASSIGNING . CREATE DATA lr_ref TYPE STANDARD TABLE OF (-tobj_name). ASSIGN lr_ref->* TO . io_xml->read( EXPORTING iv_name = -tobj_name CHANGING cg_data = ). apply_fill_logic( EXPORTING iv_table = -tobj_name iv_package = iv_package CHANGING ct_data = ). INSERT (-tobj_name) FROM TABLE . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error inserting data, { -tobj_name }| ). ENDIF. ENDLOOP. ENDMETHOD. METHOD distribute_name_to_components. DATA: lt_key_component_uncovered LIKE it_key_component, ls_key_component_uncovered LIKE LINE OF lt_key_component_uncovered, ls_objkey_sub LIKE cs_objkey, lv_objkey_sub_pos TYPE i, lv_remaining_length TYPE i, lv_count_components_covered LIKE ls_objkey_sub-num. DATA lv_len LIKE ls_key_component_uncovered-leng. lt_key_component_uncovered = it_key_component. ls_objkey_sub-num = cs_objkey-num. lv_objkey_sub_pos = 0. * we want to fill the attribute values which are not covered by explicit key components yet lv_count_components_covered = ls_objkey_sub-num - 1. DO lv_count_components_covered TIMES. DELETE lt_key_component_uncovered INDEX 1. ENDDO. LOOP AT lt_key_component_uncovered INTO ls_key_component_uncovered. CLEAR ls_objkey_sub-value. * Some datatype used in the key might exceed the total remaining characters length (e. g. SICF) TRY. lv_remaining_length = strlen( |{ substring( val = cs_objkey-value off = lv_objkey_sub_pos ) }| ). CATCH cx_sy_range_out_of_bounds. lv_remaining_length = 0. RETURN. ">>>>>>>>>>>>>>>>>>>>>>>>>>> ENDTRY. IF ls_key_component_uncovered-leng <= lv_remaining_length. lv_len = ls_key_component_uncovered-leng. ELSE. lv_len = lv_remaining_length. ENDIF. ls_objkey_sub-value = |{ substring( val = cs_objkey-value off = lv_objkey_sub_pos len = lv_len ) }|. ls_objkey_sub-num = cv_non_value_pos. INSERT ls_objkey_sub INTO TABLE ct_objkey. lv_objkey_sub_pos = lv_objkey_sub_pos + ls_key_component_uncovered-leng. cv_non_value_pos = cv_non_value_pos + 1. CLEAR ls_objkey_sub. IF lv_objkey_sub_pos = strlen( cs_objkey-value ). cs_objkey-num = cv_non_value_pos. EXIT. "end splitting - all characters captured ENDIF. ENDLOOP. ENDMETHOD. METHOD exists. DATA: lv_where_clause TYPE string, lv_primary TYPE objsl-tobj_name, lr_table_line TYPE REF TO data. FIELD-SYMBOLS: TYPE any. lv_primary = get_primary_table( ). lv_where_clause = get_where_clause( lv_primary ). CREATE DATA lr_table_line TYPE (lv_primary). ASSIGN lr_table_line->* TO . SELECT SINGLE * FROM (lv_primary) INTO WHERE (lv_where_clause). rv_bool = boolc( sy-dbcnt > 0 ). ENDMETHOD. METHOD get_key_fields. DATA: lv_table TYPE ddobjname. lv_table = iv_table. CALL FUNCTION 'DDIF_NAMETAB_GET' EXPORTING tabname = lv_table TABLES dfies_tab = rt_keys EXCEPTIONS not_found = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. DELETE rt_keys WHERE keyflag = abap_false. ENDMETHOD. METHOD get_primary_table. DATA: ls_object_table LIKE LINE OF mt_object_table. DATA: lt_object_table LIKE mt_object_table. " There might be several tables marked as "primary" " Sort by DB key so we get first one in the list lt_object_table = mt_object_table. SORT lt_object_table. READ TABLE lt_object_table INTO ls_object_table WITH KEY prim_table = abap_true. IF sy-subrc <> 0. " Fallback. For some objects, no primary table is explicitly flagged " Then, the one with only one key field shall be chosen READ TABLE lt_object_table INTO ls_object_table WITH KEY tobjkey = '/&'. "#EC CI_SUBRC ENDIF. IF ls_object_table IS INITIAL. zcx_abapgit_exception=>raise( |Object { ms_item-obj_type } has got no defined primary table| ). ENDIF. rv_table = ls_object_table-tobj_name. ENDMETHOD. METHOD get_where_clause. DATA: lv_objkey_pos TYPE i, lv_next_objkey_pos TYPE i, lv_value_pos TYPE i, lv_objkey_length TYPE i, lt_objkey TYPE ty_t_objkey, ls_objkey LIKE LINE OF lt_objkey, lv_non_value_pos TYPE numc3, lt_key_fields TYPE ddfields. DATA: lv_is_asterix TYPE abap_bool, lv_where_statement TYPE string, lv_key_pos TYPE i, lv_value128 TYPE string. FIELD-SYMBOLS LIKE LINE OF mt_object_table. FIELD-SYMBOLS LIKE LINE OF lt_key_fields. READ TABLE mt_object_table ASSIGNING WITH KEY tobj_name = iv_tobj_name. ASSERT sy-subrc = 0. lt_key_fields = get_key_fields( iv_tobj_name ). * analyze the object key and compose the key (table) CLEAR lt_objkey. CLEAR ls_objkey. lv_objkey_pos = 0. lv_non_value_pos = 1. lv_value_pos = 0. lv_objkey_length = strlen( -tobjkey ). WHILE lv_objkey_pos <= lv_objkey_length. ls_objkey-num = lv_non_value_pos. * command IF -tobjkey+lv_objkey_pos(1) = '/'. IF NOT ls_objkey-value IS INITIAL. * We reached the end of a key-definition. * this key part may address multiple fields. * E. g. six characters may address one boolean field and a five-digit version field. * Thus, we need to analyze the remaining key components which have not been covered yet. split_value_to_keys( EXPORTING it_key_component = lt_key_fields CHANGING ct_objkey = lt_objkey cs_objkey = ls_objkey cv_non_value_pos = lv_non_value_pos ). ENDIF. lv_next_objkey_pos = lv_objkey_pos + 1. * '*' means all further key values IF -tobjkey+lv_next_objkey_pos(1) = '*'. ls_objkey-value = '*'. INSERT ls_objkey INTO TABLE lt_objkey. CLEAR ls_objkey. lv_non_value_pos = lv_non_value_pos + 1. lv_objkey_pos = lv_objkey_pos + 1. * object name ELSEIF -tobjkey+lv_next_objkey_pos(1) = '&'. ls_objkey-value = ms_item-obj_name. * The object name might comprise multiple key components (e. g. WDCC) * This string needs to be split distribute_name_to_components( EXPORTING it_key_component = lt_key_fields CHANGING ct_objkey = lt_objkey cs_objkey = ls_objkey cv_non_value_pos = lv_non_value_pos ). CLEAR ls_objkey. lv_objkey_pos = lv_objkey_pos + 1. * language ELSEIF -tobjkey+lv_next_objkey_pos(1) = 'L'. ls_objkey-value = mv_language. INSERT ls_objkey INTO TABLE lt_objkey. CLEAR ls_objkey. lv_non_value_pos = lv_non_value_pos + 1. lv_objkey_pos = lv_objkey_pos + 1. * Client ELSEIF -tobjkey+lv_next_objkey_pos(1) = 'C'. ls_objkey-value = sy-mandt. INSERT ls_objkey INTO TABLE lt_objkey. CLEAR ls_objkey. lv_non_value_pos = lv_non_value_pos + 1. lv_objkey_pos = lv_objkey_pos + 1. ENDIF. lv_value_pos = 0. * value ELSE. ls_objkey-value+lv_value_pos(1) = -tobjkey+lv_objkey_pos(1). lv_value_pos = lv_value_pos + 1. ENDIF. lv_objkey_pos = lv_objkey_pos + 1. ENDWHILE. * Similarly to that, fixed values might be supplied in the object key which actually make up key components IF NOT ls_objkey-value IS INITIAL. split_value_to_keys( EXPORTING it_key_component = lt_key_fields CHANGING ct_objkey = lt_objkey cs_objkey = ls_objkey cv_non_value_pos = lv_non_value_pos ). ENDIF. * compose the where clause lv_is_asterix = abap_false. lv_key_pos = 1. LOOP AT lt_key_fields ASSIGNING . READ TABLE lt_objkey INTO ls_objkey WITH TABLE KEY num = lv_key_pos. IF sy-subrc <> 0 OR -fieldname = 'LANGU'. CLEAR ls_objkey. lv_key_pos = lv_key_pos + 1. CONTINUE. ENDIF. IF ls_objkey-value = '*'. lv_is_asterix = abap_true. ENDIF. IF lv_is_asterix = abap_true. CONTINUE. ENDIF. IF NOT lv_where_statement IS INITIAL. CONCATENATE lv_where_statement 'AND' INTO lv_where_statement SEPARATED BY space. ENDIF. lv_value128 = cl_abap_dyn_prg=>quote( ls_objkey-value ). CONCATENATE lv_where_statement -fieldname '=' lv_value128 INTO lv_where_statement SEPARATED BY space. lv_key_pos = lv_key_pos + 1. ENDLOOP. rv_where = condense( lv_where_statement ). ENDMETHOD. METHOD serialize. before_export( ). serialize_data( io_xml ). ENDMETHOD. METHOD serialize_data. DATA: lr_ref TYPE REF TO data, lv_where TYPE string. FIELD-SYMBOLS: TYPE STANDARD TABLE, LIKE LINE OF mt_object_table. LOOP AT mt_object_table ASSIGNING . CREATE DATA lr_ref TYPE STANDARD TABLE OF (-tobj_name). ASSIGN lr_ref->* TO . lv_where = get_where_clause( -tobj_name ). SELECT * FROM (-tobj_name) INTO TABLE WHERE (lv_where) ORDER BY PRIMARY KEY. apply_clear_logic( EXPORTING iv_table = -tobj_name CHANGING ct_data = ). io_xml->add( iv_name = -tobj_name ig_data = ). ENDLOOP. ENDMETHOD. METHOD split_value_to_keys. DATA: lt_key_component_uncovered LIKE it_key_component, ls_dummy LIKE LINE OF ct_objkey, ls_key_component_uncovered LIKE LINE OF lt_key_component_uncovered, ls_objkey_sub LIKE cs_objkey, lv_objkey_sub_pos TYPE i. lt_key_component_uncovered = it_key_component. * we want to fill the attribute values which are not covered by explicit key components yet LOOP AT ct_objkey INTO ls_dummy. DELETE lt_key_component_uncovered INDEX 1. ENDLOOP. ls_objkey_sub-num = cs_objkey-num. lv_objkey_sub_pos = 0. LOOP AT lt_key_component_uncovered INTO ls_key_component_uncovered. CLEAR ls_objkey_sub-value. ls_objkey_sub-value = cs_objkey-value+lv_objkey_sub_pos(ls_key_component_uncovered-leng). ls_objkey_sub-num = cv_non_value_pos. INSERT ls_objkey_sub INTO TABLE ct_objkey. lv_objkey_sub_pos = lv_objkey_sub_pos + ls_key_component_uncovered-leng. cv_non_value_pos = cv_non_value_pos + 1. CLEAR ls_objkey_sub. IF lv_objkey_sub_pos = strlen( cs_objkey-value ). cs_objkey-num = cv_non_value_pos. EXIT. "end splitting - all characters captured ENDIF. ENDLOOP. ENDMETHOD. METHOD validate. DATA: lv_where TYPE string, lv_primary TYPE objsl-tobj_name, lr_ref TYPE REF TO data. FIELD-SYMBOLS: TYPE STANDARD TABLE. lv_primary = get_primary_table( ). CREATE DATA lr_ref TYPE STANDARD TABLE OF (lv_primary). ASSIGN lr_ref->* TO . io_xml->read( EXPORTING iv_name = lv_primary CHANGING cg_data = ). IF lines( ) = 0. zcx_abapgit_exception=>raise( |Primary table { lv_primary } not found in imported container| ). ELSEIF lines( ) <> 1. zcx_abapgit_exception=>raise( |Primary table { lv_primary } contains more than one instance!| ). ENDIF. lv_where = get_where_clause( lv_primary ). * validate that max one local instance was affected by the import SELECT COUNT(*) FROM (lv_primary) WHERE (lv_where). IF sy-dbcnt > 1. zcx_abapgit_exception=>raise( |More than one instance exists locally in primary table { lv_primary }| ). ENDIF. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECTS_FACTORY IMPLEMENTATION. METHOD get_gui_jumper. IF gi_gui_jumper IS INITIAL. CREATE OBJECT gi_gui_jumper TYPE zcl_abapgit_gui_jumper. ENDIF. ri_gui_jumper = gi_gui_jumper. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_objects_bridge IMPLEMENTATION. METHOD constructor. DATA ls_objtype_map LIKE LINE OF gt_objtype_map. super->constructor( is_item = is_item iv_language = zif_abapgit_definitions=>c_english io_files = io_files io_i18n_params = io_i18n_params ). initialize( ). * determine the responsible plugin READ TABLE gt_objtype_map INTO ls_objtype_map WITH TABLE KEY obj_typ = is_item-obj_type. IF sy-subrc = 0. CREATE OBJECT mo_plugin TYPE (ls_objtype_map-plugin_class). CALL METHOD mo_plugin->('SET_ITEM') EXPORTING iv_obj_type = is_item-obj_type iv_obj_name = is_item-obj_name. ELSE. RAISE EXCEPTION TYPE cx_sy_create_object_error EXPORTING classname = 'LCL_OBJECTS_BRIDGE'. ENDIF. ENDMETHOD. METHOD initialize. DATA lt_plugin_class TYPE STANDARD TABLE OF seoclsname WITH DEFAULT KEY. DATA lv_plugin_class LIKE LINE OF lt_plugin_class. DATA lo_plugin TYPE REF TO object. DATA lt_plugin_obj_type TYPE STANDARD TABLE OF tadir-object WITH DEFAULT KEY. DATA ls_objtype_map LIKE LINE OF gt_objtype_map. IF gv_init = abap_true. RETURN. ENDIF. gv_init = abap_true. SELECT clsname FROM seometarel INTO TABLE lt_plugin_class WHERE refclsname LIKE 'ZCL_ABAPGITP_OBJECT%' AND version = '1' ORDER BY clsname. "#EC CI_SUBRC CLEAR gt_objtype_map. LOOP AT lt_plugin_class INTO lv_plugin_class WHERE table_line <> 'ZCL_ABAPGITP_OBJECT_BY_SOBJ'. * have the generic plugin only as fallback TRY. CREATE OBJECT lo_plugin TYPE (lv_plugin_class). CATCH cx_sy_create_object_error. CONTINUE. ">>>>>>>>>>>>>> ENDTRY. CALL METHOD lo_plugin->('GET_SUPPORTED_OBJ_TYPES') IMPORTING rt_obj_type = lt_plugin_obj_type. ls_objtype_map-plugin_class = lv_plugin_class. LOOP AT lt_plugin_obj_type INTO ls_objtype_map-obj_typ. INSERT ls_objtype_map INTO TABLE gt_objtype_map. IF sy-subrc <> 0. * No exception in class-constructor possible. * Anyway, a shortdump is more appropriate in this case ASSERT 'There must not be' = |multiple abapGit-Plugins for the same object type { ls_objtype_map-obj_typ }|. ENDIF. ENDLOOP. ENDLOOP. "at plugins * and the same for the generic plugin if exists * have the generic plugin only as fallback LOOP AT lt_plugin_class INTO lv_plugin_class WHERE table_line = 'ZCL_ABAPGITP_OBJECT_BY_SOBJ'. CREATE OBJECT lo_plugin TYPE (lv_plugin_class). CALL METHOD lo_plugin->('GET_SUPPORTED_OBJ_TYPES') RECEIVING rt_obj_type = lt_plugin_obj_type. ls_objtype_map-plugin_class = lv_plugin_class. LOOP AT lt_plugin_obj_type INTO ls_objtype_map-obj_typ. INSERT ls_objtype_map INTO TABLE gt_objtype_map. "knowingly ignore the subrc ENDLOOP. ENDLOOP. "at plugins ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. METHOD zif_abapgit_object~delete. DATA lx_plugin TYPE REF TO cx_static_check. TRY. CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~DELETE'). CATCH cx_static_check INTO lx_plugin. zcx_abapgit_exception=>raise( lx_plugin->get_text( ) ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lx_plugin TYPE REF TO cx_static_check. TRY. CALL METHOD mo_plugin->('WRAP_DESERIALIZE') EXPORTING iv_package = iv_package io_xml = io_xml. CATCH cx_static_check INTO lx_plugin. zcx_abapgit_exception=>raise( lx_plugin->get_text( ) ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~EXISTS') RECEIVING rv_bool = rv_bool. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. DATA ls_meta TYPE ty_metadata. CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~GET_METADATA') RECEIVING rs_metadata = ls_meta. IF ls_meta-late_deser = abap_true. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ELSEIF ls_meta-ddic = abap_true. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ELSE. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. DATA ls_meta TYPE ty_metadata. CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~GET_METADATA') RECEIVING rs_metadata = ls_meta. MOVE-CORRESPONDING ls_meta TO rs_metadata. ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = abap_true. ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. CALL METHOD mo_plugin->('ZIF_ABAPGITP_PLUGIN~JUMP'). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. CALL METHOD mo_plugin->('WRAP_SERIALIZE') EXPORTING io_xml = io_xml. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_objects IMPLEMENTATION. METHOD changed_by. DATA: li_obj TYPE REF TO zif_abapgit_object. " For unsupported objects, return empty string IF is_type_supported( is_item-obj_type ) = abap_false. RETURN. ENDIF. TRY. li_obj = create_object( is_item ). rv_user = li_obj->changed_by( get_extra_from_filename( iv_filename ) ). CATCH zcx_abapgit_exception ##NO_HANDLER. " Ignore errors ENDTRY. IF rv_user IS INITIAL. " Eg. ".abapgit.xml" file rv_user = zcl_abapgit_objects_super=>c_user_unknown. ENDIF. ENDMETHOD. METHOD change_package_assignments. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_tadir_pgmid = 'R3TR' wi_tadir_object = is_item-obj_type wi_tadir_obj_name = is_item-obj_name wi_tadir_devclass = is_item-devclass wi_test_modus = abap_false EXCEPTIONS OTHERS = 1. IF sy-subrc = 0. ii_log->add_success( iv_msg = |Object { is_item-obj_name } assigned to package { is_item-devclass }| is_item = is_item ). ELSE. ii_log->add_error( iv_msg = |Package change of object { is_item-obj_name } failed| is_item = is_item ). ENDIF. ENDMETHOD. METHOD check_duplicates. DATA: lt_files TYPE zif_abapgit_git_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_main_package. " check package restrictions, closed package, descriptive or " functional package cl_pak_object_types=>check_object_type( EXPORTING i_working_mode = 'I' i_package_name = iv_package i_pgmid = 'R3TR' i_object_type = iv_obj_type EXCEPTIONS wrong_object_type = 1 package_not_extensible = 2 package_not_loaded = 3 OTHERS = 4 ). CASE sy-subrc. WHEN 0. RETURN. WHEN 2. zcx_abapgit_exception=>raise( |Object type { iv_obj_type } not allowed for package { iv_package }| ). WHEN OTHERS. zcx_abapgit_exception=>raise_t100( ). ENDCASE. 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_type_supported( -obj_type ) = abap_false. CONTINUE. ENDIF. li_obj = create_object( ). 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 check_original_system. DATA: lv_srcsystem TYPE tadir-srcsystem, lv_error TYPE abap_bool. FIELD-SYMBOLS LIKE LINE OF it_items. lv_srcsystem = io_dot->get_original_system( ). IF lv_srcsystem IS INITIAL. RETURN. ENDIF. ii_log->add_info( |>> Checking original system| ). LOOP AT it_items ASSIGNING WHERE srcsystem <> lv_srcsystem AND srcsystem IS NOT INITIAL. ii_log->add_error( iv_msg = |Object belongs to system { -srcsystem }. Can't overwrite it from system { lv_srcsystem }| is_item = ). lv_error = abap_true. ENDLOOP. IF lv_error = abap_true. zcx_abapgit_exception=>raise( 'Error trying to overwrite object from different system' ). ENDIF. 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_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. DATA: lv_message TYPE string, lv_class_name TYPE string, ls_obj_serializer_map LIKE LINE OF gt_obj_serializer_map. " serialize & deserialize require files and i18n parameters, " other calls are good without them ASSERT io_files IS BOUND AND io_i18n_params IS BOUND OR io_files IS NOT BOUND AND io_i18n_params IS NOT BOUND. 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 deserialization * Once this has been triggered, the same deserializer 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'. 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. IF io_files IS BOUND AND io_i18n_params IS BOUND. CREATE OBJECT ri_obj TYPE (lv_class_name) EXPORTING is_item = is_item iv_language = io_i18n_params->ms_params-main_language io_files = io_files io_i18n_params = io_i18n_params. ELSE. CREATE OBJECT ri_obj TYPE (lv_class_name) EXPORTING is_item = is_item iv_language = zif_abapgit_definitions=>c_english. ENDIF. CATCH cx_sy_create_object_error. lv_message = |Object type { is_item-obj_type } is not supported by this system|. IF iv_native_only = abap_false. TRY. " 2nd step, try looking for plugins IF io_files IS BOUND AND io_i18n_params IS BOUND. CREATE OBJECT ri_obj TYPE zcl_abapgit_objects_bridge EXPORTING is_item = is_item io_files = io_files io_i18n_params = io_i18n_params. ELSE. CREATE OBJECT ri_obj TYPE zcl_abapgit_objects_bridge EXPORTING is_item = is_item. ENDIF. 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. IF it_tadir IS INITIAL. RETURN. ENDIF. lt_tadir = it_tadir. IF ii_log IS BOUND. IF lines( lt_tadir ) = 1. ii_log->add_info( |>>> Deleting 1 object| ). ELSE. ii_log->add_info( |>>> Deleting { lines( lt_tadir ) } objects| ). ENDIF. ENDIF. IF is_checks-transport-required = abap_true. zcl_abapgit_factory=>get_default_transport( )->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( lt_items ). CATCH zcx_abapgit_exception INTO lx_error. zcl_abapgit_factory=>get_default_transport( )->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_object( iv_package = -devclass is_item = ls_item iv_transport = is_checks-transport-transport ). INSERT INTO TABLE lt_deleted. DELETE lt_tadir. lv_count = lv_count + 1. " make sure to save object deletions COMMIT WORK. IF ii_log IS BOUND. ii_log->add_info( iv_msg = |Object { ls_item-obj_type } { ls_item-obj_name } deleted| is_item = ls_item ). ENDIF. 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_factory=>get_default_transport( )->reset( ). IF lx_error IS BOUND AND lines( lt_tadir ) > 0. zcx_abapgit_exception=>raise( 'Error during uninstall. Check the log.' ). ENDIF. li_progress->off( ). ENDMETHOD. METHOD delete_object. DATA: li_obj TYPE REF TO zif_abapgit_object. " Nothing to do for unsupported objects IF is_type_supported( is_item-obj_type ) = abap_false. RETURN. ENDIF. li_obj = create_object( is_item ). li_obj->delete( iv_package = iv_package iv_transport = iv_transport ). ENDMETHOD. METHOD deserialize. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, lo_dot TYPE REF TO zcl_abapgit_dot_abapgit, li_obj TYPE REF TO zif_abapgit_object, lt_remote TYPE zif_abapgit_git_definitions=>ty_files_tt, lv_package TYPE devclass, lo_files TYPE REF TO zcl_abapgit_objects_files, ls_metadata TYPE zif_abapgit_definitions=>ty_metadata, 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. DATA lo_i18n_params TYPE REF TO zcl_abapgit_i18n_params. DATA lo_timer TYPE REF TO zcl_abapgit_timer. DATA lo_abap_language_vers TYPE REF TO zcl_abapgit_abap_language_vers. 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( ). lo_dot = io_repo->get_dot_abapgit( ). IF is_checks-transport-required = abap_true. zcl_abapgit_factory=>get_default_transport( )->set( is_checks-transport-transport ). ENDIF. zcl_abapgit_objects_activation=>clear( ). lt_remote = io_repo->get_files_remote( iv_ignore_files = abap_true ). lt_results = zcl_abapgit_file_deserialize=>get_results( io_repo = io_repo ii_log = ii_log ). IF lt_results IS INITIAL. RETURN. ENDIF. zcl_abapgit_objects_check=>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 ). lo_timer = zcl_abapgit_timer=>create( iv_text = 'Deserialize:' iv_count = lines( lt_items ) )->start( ). zcl_abapgit_factory=>get_cts_api( )->confirm_transport_messages( ). check_objects_locked( lt_items ). " Check the original system of all objects to prevent overwriting check_original_system( it_items = lt_items ii_log = ii_log io_dot = io_repo->get_dot_abapgit( ) ). lo_i18n_params = zcl_abapgit_i18n_params=>new( is_params = lo_dot->determine_i18n_parameters( io_repo->get_local_settings( )-main_language_only ) ). IF lines( lt_items ) = 1. ii_log->add_info( |>>> Deserializing 1 object| ). ELSE. ii_log->add_info( |>>> Deserializing { lines( lt_items ) } objects| ). ENDIF. CREATE OBJECT lo_abap_language_vers EXPORTING io_dot_abapgit = lo_dot. lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). LOOP AT lt_results ASSIGNING . li_progress->show( iv_current = sy-tabix iv_text = |Prepare Deserialize: { -obj_type } { -obj_name }| ). CLEAR ls_item. CLEAR: lv_path, lv_package. ls_item-obj_type = -obj_type. ls_item-obj_name = -obj_name. "error handling & logging added TRY. IF ls_item-obj_type <> 'NSPC'. " If package does not exist yet, it will be created with this call lv_package = lo_folder_logic->path_to_package( iv_top = io_repo->get_package( ) io_dot = lo_dot iv_path = -path ). check_main_package( iv_package = lv_package iv_obj_type = ls_item-obj_type ). ENDIF. 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. ls_item-devclass = lv_package. ls_item-abap_language_version = lo_abap_language_vers->get_abap_language_vers_by_objt( iv_object_type = ls_item-obj_type iv_package = lv_package ). IF -packmove = abap_true. " Move object to new package change_package_assignments( is_item = ls_item ii_log = ii_log ). " No other changes required CONTINUE. ENDIF. " Create or update object lo_files = zcl_abapgit_objects_files=>new( is_item = ls_item iv_path = lv_path ). lo_files->set_files( lt_remote ). IF lo_files->is_json_metadata( ) = abap_false. "analyze XML in order to instantiate the proper serializer lo_xml = lo_files->read_xml( ). ls_metadata = lo_xml->get_metadata( ). ELSE. " there's no XML and metadata for JSON format CLEAR: lo_xml, ls_metadata. ENDIF. li_obj = create_object( is_item = ls_item is_metadata = ls_metadata io_files = lo_files io_i18n_params = lo_i18n_params ). compare_remote_to_local( ii_object = li_obj it_remote = lt_remote is_result = ii_log = ii_log ). "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 = zif_abapgit_object=>gc_step_id-ddic AND zcl_abapgit_objects_activation=>is_ddic_type( ls_item-obj_type ) = 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. " LXE, TODO refactor and move below activation IF lo_i18n_params->is_lxe_applicable( ) = abap_true. zcl_abapgit_factory=>get_lxe_texts( )->deserialize( iv_object_type = ls_item-obj_type iv_object_name = ls_item-obj_name io_i18n_params = lo_i18n_params ii_xml = lo_xml io_files = lo_files ). ENDIF. 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. li_progress->off( ). "run deserialize for all steps and its objects deserialize_steps( EXPORTING it_steps = lt_steps ii_log = ii_log iv_transport = is_checks-transport-transport CHANGING ct_files = rt_accessed_files ). " TODO: LXE translations (objects has been activated by now) update_package_tree( io_repo->get_package( ) ). " Set the original system for all updated objects to what's defined in repo settings update_original_system( it_items = lt_items ii_log = ii_log io_dot = lo_dot iv_transport = is_checks-transport-transport ). zcl_abapgit_factory=>get_default_transport( )->reset( ). lo_timer->end( abap_true ). ENDMETHOD. METHOD deserialize_checks. rs_checks = zcl_abapgit_objects_check=>deserialize_checks( io_repo ). ENDMETHOD. METHOD deserialize_step. DATA: li_progress TYPE REF TO zif_abapgit_progress, li_exit TYPE REF TO zif_abapgit_exit, lo_base TYPE REF TO zcl_abapgit_objects_super, lx_exc TYPE REF TO zcx_abapgit_exception. FIELD-SYMBOLS: LIKE LINE OF is_step-objects. zcl_abapgit_objects_activation=>clear( ). ii_log->add_success( |>> Step { is_step-order } - { is_step-descr }| ). 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 = |Step { is_step-order } - { is_step-descr }:| && | { -item-obj_type } { -item-obj_name }| ). TRY. -obj->deserialize( iv_package = -package io_xml = -xml iv_step = is_step-step_id ii_log = ii_log iv_transport = iv_transport ). lo_base ?= -obj. APPEND LINES OF lo_base->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. li_progress->show( iv_current = lines( is_step-objects ) iv_text = |Step { is_step-order } - Activating Objects| ). CASE is_step-step_id. WHEN zif_abapgit_object=>gc_step_id-ddic. zcl_abapgit_objects_activation=>activate( iv_ddic = abap_true ii_log = ii_log ). WHEN zif_abapgit_object=>gc_step_id-abap. zcl_abapgit_objects_activation=>activate( iv_ddic = abap_false ii_log = ii_log ). 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( iv_ddic = abap_true ii_log = ii_log ). zcl_abapgit_objects_activation=>activate( iv_ddic = abap_false ii_log = ii_log ). ENDCASE. li_progress->off( ). * Call postprocessing li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->deserialize_postprocess( is_step = is_step ii_log = ii_log ). ENDMETHOD. METHOD deserialize_steps. FIELD-SYMBOLS LIKE LINE OF it_steps. LOOP AT it_steps ASSIGNING . deserialize_step( EXPORTING is_step = ii_log = ii_log iv_transport = iv_transport CHANGING ct_files = ct_files ). ENDLOOP. SORT ct_files BY path ASCENDING filename ASCENDING. DELETE ADJACENT DUPLICATES FROM ct_files. " Just in case ENDMETHOD. METHOD exists. DATA: li_obj TYPE REF TO zif_abapgit_object. " Might be called for objects without tadir entry IF is_item IS INITIAL. RETURN. ENDIF. " For unsupported objects, assume object exists IF is_type_supported( is_item-obj_type ) = abap_false. rv_bool = abap_true. RETURN. ENDIF. TRY. li_obj = create_object( is_item ). rv_bool = li_obj->exists( ). CATCH zcx_abapgit_exception. " Ignore errors and assume the object exists rv_bool = abap_true. ENDTRY. 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-early. -descr = 'Pre-process Objects'. -syntax_check = abap_false. -order = 1. APPEND INITIAL LINE TO rt_steps ASSIGNING . -step_id = zif_abapgit_object=>gc_step_id-ddic. -descr = 'Deserialize DDIC Objects'. -syntax_check = abap_false. -order = 2. APPEND INITIAL LINE TO rt_steps ASSIGNING . -step_id = zif_abapgit_object=>gc_step_id-abap. -descr = 'Deserialize non-DDIC Objects'. -syntax_check = abap_false. -order = 3. APPEND INITIAL LINE TO rt_steps ASSIGNING . -step_id = zif_abapgit_object=>gc_step_id-late. -descr = 'Post-process Objects'. -syntax_check = abap_true. -order = 4. SORT rt_steps BY order. " ensure correct processing order ENDMETHOD. METHOD get_extra_from_filename. IF iv_filename IS NOT INITIAL. FIND REGEX '\..*\.([\-a-z0-9_%]*)\.' IN iv_filename SUBMATCHES rv_extra. IF sy-subrc = 0. rv_extra = cl_http_utility=>unescape_url( rv_extra ). ENDIF. ENDIF. ENDMETHOD. METHOD is_active. DATA: li_obj TYPE REF TO zif_abapgit_object. " For unsupported objects, assume active state IF is_type_supported( is_item-obj_type ) = abap_false. rv_active = abap_true. RETURN. ENDIF. TRY. li_obj = create_object( is_item ). rv_active = li_obj->is_active( ). CATCH cx_sy_dyn_call_illegal_method cx_sy_ref_is_initial zcx_abapgit_exception. " Ignore errors and assume active state rv_active = abap_true. ENDTRY. ENDMETHOD. METHOD is_supported. TRY. create_object( is_item = is_item iv_native_only = iv_native_only ). rv_bool = abap_true. CATCH zcx_abapgit_exception. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD is_type_supported. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, ls_supported_obj_type TYPE ty_supported_types. FIELD-SYMBOLS TYPE ty_supported_types. IF iv_obj_type IS INITIAL. " empty object type should never exist RETURN. ENDIF. READ TABLE gt_supported_obj_types ASSIGNING WITH KEY obj_type = iv_obj_type. IF sy-subrc <> 0. ls_item-obj_type = iv_obj_type. ls_supported_obj_type-obj_type = iv_obj_type. ls_supported_obj_type-supported = is_supported( ls_item ). INSERT ls_supported_obj_type INTO TABLE gt_supported_obj_types. rv_bool = ls_supported_obj_type-supported. RETURN. ENDIF. rv_bool = -supported. ENDMETHOD. METHOD jump. DATA: li_obj TYPE REF TO zif_abapgit_object, lv_exit TYPE abap_bool. " Nothing to do for unsupported objects IF is_type_supported( is_item-obj_type ) = abap_false. zcx_abapgit_exception=>raise( |Object type { is_item-obj_type } is not supported by this system| ). ENDIF. " Nothing to do if object does not exist li_obj = create_object( is_item ). IF li_obj->exists( ) = abap_false. zcx_abapgit_exception=>raise( |Object { is_item-obj_type } { is_item-obj_name } doesn't exist| ). ENDIF. " First priority object-specific handler lv_exit = li_obj->jump( get_extra_from_filename( iv_filename ) ). IF lv_exit = abap_false. " Open object in new window with generic jumper lv_exit = zcl_abapgit_objects_factory=>get_gui_jumper( )->jump( is_item = is_item is_sub_item = is_sub_item iv_line_number = iv_line_number iv_new_window = iv_new_window ). ENDIF. IF lv_exit = abap_false. zcx_abapgit_exception=>raise( |Jump to { is_item-obj_type } { is_item-obj_name } not possible| ). 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. ls_item-srcsystem = -srcsystem. ls_item-origlang = -origlang. 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. ls_item-srcsystem = -srcsystem. ls_item-origlang = -masterlang. INSERT ls_item INTO TABLE rt_items. ENDLOOP. ENDMETHOD. METHOD serialize. DATA: li_obj TYPE REF TO zif_abapgit_object, lx_error TYPE REF TO zcx_abapgit_exception, 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. IF is_type_supported( is_item-obj_type ) = abap_false. zcx_abapgit_exception=>raise( |Object type ignored, not supported: { is_item-obj_type }-{ is_item-obj_name }| ). ENDIF. lo_files = zcl_abapgit_objects_files=>new( is_item ). li_obj = create_object( is_item = is_item io_files = lo_files io_i18n_params = io_i18n_params ). CREATE OBJECT li_xml TYPE zcl_abapgit_xml_output. rs_files_and_item-item = is_item. TRY. li_obj->serialize( li_xml ). CATCH zcx_abapgit_exception INTO lx_error. rs_files_and_item-item-inactive = boolc( li_obj->is_active( ) = abap_false ). RAISE EXCEPTION lx_error. ENDTRY. IF io_i18n_params->is_lxe_applicable( ) = abap_true. zcl_abapgit_factory=>get_lxe_texts( )->serialize( iv_object_type = is_item-obj_type iv_object_name = is_item-obj_name io_i18n_params = io_i18n_params io_files = lo_files ii_xml = li_xml ). ENDIF. IF lo_files->is_json_metadata( ) = abap_false. lo_files->add_xml( ii_xml = li_xml is_metadata = li_obj->get_metadata( ) ). ENDIF. 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. DATA ls_item TYPE zif_abapgit_definitions=>ty_item. DATA ls_supported_obj_type TYPE ty_supported_types. DATA lt_types TYPE zif_abapgit_exit=>ty_object_types. DATA lv_type LIKE LINE OF lt_types. DATA li_exit TYPE REF TO zif_abapgit_exit. FIELD-SYMBOLS LIKE LINE OF lt_objects. FIELD-SYMBOLS TYPE ty_supported_types. IF gv_supported_obj_types_loaded = abap_true. LOOP AT gt_supported_obj_types ASSIGNING WHERE supported = abap_true. INSERT -obj_type INTO TABLE rt_types. ENDLOOP. RETURN. ENDIF. " delete content because it might be filled already by method IS_TYPE_SUPPORTED CLEAR gt_supported_obj_types. 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'. INSERT -object INTO TABLE lt_types. ENDLOOP. li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->change_supported_object_types( CHANGING ct_types = lt_types ). LOOP AT lt_types INTO lv_type. ls_item-obj_type = lv_type. ls_supported_obj_type-obj_type = lv_type. ls_supported_obj_type-supported = is_supported( ls_item ). INSERT ls_supported_obj_type INTO TABLE gt_supported_obj_types. IF ls_supported_obj_type-supported = abap_true. INSERT ls_supported_obj_type-obj_type INTO TABLE rt_types. ENDIF. ENDLOOP. gv_supported_obj_types_loaded = abap_true. ENDMETHOD. METHOD update_original_system. DATA: lv_srcsystem TYPE tadir-srcsystem, lv_transport_type_from TYPE trfunction, lv_transport_type_to TYPE trfunction, lv_errors TYPE abap_bool, lv_msg TYPE string. FIELD-SYMBOLS LIKE LINE OF it_items. lv_srcsystem = io_dot->get_original_system( ). IF lv_srcsystem IS INITIAL. RETURN. ELSEIF lv_srcsystem = 'SID'. " Change objects to local system and switch repairs to development requests lv_srcsystem = sy-sysid. lv_transport_type_from = zif_abapgit_cts_api=>c_transport_type-wb_repair. lv_transport_type_to = zif_abapgit_cts_api=>c_transport_type-wb_task. ELSE. " Change objects to external system and switch development requests to repairs lv_transport_type_from = zif_abapgit_cts_api=>c_transport_type-wb_task. lv_transport_type_to = zif_abapgit_cts_api=>c_transport_type-wb_repair. ENDIF. ii_log->add_info( |>> Setting original system| ). LOOP AT it_items ASSIGNING . " Local packages are not stored in TADIR IF -obj_type = 'DEVC' AND -obj_name(1) = '$'. CONTINUE. ENDIF. IF exists( ) = abap_true. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_tadir_pgmid = 'R3TR' wi_tadir_object = -obj_type wi_tadir_obj_name = -obj_name wi_tadir_srcsystem = lv_srcsystem wi_test_modus = abap_false EXCEPTIONS tadir_entry_not_existing = 1 tadir_entry_ill_type = 2 no_systemname = 3 no_systemtype = 4 original_system_conflict = 5 object_reserved_for_devclass = 6 object_exists_global = 7 object_exists_local = 8 object_is_distributed = 9 obj_specification_not_unique = 10 no_authorization_to_delete = 11 devclass_not_existing = 12 simultanious_set_remove_repair = 13 order_missing = 14 no_modification_of_head_syst = 15 pgmid_object_not_allowed = 16 masterlanguage_not_specified = 17 devclass_not_specified = 18 specify_owner_unique = 19 loc_priv_objs_no_repair = 20 gtadir_not_reached = 21 object_locked_for_order = 22 change_of_class_not_allowed = 23 no_change_from_sap_to_tmp = 24 OTHERS = 25. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_msg. ii_log->add_error( iv_msg = lv_msg is_item = ). lv_errors = abap_true. ENDIF. ENDIF. ENDLOOP. IF lv_errors IS INITIAL. " Since original system has changed, the type of transport request needs to be adjusted zcl_abapgit_factory=>get_cts_api( )->change_transport_type( iv_transport_request = iv_transport iv_transport_type_from = lv_transport_type_from iv_transport_type_to = lv_transport_type_to ). ENDIF. 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. ENDCLASS. CLASS zcl_abapgit_object_xslt IMPLEMENTATION. METHOD get. DATA: lv_name TYPE cxsltdesc. lv_name = ms_item-obj_name. cl_o2_api_xsltdesc=>load( EXPORTING p_xslt_desc = lv_name IMPORTING p_obj = ro_xslt EXCEPTIONS not_existing = 1 permission_failure = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from cl_o2_api_xsltdesc=>load' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lo_xslt TYPE REF TO cl_o2_api_xsltdesc, ls_attributes TYPE o2xsltattr. lo_xslt = get( ). lo_xslt->get_attributes( RECEIVING p_attributes = ls_attributes EXCEPTIONS object_invalid = 1 xsltdesc_deleted = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. rv_user = ls_attributes-changedby. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_xslt TYPE REF TO cl_o2_api_xsltdesc, lv_name TYPE cxsltdesc. lv_name = ms_item-obj_name. cl_o2_api_xsltdesc=>load( EXPORTING p_xslt_desc = lv_name IMPORTING p_obj = lo_xslt EXCEPTIONS error_occured = 1 not_existing = 2 permission_failure = 3 version_not_found = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from cl_o2_api_xsltdesc=>load' ). ENDIF. lo_xslt->set_changeable( abap_true ). lo_xslt->delete( ). lo_xslt->save( ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_source TYPE string, lo_xslt TYPE REF TO cl_o2_api_xsltdesc, lv_len TYPE i, ls_attributes TYPE o2xsltattr. " Transformation might depend on other objects like a class " We attempt to activate it in late step IF iv_step = zif_abapgit_object=>gc_step_id-late. IF zif_abapgit_object~is_active( ) = abap_false. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDIF. RETURN. ENDIF. IF zif_abapgit_object~exists( ) = abap_true. zif_abapgit_object~delete( iv_package = iv_package iv_transport = iv_transport ). ENDIF. io_xml->read( EXPORTING iv_name = 'ATTRIBUTES' CHANGING cg_data = ls_attributes ). ls_attributes-devclass = iv_package. lv_source = mo_files->read_string( iv_extra = 'source' iv_ext = 'xml' ). zcl_abapgit_utils=>check_eol( lv_source ). * workaround: somewhere additional linefeeds are added lv_len = strlen( lv_source ) - 2. IF lv_source+lv_len(2) = cl_abap_char_utilities=>cr_lf. lv_source = lv_source(lv_len). ENDIF. cl_o2_api_xsltdesc=>create_new_from_string( EXPORTING p_source = lv_source p_attr = ls_attributes IMPORTING p_obj = lo_xslt EXCEPTIONS action_cancelled = 1 error_occured = 2 not_authorized = 3 object_already_existing = 4 undefined_name = 5 OTHERS = 6 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from XSLT new, { sy-subrc }| ). ENDIF. lo_xslt->save( EXCEPTIONS action_cancelled = 1 error_occured = 2 object_invalid = 3 object_not_changeable = 4 permission_failure = 5 OTHERS = 6 ). IF sy-subrc <> 0. lo_xslt->set_changeable( abap_false ). " unlock zcx_abapgit_exception=>raise( |Error from XSLT save, { sy-subrc }| ). ENDIF. lo_xslt->set_changeable( abap_false ). zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_name TYPE cxsltdesc. lv_name = ms_item-obj_name. rv_bool = cl_o2_api_xsltdesc=>exists( lv_name ). rv_bool = boolc( rv_bool = '1' ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_xslt TYPE REF TO cl_o2_api_xsltdesc, lv_source TYPE string, ls_attributes TYPE o2xsltattr. lo_xslt = get( ). ls_attributes = lo_xslt->get_attributes( ). CLEAR: ls_attributes-author, ls_attributes-createdon, ls_attributes-changedby, ls_attributes-changedon, ls_attributes-devclass. io_xml->add( iv_name = 'ATTRIBUTES' ig_data = ls_attributes ). lv_source = lo_xslt->get_source_string( ). mo_files->add_string( iv_extra = 'source' iv_ext = 'xml' iv_string = lv_source ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_xinx IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). cl_wb_object_type=>get_key_components_from_id( EXPORTING p_key = |{ ms_item-obj_name }| p_external_id = swbm_c_type_ddic_db_tabxinx IMPORTING p_key_component1 = mv_name p_key_component2 = mv_id EXCEPTIONS too_many_key_components = 1 objecttype_not_existing = 2 OTHERS = 3 ). ASSERT sy-subrc = 0. ENDMETHOD. METHOD xinx_delete_docu. DATA: lv_docuid TYPE dokhl-id, lv_doctype TYPE dokhl-typ, lv_docname TYPE dokhl-object. lv_docname = iv_objname. lv_docname+30 = iv_id. CALL FUNCTION 'INTERN_DD_DOCU_ID_MATCH' EXPORTING p_trobjtype = c_objtype_extension_index IMPORTING p_docu_id = lv_docuid p_doctype = lv_doctype EXCEPTIONS illegal_type = 1 OTHERS = 2. IF sy-subrc <> 0. RETURN. ENDIF. CALL FUNCTION 'DOKU_DELETE_ALL' EXPORTING doku_id = lv_docuid doku_object = lv_docname doku_typ = lv_doctype suppress_authority = 'X' suppress_enqueue = 'X' suppress_transport = 'X' EXCEPTIONS no_docu_found = 1 OTHERS = 2. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE as4user FROM dd12l INTO rv_user WHERE sqltab = mv_name AND indexname = mv_id. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. " Reimplement FM RS_DD_INDX_DELETE as it calls the UI DATA: ls_enqueue TYPE ddenqs, lv_protname TYPE tstrf01-file, lv_del_concname LIKE ls_enqueue-objname, lv_concname TYPE rsdxx-objname, ls_transp_key TYPE trkey, ls_e071 TYPE e071, lv_clm_corrnum TYPE e070-trkorr. CONCATENATE mv_name '-' mv_id INTO lv_concname. ls_enqueue-objtype = c_objtype_extension_index. CALL FUNCTION 'INT_INDX_DEL_LOCK' EXPORTING i_trobjtype = ls_enqueue-objtype i_tabname = mv_name i_indexname = mv_id EXCEPTIONS not_executed = 1 error_occured = 2 permission_failure = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ls_enqueue-objname = mv_name. ls_enqueue-secname = mv_id. CALL FUNCTION 'RS_CORR_INSERT' EXPORTING object = ls_enqueue object_class = 'DICT' mode = 'DELETE' IMPORTING transport_key = ls_transp_key EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. " & was not deleted (correction entry not possible or canceled) MESSAGE s015(e2) WITH lv_concname INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'DD_LOGNPROT_NAME_GET' EXPORTING task = 'DEL' obj_type = ls_enqueue-objtype obj_name = ls_enqueue-objname ind_name = ls_enqueue-secname IMPORTING protname = lv_protname EXCEPTIONS input_error = 0. PERFORM logdelete IN PROGRAM rddu0001 USING lv_protname. lv_del_concname = ls_enqueue-objname. lv_del_concname+16 = ls_enqueue-secname. CALL FUNCTION 'DD_OBJ_DEL' EXPORTING object_name = lv_del_concname object_type = ls_enqueue-objtype del_state = 'M' EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. RETURN. ENDIF. CALL FUNCTION 'DD_DD_TO_E071' EXPORTING type = ls_enqueue-objtype name = ls_enqueue-objname id = ls_enqueue-secname IMPORTING obj_name = ls_e071-obj_name EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. " Internal error & in & (contact person in charge) MESSAGE i008(e2) WITH 'DD_DD_TO_E071' 'RS_DD_INDX_DELETE' INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. ls_e071-object = ls_enqueue-objtype. CALL FUNCTION 'RS_DELETE_FROM_WORKING_AREA' EXPORTING object = ls_e071-object obj_name = ls_e071-obj_name immediate = 'X' actualize_working_area = 'X'. xinx_delete_docu( iv_objname = mv_name iv_id = mv_id ). CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' EXPORTING object = ls_e071-obj_name operation = 'DELETE' type = c_objtype_extension_index. IF mv_id(1) CA 'YZ'. CALL FUNCTION 'CLM_INDX_MODIFICATION_DELETE' EXPORTING idxobj_name = ls_enqueue-objname idx_type = ls_enqueue-objtype idx_name = mv_id transport_key = ls_transp_key corrnum = lv_clm_corrnum. ENDIF. CALL FUNCTION 'RS_DD_DEQUEUE' EXPORTING objtype = ls_enqueue-objtype objname = ls_enqueue-objname secname = ls_enqueue-secname. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_extension_index TYPE ty_extension_index, lv_rc TYPE sy-subrc. io_xml->read( EXPORTING iv_name = 'XINX' CHANGING cg_data = ls_extension_index ). tadir_insert( iv_package ). corr_insert( iv_package ). CALL FUNCTION 'DDIF_INDX_PUT' EXPORTING name = mv_name id = mv_id dd12v_wa = ls_extension_index-dd12v TABLES dd17v_tab = ls_extension_index-t_dd17v EXCEPTIONS indx_not_found = 1 name_inconsistent = 2 indx_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from DDIF_INDX_PUT { sy-subrc }| ). ENDIF. CALL FUNCTION 'DDIF_INDX_ACTIVATE' EXPORTING name = mv_name id = mv_id IMPORTING rc = lv_rc EXCEPTIONS not_found = 1 put_failure = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from DDIF_INDX_ACTIVATE { sy-subrc }| ). ENDIF. IF lv_rc <> 0. zcx_abapgit_exception=>raise( |Cannot activate extension index { mv_id } of table { mv_name }| ). ENDIF. deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_xinx ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_dd12v TYPE dd12v. CALL FUNCTION 'DDIF_INDX_GET' EXPORTING name = mv_name id = mv_id IMPORTING dd12v_wa = ls_dd12v EXCEPTIONS illegal_input = 1 OTHERS = 2. rv_bool = boolc( ls_dd12v IS NOT INITIAL ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_extension_index TYPE ty_extension_index. CALL FUNCTION 'DDIF_INDX_GET' EXPORTING name = mv_name id = mv_id langu = mv_language IMPORTING dd12v_wa = ls_extension_index-dd12v TABLES dd17v_tab = ls_extension_index-t_dd17v EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from DDIF_INDX_GET { sy-subrc }| ). ENDIF. CLEAR: ls_extension_index-dd12v-as4user, ls_extension_index-dd12v-as4date, ls_extension_index-dd12v-as4time. io_xml->add( iv_name = 'XINX' ig_data = ls_extension_index ). serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_xinx ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_WEBI IMPLEMENTATION. METHOD handle_endpoint. DATA: ls_endpoint LIKE LINE OF is_webi-pvependpoint, li_endpoint TYPE REF TO if_ws_md_vif_endpoint_ref. FIELD-SYMBOLS: LIKE LINE OF is_webi-pvepfunction. READ TABLE is_webi-pvependpoint INDEX 1 INTO ls_endpoint. ASSERT sy-subrc = 0. IF mi_vi->has_endpoint_reference( sews_c_vif_version-all ) = abap_true. RETURN. ENDIF. li_endpoint = mi_vi->create_endpoint_reference( endpoint_type = ls_endpoint-endpointtype service_def_startpoint = ls_endpoint-def_start_pt auto_generated = ls_endpoint-auto_generated i_is_srvv = ls_endpoint-is_srvv ). IF ls_endpoint-endpointtype = 'BAPI'. * it looks like some special handling is needed when calling * set_data, and looking at the cluster data LS_ENDPOINT-CLUSTD zcx_abapgit_exception=>raise( 'todo, WEBI BAPI' ). ENDIF. * field ls_endpoint-endpointname does not exist in 702 READ TABLE is_webi-pvepfunction INDEX 1 ASSIGNING . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |WEBI { ms_item-obj_name }: couldn't detect endpoint name| ). ENDIF. li_endpoint->set_data( data_version = '1' data = -function ). ENDMETHOD. METHOD handle_function. DATA: li_parameter TYPE REF TO if_ws_md_vif_param, li_soap TYPE REF TO if_ws_md_soap_ext_func, li_fault TYPE REF TO if_ws_md_vif_fault, li_function TYPE REF TO if_ws_md_vif_func. FIELD-SYMBOLS: LIKE LINE OF is_webi-pvepfunction, LIKE LINE OF is_webi-pvepfuncsoapext, LIKE LINE OF is_webi-pvepfault, LIKE LINE OF is_webi-pvepparameter. LOOP AT is_webi-pvepfunction ASSIGNING . IF mi_vi->has_function( funcname = -function version = sews_c_vif_version-active ) = abap_true. CONTINUE. ENDIF. IF mi_vi->has_function( funcname = -function version = sews_c_vif_version-inactive ) = abap_true. li_function = mi_vi->get_function( funcname = -function version = sews_c_vif_version-inactive ). ELSE. li_function = mi_vi->create_function( funcname = -function mapped_name = -mappedname ). ENDIF. li_function->set_is_exposed( -is_exposed ). LOOP AT is_webi-pvepparameter ASSIGNING WHERE function = -function. li_parameter = handle_single_parameter( iv_name = -vepparam ii_function = li_function iv_parameter_type = -vepparamtype ). li_parameter->set_name_mapped_to( -mappedname ). li_parameter->set_is_exposed( -is_exposed ). li_parameter->set_is_optional( -is_optional ). li_parameter->set_default_value( -default_value ). li_parameter->set_initial( -is_initial ). li_parameter->set_type( -typename ). ENDLOOP. LOOP AT is_webi-pvepfuncsoapext ASSIGNING WHERE function = -function. IF li_function->has_soap_extension_function( 'I' ) = abap_true. li_function->delete_soap_extension_function( ). ENDIF. li_soap = li_function->create_soap_extension_function( ). li_soap->set_soap_request_name( -requestname ). li_soap->set_soap_response_name( -responsename ). li_soap->set_namespace( -namespace ). ENDLOOP. LOOP AT is_webi-pvepfault ASSIGNING WHERE function = -function. li_fault = li_function->create_fault( -fault ). li_fault->set_name_mapped_to( -mappedname ). li_fault->set_detail( -detail ). ENDLOOP. ENDLOOP. ENDMETHOD. METHOD handle_single_parameter. CONSTANTS: BEGIN OF lc_parameter_type, import TYPE vepparamtype VALUE 'I', export TYPE vepparamtype VALUE 'O', END OF lc_parameter_type. CASE iv_parameter_type. WHEN lc_parameter_type-import. ri_parameter = ii_function->get_incoming_parameter( parameter_name = iv_name version = 'I' ). IF ri_parameter IS BOUND. ii_function->delete_incoming_parameter( ri_parameter ). ENDIF. ri_parameter = ii_function->create_incoming_parameter( iv_name ). WHEN lc_parameter_type-export. ri_parameter = ii_function->get_outgoing_parameter( parameter_name = iv_name version = 'I' ). IF ri_parameter IS BOUND. ii_function->delete_outgoing_parameter( parameter = ri_parameter ). ENDIF. ri_parameter = ii_function->create_outgoing_parameter( iv_name ). WHEN OTHERS. ASSERT 0 = 1. ENDCASE. ENDMETHOD. METHOD handle_soap. DATA: li_soap TYPE REF TO if_ws_md_soap_ext_virtinfc, ls_soap LIKE LINE OF is_webi-pvepvisoapext. READ TABLE is_webi-pvepvisoapext INDEX 1 INTO ls_soap. ASSERT sy-subrc = 0. IF mi_vi->has_soap_extension_virtinfc( sews_c_vif_version-active ) = abap_true. RETURN. ENDIF. IF mi_vi->has_soap_extension_virtinfc( sews_c_vif_version-inactive ) = abap_true. li_soap = mi_vi->get_soap_extension_virtinfc( sews_c_vif_version-inactive ). ELSE. li_soap = mi_vi->create_soap_extension_virtinfc( ls_soap-soap_appl_uri ). ENDIF. li_soap->set_namespace( ls_soap-namespace ). ENDMETHOD. METHOD handle_types. DATA: lv_index TYPE i, li_soap TYPE REF TO if_ws_md_soap_extension_type, li_struc TYPE REF TO if_ws_md_vif_struc_type, li_field TYPE REF TO if_ws_md_vif_field, li_table TYPE REF TO if_ws_md_vif_table_type, li_elem TYPE REF TO if_ws_md_vif_elem_type. FIELD-SYMBOLS: LIKE LINE OF is_webi-pvepelemtype, LIKE LINE OF is_webi-pveptabletype, LIKE LINE OF is_webi-pveptypesoapext, LIKE LINE OF is_webi-pvepstrutype. LOOP AT is_webi-pvepelemtype ASSIGNING . li_elem = mi_vi->create_type_as_elementary( -typename ). li_elem->set_built_in_type( -build_in_type ). li_elem->set_decimals( -decimals ). li_elem->set_kind( -kind ). li_elem->set_length( -length ). li_elem->set_signed( -signed ). li_elem->set_abaptype( -abaptype ). IF li_elem->if_ws_md_vif_type~has_soap_extension_type( sews_c_vif_version-all ) = abap_false. READ TABLE is_webi-pveptypesoapext ASSIGNING WITH KEY typename = -typename. IF sy-subrc = 0. li_soap = li_elem->if_ws_md_vif_type~create_soap_extension_type( ). li_soap->set_namespace( -namespace ). ENDIF. ENDIF. ENDLOOP. LOOP AT is_webi-pvepstrutype ASSIGNING . lv_index = sy-tabix. li_struc = mi_vi->create_type_as_structure( -typename ). IF li_struc->has_field( field_pos = -fieldpos version = sews_c_vif_version-active ) = abap_true. CONTINUE. ENDIF. li_field = li_struc->create_field( field_name = -fieldname fieldpos = -fieldpos ). li_field->set_type( mi_vi->get_type( typename = -typeref version = sews_c_vif_version-inactive ) ). IF lv_index = 1 AND li_struc->if_ws_md_vif_type~has_soap_extension_type( sews_c_vif_version-all ) = abap_false. READ TABLE is_webi-pveptypesoapext ASSIGNING WITH KEY typename = -typename. IF sy-subrc = 0. li_soap = li_struc->if_ws_md_vif_type~create_soap_extension_type( ). li_soap->set_namespace( -namespace ). ENDIF. ENDIF. ENDLOOP. LOOP AT is_webi-pveptabletype ASSIGNING . li_table = mi_vi->create_type_as_table( -typename ). li_table->set_line_type( mi_vi->get_type( typename = -typeref version = sews_c_vif_version-inactive ) ). IF li_table->if_ws_md_vif_type~has_soap_extension_type( sews_c_vif_version-all ) = abap_false. READ TABLE is_webi-pveptypesoapext ASSIGNING WITH KEY typename = -typename. IF sy-subrc = 0. li_soap = li_table->if_ws_md_vif_type~create_soap_extension_type( ). li_soap->set_namespace( -namespace ). ENDIF. ENDIF. ENDLOOP. ENDMETHOD. METHOD sort. SORT cs_webi-pvepheader BY vepname version. SORT cs_webi-pvepfunction BY vepname version function. SORT cs_webi-pvepfault BY vepname version function fault. SORT cs_webi-pvepparameter BY vepname version function vepparam vepparamtype. SORT cs_webi-pveptype BY vepname version typename. SORT cs_webi-pvepelemtype BY vepname version typename. SORT cs_webi-pveptabletype BY vepname version typename. SORT cs_webi-pvepstrutype BY vepname version typename fieldpos. SORT cs_webi-pveptypesoapext BY vepname version typename. SORT cs_webi-pvepeletypsoap BY vepname version typename assign_type assign_data1 assign_data2. SORT cs_webi-pveptabtypsoap BY vepname version typename. SORT cs_webi-pvepfuncsoapext BY vepname version function. SORT cs_webi-pvepfieldref BY vepname version function vepparam vepparamtype strucid fieldname. SORT cs_webi-pvependpoint BY relid vepname version sortfield. SORT cs_webi-pvepvisoapext BY vepname version. SORT cs_webi-pvepparasoapext BY vepname version function vepparam vepparamtype. SORT cs_webi-pwsheader BY wsname version. SORT cs_webi-pwssoapprop BY wsname version feature soapapp funcref propnum. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changedby FROM vepheader INTO rv_user WHERE vepname = ms_item-obj_name AND version = 'A'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_name TYPE vepname, lo_vif TYPE REF TO cl_ws_md_vif_root. lv_name = ms_item-obj_name. CREATE OBJECT lo_vif. TRY. lo_vif->if_ws_md_vif_root~delete_virtual_interface( lv_name ). CATCH cx_ws_md_exception. zcx_abapgit_exception=>raise( 'error deleting WEBI' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_webi TYPE ty_webi, lv_name TYPE vepname, ls_header LIKE LINE OF ls_webi-pvepheader, lx_root TYPE REF TO cx_root, lv_exists TYPE abap_bool, li_root TYPE REF TO if_ws_md_vif_root, ls_endpoint LIKE LINE OF ls_webi-pvependpoint. io_xml->read( EXPORTING iv_name = 'WEBI' CHANGING cg_data = ls_webi ). lv_name = ms_item-obj_name. READ TABLE ls_webi-pvependpoint INDEX 1 INTO ls_endpoint. ASSERT sy-subrc = 0. IF ls_endpoint-auto_generated = abap_true. " handled by SPRX. RETURN. ENDIF. READ TABLE ls_webi-pvepheader INDEX 1 INTO ls_header. ASSERT sy-subrc = 0. lv_exists = cl_ws_md_vif_root=>check_existence_by_vif_name( name = lv_name i_version = sews_c_vif_version-all ). li_root = cl_ws_md_factory=>get_vif_root( ). TRY. IF lv_exists = abap_false. mi_vi = li_root->create_virtual_interface( name = lv_name nameext = ls_header-vepnameext ). ELSE. mi_vi = li_root->get_virtual_interface( lv_name ). mi_vi->if_ws_md_lockable_object~lock( ). ENDIF. mi_vi->set_short_text( ls_webi-veptext ). handle_endpoint( ls_webi ). handle_types( ls_webi ). handle_function( ls_webi ). handle_soap( ls_webi ). tadir_insert( iv_package ). mi_vi->if_ws_md_lockable_object~save( ). mi_vi->if_ws_md_lockable_object~unlock( ). CATCH cx_ws_md_exception INTO lx_root. TRY. mi_vi->if_ws_md_lockable_object~unlock( ). CATCH cx_ws_md_exception ##NO_HANDLER. ENDTRY. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). zcl_abapgit_sotr_handler=>create_sotr( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_name TYPE vepname. DATA lv_generated TYPE abap_bool. lv_name = ms_item-obj_name. " Check if service is generated by proxy SELECT SINGLE auto_generated FROM vependpoint INTO lv_generated WHERE vepname = lv_name AND version = sews_c_vif_version-active. IF sy-subrc = 0 AND lv_generated = abap_true. RETURN. ENDIF. rv_bool = cl_ws_md_vif_root=>check_existence_by_vif_name( name = lv_name i_version = sews_c_vif_version-all ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_webi TYPE ty_webi, lx_error TYPE REF TO cx_ws_md_exception, lt_modilog TYPE STANDARD TABLE OF smodilog WITH DEFAULT KEY, li_vi TYPE REF TO if_ws_md_vif, lv_name TYPE vepname. FIELD-SYMBOLS: LIKE LINE OF ls_webi-pvepheader, LIKE LINE OF ls_webi-pvependpoint, TYPE wsheader. CALL FUNCTION 'WEBI_GET_OBJECT' EXPORTING webiname = ms_item-obj_name TABLES psmodilog = lt_modilog pvepheader = ls_webi-pvepheader pvepfunction = ls_webi-pvepfunction pvepfault = ls_webi-pvepfault pvepparameter = ls_webi-pvepparameter pveptype = ls_webi-pveptype pvepelemtype = ls_webi-pvepelemtype pveptabletype = ls_webi-pveptabletype pvepstrutype = ls_webi-pvepstrutype pveptypesoapext = ls_webi-pveptypesoapext pvepeletypsoap = ls_webi-pvepeletypsoap pveptabtypsoap = ls_webi-pveptabtypsoap pvepfuncsoapext = ls_webi-pvepfuncsoapext pvepfieldref = ls_webi-pvepfieldref pvependpoint = ls_webi-pvependpoint pvepvisoapext = ls_webi-pvepvisoapext pvepparasoapext = ls_webi-pvepparasoapext pwsheader = ls_webi-pwsheader pwssoapprop = ls_webi-pwssoapprop EXCEPTIONS version_not_found = 1 webi_not_exist = 2 OTHERS = 3. IF sy-subrc = 1. " no active version RETURN. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. sort( CHANGING cs_webi = ls_webi ). lv_name = ms_item-obj_name. TRY. li_vi = cl_ws_md_factory=>get_vif_root( )->get_virtual_interface( lv_name ). ls_webi-veptext = li_vi->get_short_text( sews_c_vif_version-active ). CATCH cx_ws_md_exception INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. LOOP AT ls_webi-pvepheader ASSIGNING . CLEAR -author. CLEAR -createdon. CLEAR -changedby. CLEAR -changedon. CLEAR -ctime. CLEAR -text_id. CLEAR -utime. CLEAR -wsint_version. ENDLOOP. LOOP AT ls_webi-pvependpoint ASSIGNING . CLEAR -clustd. ENDLOOP. LOOP AT ls_webi-pwsheader ASSIGNING . CLEAR: -author, -createdon, -changedby, -changedon, -ctime, -utime. ENDLOOP. io_xml->add( iv_name = 'WEBI' ig_data = ls_webi ). zcl_abapgit_sotr_handler=>read_sotr( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params io_xml = io_xml ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_WDYN IMPLEMENTATION. METHOD add_fm_exception. DATA: ls_exception LIKE LINE OF ct_exception. ls_exception-name = iv_name. ls_exception-value = iv_value. INSERT ls_exception INTO TABLE ct_exception. ENDMETHOD. METHOD add_fm_param_exporting. DATA: ls_param LIKE LINE OF ct_param. ls_param-kind = abap_func_exporting. ls_param-name = iv_name. GET REFERENCE OF ig_value INTO ls_param-value. INSERT ls_param INTO TABLE ct_param. ENDMETHOD. METHOD add_fm_param_tables. DATA: ls_param LIKE LINE OF ct_param. ls_param-kind = abap_func_tables. ls_param-name = iv_name. GET REFERENCE OF ct_value INTO ls_param-value. INSERT ls_param INTO TABLE ct_param. ENDMETHOD. METHOD add_with_inactive_parts. DATA: lv_obj_name TYPE trobj_name, lv_object TYPE trobjtype, lt_objects TYPE dwinactiv_tab. FIELD-SYMBOLS: LIKE LINE OF lt_objects. lv_obj_name = ms_item-obj_name. lv_object = ms_item-obj_type. CALL FUNCTION 'RS_INACTIVE_OBJECTS_IN_OBJECT' EXPORTING obj_name = lv_obj_name object = lv_object TABLES inactive_objects = lt_objects EXCEPTIONS object_not_found = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. LOOP AT lt_objects ASSIGNING . zcl_abapgit_objects_activation=>add( iv_type = -object iv_name = -obj_name ). ENDLOOP. ENDMETHOD. METHOD delta_controller. DATA: li_controller TYPE REF TO if_wdy_md_controller, lx_error TYPE REF TO cx_wdy_md_exception, lv_found TYPE abap_bool, ls_key TYPE wdy_md_controller_key, ls_obj_new TYPE svrs2_versionable_object, ls_obj_old TYPE svrs2_versionable_object. FIELD-SYMBOLS: LIKE LINE OF mt_components, LIKE LINE OF mt_sources, TYPE ANY TABLE, TYPE ANY TABLE, TYPE ANY TABLE, TYPE ANY TABLE. ls_key-component_name = is_controller-definition-component_name. ls_key-controller_name = is_controller-definition-controller_name. lv_found = cl_wdy_md_controller=>check_existency( component_name = ls_key-component_name controller_name = ls_key-controller_name ). IF lv_found = abap_false. TRY. li_controller ?= cl_wdy_md_controller=>create_complete( component_name = ls_key-component_name controller_name = ls_key-controller_name controller_type = is_controller-definition-controller_type ). li_controller->save_to_database( ). li_controller->unlock( ). CATCH cx_wdy_md_exception INTO lx_error. zcx_abapgit_exception=>raise( |Error creating dummy controller: { lx_error->get_text( ) }| ). ENDTRY. ENDIF. ls_obj_new-objtype = wdyn_limu_component_controller. ls_obj_new-objname = ls_key. ls_obj_old-objtype = wdyn_limu_component_controller. ls_obj_old-objname = ls_key. APPEND is_controller-definition TO ls_obj_old-wdyc-defin. LOOP AT mt_components ASSIGNING WHERE component_name = ls_key-component_name AND controller_name = ls_key-controller_name. APPEND TO ls_obj_old-wdyc-ccomp. ENDLOOP. LOOP AT mt_sources ASSIGNING WHERE component_name = ls_key-component_name AND controller_name = ls_key-controller_name. APPEND TO ls_obj_old-wdyc-ccoms. ENDLOOP. ls_obj_old-wdyc-descr = is_controller-descriptions. ls_obj_old-wdyc-cusag = is_controller-controller_usages. ls_obj_old-wdyc-ccomt = is_controller-controller_component_texts. ls_obj_old-wdyc-cpara = is_controller-controller_parameters. ls_obj_old-wdyc-cpart = is_controller-controller_parameter_texts. ls_obj_old-wdyc-cnode = is_controller-context_nodes. ls_obj_old-wdyc-cattr = is_controller-context_attributes. ls_obj_old-wdyc-cmapp = is_controller-context_mappings. * Version 702 doesn't have these two attributes so we * use them dynamically for downward compatibility ASSIGN COMPONENT 'CONTROLLER_EXCEPTIONS' OF STRUCTURE is_controller TO . IF sy-subrc = 0. ASSIGN COMPONENT 'EXCP' OF STRUCTURE ls_obj_old-wdyc TO . IF sy-subrc = 0. = . ENDIF. ENDIF. ASSIGN COMPONENT 'CONTROLLER_EXCEPTIONS_TEXTS' OF STRUCTURE is_controller TO . IF sy-subrc = 0. ASSIGN COMPONENT 'EXCPT' OF STRUCTURE ls_obj_old-wdyc TO . IF sy-subrc = 0. = . ENDIF. ENDIF. ls_obj_old-wdyc-fgrps = is_controller-fieldgroups. CALL FUNCTION 'SVRS_MAKE_OBJECT_DELTA' EXPORTING obj_old = ls_obj_new obj_new = ls_obj_old CHANGING delta = rs_delta EXCEPTIONS inconsistent_objects = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from SVRS_MAKE_OBJECT_DELTA' ). ENDIF. ENDMETHOD. METHOD delta_definition. DATA: ls_key TYPE wdy_md_component_key, lv_found TYPE abap_bool, ls_obj_new TYPE svrs2_versionable_object, li_component TYPE REF TO if_wdy_md_component, lx_error TYPE REF TO cx_wdy_md_exception, ls_obj_old TYPE svrs2_versionable_object. ls_key-component_name = is_definition-definition-component_name. lv_found = cl_wdy_md_component=>check_existency( ls_key-component_name ). IF lv_found = abap_false. TRY. cl_wdy_md_component=>create_complete( EXPORTING name = ls_key-component_name IMPORTING component = li_component CHANGING devclass = iv_package ). li_component->save_to_database( ). li_component->unlock( ). CATCH cx_wdy_md_exception INTO lx_error. zcx_abapgit_exception=>raise( |Error creating dummy component: { lx_error->get_text( ) }| ). ENDTRY. ENDIF. ls_obj_new-objtype = wdyn_limu_component_definition. ls_obj_new-objname = ls_key-component_name. ls_obj_old-objtype = wdyn_limu_component_definition. ls_obj_old-objname = ls_key-component_name. APPEND is_definition-definition TO ls_obj_old-wdyd-defin. ls_obj_old-wdyd-descr = is_definition-descriptions. ls_obj_old-wdyd-cusag = is_definition-component_usages. ls_obj_old-wdyd-intrf = is_definition-interface_implementings. ls_obj_old-wdyd-libra = is_definition-library_usages. ls_obj_old-wdyd-ctuse = is_definition-ext_ctlr_usages. ls_obj_old-wdyd-ctmap = is_definition-ext_ctx_mappings. CALL FUNCTION 'SVRS_MAKE_OBJECT_DELTA' EXPORTING obj_old = ls_obj_new obj_new = ls_obj_old CHANGING delta = rs_delta EXCEPTIONS inconsistent_objects = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from SVRS_MAKE_OBJECT_DELTA' ). ENDIF. ENDMETHOD. METHOD delta_view. DATA: ls_key TYPE wdy_md_view_key, ls_obj_new TYPE svrs2_versionable_object, ls_obj_old TYPE svrs2_versionable_object, lv_found TYPE abap_bool, lx_error TYPE REF TO cx_wdy_md_exception, li_view TYPE REF TO if_wdy_md_abstract_view. FIELD-SYMBOLS: LIKE LINE OF ls_obj_old-wdyv-defin. ls_key-component_name = is_view-definition-component_name. ls_key-view_name = is_view-definition-view_name. lv_found = cl_wdy_md_abstract_view=>check_existency( component_name = ls_key-component_name name = ls_key-view_name ). IF lv_found = abap_false. TRY. li_view = cl_wdy_md_abstract_view=>create( component_name = is_view-definition-component_name view_name = is_view-definition-view_name type = is_view-definition-type ). li_view->save_to_database( ). li_view->unlock( ). CATCH cx_wdy_md_exception INTO lx_error. zcx_abapgit_exception=>raise( |Error creating dummy view: { lx_error->get_text( ) }| ). ENDTRY. ENDIF. ls_obj_new-objtype = wdyn_limu_component_view. ls_obj_new-objname = ls_key. ls_obj_old-objtype = wdyn_limu_component_view. ls_obj_old-objname = ls_key. APPEND INITIAL LINE TO ls_obj_old-wdyv-defin ASSIGNING . MOVE-CORRESPONDING is_view-definition TO . ls_obj_old-wdyv-descr = is_view-descriptions. ls_obj_old-wdyv-vcont = is_view-view_containers. ls_obj_old-wdyv-vcntt = is_view-view_container_texts. ls_obj_old-wdyv-ibplg = is_view-iobound_plugs. ls_obj_old-wdyv-ibplt = is_view-iobound_plug_texts. ls_obj_old-wdyv-plpar = is_view-plug_parameters. ls_obj_old-wdyv-plprt = is_view-plug_parameter_texts. ls_obj_old-wdyv-uiele = is_view-ui_elements. ls_obj_old-wdyv-uicon = is_view-ui_context_bindings. ls_obj_old-wdyv-uievt = is_view-ui_event_bindings. ls_obj_old-wdyv-uiddc = is_view-ui_ddic_bindings. ls_obj_old-wdyv-uiprp = is_view-ui_properties. ls_obj_old-wdyv-navil = is_view-navigation_links. ls_obj_old-wdyv-navit = is_view-navigation_target_refs. ls_obj_old-wdyv-vshno = is_view-vsh_nodes. ls_obj_old-wdyv-vshpl = is_view-vsh_placeholders. ls_obj_old-wdyv-views = is_view-viewset_properties. CALL FUNCTION 'SVRS_MAKE_OBJECT_DELTA' EXPORTING obj_old = ls_obj_new obj_new = ls_obj_old CHANGING delta = rs_delta EXCEPTIONS inconsistent_objects = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from SVRS_MAKE_OBJECT_DELTA' ). ENDIF. ENDMETHOD. METHOD get_limu_objects. DATA: lv_name TYPE wdy_component_name. lv_name = ms_item-obj_name. CALL FUNCTION 'WDYN_GET_LIMU_OBJECTS' EXPORTING component_name = lv_name IMPORTING limu_objects = rt_objects. ENDMETHOD. METHOD read. DATA: lt_objects TYPE wdy_md_transport_keys, ls_controller_key TYPE wdy_md_controller_key, ls_component_key TYPE wdy_md_component_key, ls_view_key TYPE wdy_md_view_key. FIELD-SYMBOLS: LIKE LINE OF lt_objects, LIKE LINE OF rs_component-ctlr_metadata, LIKE LINE OF rs_component-view_metadata, TYPE ANY TABLE, TYPE ANY TABLE. CLEAR mt_components. CLEAR mt_sources. lt_objects = get_limu_objects( ). LOOP AT lt_objects ASSIGNING . CASE -sub_type. WHEN wdyn_limu_component_controller. ls_controller_key = -sub_name. APPEND read_controller( ls_controller_key ) TO rs_component-ctlr_metadata. WHEN wdyn_limu_component_definition. ls_component_key = -sub_name. rs_component-comp_metadata = read_definition( ls_component_key ). WHEN wdyn_limu_component_view. ls_view_key = -sub_name. APPEND read_view( ls_view_key ) TO rs_component-view_metadata. WHEN OTHERS. ASSERT 0 = 1. ENDCASE. ENDLOOP. SORT rs_component-ctlr_metadata BY definition-component_name ASCENDING definition-controller_name ASCENDING. LOOP AT rs_component-ctlr_metadata ASSIGNING . SORT -descriptions. SORT -controller_usages. SORT -controller_components. SORT -controller_component_texts. SORT -controller_parameters. SORT -controller_parameter_texts. SORT -context_nodes. SORT -context_attributes. SORT -context_mappings. SORT -fieldgroups. * Version 702 doesn't have these two attributes so we * use them dynamically for downward compatibility ASSIGN COMPONENT 'CONTROLLER_EXCEPTIONS' OF STRUCTURE TO . IF sy-subrc = 0. SORT . ENDIF. ASSIGN COMPONENT 'CONTROLLER_EXCEPTION_TEXTS' OF STRUCTURE TO . IF sy-subrc = 0. SORT . ENDIF. ENDLOOP. SORT rs_component-view_metadata BY definition-component_name ASCENDING definition-view_name ASCENDING. LOOP AT rs_component-view_metadata ASSIGNING . SORT -descriptions. SORT -view_containers. SORT -view_container_texts. SORT -iobound_plugs. SORT -iobound_plug_texts. SORT -plug_parameters. SORT -plug_parameter_texts. SORT -ui_elements. SORT -ui_context_bindings. SORT -ui_event_bindings. SORT -ui_ddic_bindings. SORT -ui_properties. SORT -navigation_links. SORT -navigation_target_refs. SORT -vsh_nodes. SORT -vsh_placeholders. SORT -viewset_properties. ENDLOOP. SORT mt_components BY component_name ASCENDING controller_name ASCENDING cmpname ASCENDING. SORT mt_sources BY component_name ASCENDING controller_name ASCENDING cmpname ASCENDING line_number ASCENDING. ENDMETHOD. METHOD read_controller. DATA: lt_components TYPE TABLE OF wdy_ctlr_compo_vrs, lt_sources TYPE TABLE OF wdy_ctlr_compo_source_vrs, lt_definition TYPE TABLE OF wdy_controller, lt_psmodilog TYPE TABLE OF smodilog, lt_psmodisrc TYPE TABLE OF smodisrc, lt_fm_param TYPE abap_func_parmbind_tab, lt_fm_exception TYPE abap_func_excpbind_tab. FIELD-SYMBOLS: TYPE ANY TABLE, TYPE ANY TABLE. * Calling FM dynamically because version 702 has less parameters * FM parameters add_fm_param_exporting( EXPORTING iv_name = 'CONTROLLER_KEY' ig_value = is_key CHANGING ct_param = lt_fm_param ). add_fm_param_exporting( EXPORTING iv_name = 'GET_ALL_TRANSLATIONS' ig_value = abap_false CHANGING ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'DEFINITION' CHANGING ct_value = lt_definition ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'DESCRIPTIONS' CHANGING ct_value = rs_controller-descriptions ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_USAGES' CHANGING ct_value = rs_controller-controller_usages ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_COMPONENTS' CHANGING ct_value = lt_components ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_COMPONENT_SOURCES' CHANGING ct_value = lt_sources ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_COMPONENT_TEXTS' CHANGING ct_value = rs_controller-controller_component_texts ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_PARAMETERS' CHANGING ct_value = rs_controller-controller_parameters ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_PARAMETER_TEXTS' CHANGING ct_value = rs_controller-controller_parameter_texts ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'CONTEXT_NODES' CHANGING ct_value = rs_controller-context_nodes ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'CONTEXT_ATTRIBUTES' CHANGING ct_value = rs_controller-context_attributes ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'CONTEXT_MAPPINGS' CHANGING ct_value = rs_controller-context_mappings ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'FIELDGROUPS' CHANGING ct_value = rs_controller-fieldgroups ct_param = lt_fm_param ). * Version 702 doesn't have these two attributes so we * use them dynamically for downward compatibility ASSIGN COMPONENT 'CONTROLLER_EXCEPTIONS' OF STRUCTURE rs_controller TO . IF sy-subrc = 0. add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_EXCEPTIONS' CHANGING ct_value = ct_param = lt_fm_param ). ENDIF. ASSIGN COMPONENT 'CONTROLLER_EXCEPTION_TEXTS' OF STRUCTURE rs_controller TO . IF sy-subrc = 0. add_fm_param_tables( EXPORTING iv_name = 'CONTROLLER_EXCEPTION_TEXTS' CHANGING ct_value = ct_param = lt_fm_param ). ENDIF. add_fm_param_tables( EXPORTING iv_name = 'PSMODILOG' CHANGING ct_value = lt_psmodilog ct_param = lt_fm_param ). add_fm_param_tables( EXPORTING iv_name = 'PSMODISRC' CHANGING ct_value = lt_psmodisrc ct_param = lt_fm_param ). * FM exceptions add_fm_exception( EXPORTING iv_name = 'NOT_EXISTING' iv_value = 1 CHANGING ct_exception = lt_fm_exception ). add_fm_exception( EXPORTING iv_name = 'OTHERS' iv_value = 2 CHANGING ct_exception = lt_fm_exception ). CALL FUNCTION 'WDYC_GET_OBJECT' PARAMETER-TABLE lt_fm_param EXCEPTION-TABLE lt_fm_exception. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from WDYC_GET_OBJECT' ). ENDIF. APPEND LINES OF lt_components TO mt_components. APPEND LINES OF lt_sources TO mt_sources. READ TABLE lt_definition INDEX 1 INTO rs_controller-definition. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'WDYC, definition not found' ). ENDIF. CLEAR: rs_controller-definition-author, rs_controller-definition-createdon, rs_controller-definition-changedby, rs_controller-definition-changedon. ENDMETHOD. METHOD read_definition. DATA: lt_definition TYPE TABLE OF wdy_component, lt_psmodilog TYPE TABLE OF smodilog, lt_psmodisrc TYPE TABLE OF smodisrc. CALL FUNCTION 'WDYD_GET_OBJECT' EXPORTING component_key = is_key get_all_translations = abap_false TABLES definition = lt_definition descriptions = rs_definition-descriptions component_usages = rs_definition-component_usages interface_implementings = rs_definition-interface_implementings library_usages = rs_definition-library_usages ext_ctlr_usages = rs_definition-ext_ctlr_usages ext_ctx_mappings = rs_definition-ext_ctx_mappings psmodilog = lt_psmodilog " not optional in all versions psmodisrc = lt_psmodisrc " not optional in all versions EXCEPTIONS not_existing = 1 OTHERS = 2. IF sy-subrc = 1. RETURN. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from WDYD_GET_OBJECT' ). ENDIF. READ TABLE lt_definition INDEX 1 INTO rs_definition-definition. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'WDYD, definition not found' ). ENDIF. CLEAR: rs_definition-definition-author, rs_definition-definition-createdon, rs_definition-definition-changedby, rs_definition-definition-changedon, rs_definition-definition-gendate, rs_definition-definition-gentime. ENDMETHOD. METHOD read_view. DATA: lt_definition TYPE TABLE OF wdy_view_vrs, lt_psmodilog TYPE TABLE OF smodilog, lt_psmodisrc TYPE TABLE OF smodisrc. FIELD-SYMBOLS: LIKE LINE OF lt_definition. CALL FUNCTION 'WDYV_GET_OBJECT' EXPORTING view_key = is_key get_all_translations = abap_false TABLES definition = lt_definition descriptions = rs_view-descriptions view_containers = rs_view-view_containers view_container_texts = rs_view-view_container_texts iobound_plugs = rs_view-iobound_plugs iobound_plug_texts = rs_view-iobound_plug_texts plug_parameters = rs_view-plug_parameters plug_parameter_texts = rs_view-plug_parameter_texts ui_elements = rs_view-ui_elements ui_context_bindings = rs_view-ui_context_bindings ui_event_bindings = rs_view-ui_event_bindings ui_ddic_bindings = rs_view-ui_ddic_bindings ui_properties = rs_view-ui_properties navigation_links = rs_view-navigation_links navigation_target_refs = rs_view-navigation_target_refs vsh_nodes = rs_view-vsh_nodes vsh_placeholders = rs_view-vsh_placeholders viewset_properties = rs_view-viewset_properties psmodilog = lt_psmodilog psmodisrc = lt_psmodisrc EXCEPTIONS not_existing = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from WDYV_GET_OBJECT' ). ENDIF. READ TABLE lt_definition INDEX 1 ASSIGNING . ASSERT sy-subrc = 0. MOVE-CORRESPONDING TO rs_view-definition. CLEAR: rs_view-definition-author, rs_view-definition-createdon, rs_view-definition-changedby, rs_view-definition-changedon. ENDMETHOD. METHOD recover_controller. DATA: ls_key TYPE wdy_controller_key, lv_corrnr TYPE trkorr, lx_error TYPE REF TO cx_wdy_md_exception, ls_delta TYPE svrs2_xversionable_object. ls_delta = delta_controller( is_controller ). ls_key-component_name = is_controller-definition-component_name. ls_key-controller_name = is_controller-definition-controller_name. TRY. cl_wdy_md_controller=>recover_version( EXPORTING controller_key = ls_key delta = ls_delta-wdyc CHANGING corrnr = lv_corrnr ). CATCH cx_wdy_md_exception INTO lx_error. zcx_abapgit_exception=>raise( |Error recovering version of controller: { lx_error->get_text( ) }| ). ENDTRY. ENDMETHOD. METHOD recover_definition. DATA: ls_key TYPE wdy_md_component_key, lv_corrnr TYPE trkorr, lx_error TYPE REF TO cx_wdy_md_exception, ls_delta TYPE svrs2_xversionable_object. ls_delta = delta_definition( is_definition = is_definition iv_package = iv_package ). ls_key-component_name = is_definition-definition-component_name. TRY. cl_wdy_md_component=>recover_version( EXPORTING component_key = ls_key delta = ls_delta-wdyd CHANGING corrnr = lv_corrnr ). CATCH cx_wdy_md_exception INTO lx_error. zcx_abapgit_exception=>raise( |Error recovering version of component: { lx_error->get_text( ) }| ). ENDTRY. ENDMETHOD. METHOD recover_view. DATA: ls_key TYPE wdy_md_view_key, lv_corrnr TYPE trkorr, lx_error TYPE REF TO cx_wdy_md_exception, ls_delta TYPE svrs2_xversionable_object. ls_delta = delta_view( is_view ). ls_key-component_name = is_view-definition-component_name. ls_key-view_name = is_view-definition-view_name. TRY. cl_wdy_md_abstract_view=>recover_version( EXPORTING view_key = ls_key delta = ls_delta-wdyv CHANGING corrnr = lv_corrnr ). CATCH cx_wdy_md_exception INTO lx_error. zcx_abapgit_exception=>raise( |Error recovering version of abstract view: { lx_error->get_text( ) }| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changedby FROM wdy_component INTO rv_user WHERE component_name = ms_item-obj_name AND version = 'A'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_component TYPE REF TO cl_wdy_wb_component, lo_request TYPE REF TO cl_wb_request, li_state TYPE REF TO if_wb_program_state, lv_object_name TYPE seu_objkey. CREATE OBJECT lo_component. lv_object_name = ms_item-obj_name. CREATE OBJECT lo_request EXPORTING p_object_type = 'YC' p_object_name = lv_object_name p_operation = swbm_c_op_delete_no_dialog. lo_component->if_wb_program~process_wb_request( p_wb_request = lo_request p_wb_program_state = li_state ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_component TYPE wdy_component_metadata, ls_description TYPE wdy_ext_ctx_map. FIELD-SYMBOLS: LIKE LINE OF ls_component-view_metadata, LIKE LINE OF ls_component-ctlr_metadata. io_xml->read( EXPORTING iv_name = 'COMPONENT' CHANGING cg_data = ls_component ). io_xml->read( EXPORTING iv_name = 'COMPONENTS' CHANGING cg_data = mt_components ). io_xml->read( EXPORTING iv_name = 'SOURCES' CHANGING cg_data = mt_sources ). ls_component-comp_metadata-definition-author = sy-uname. ls_component-comp_metadata-definition-createdon = sy-datum. recover_definition( is_definition = ls_component-comp_metadata iv_package = iv_package ). LOOP AT ls_component-ctlr_metadata ASSIGNING . -definition-author = sy-uname. -definition-createdon = sy-datum. recover_controller( ). ENDLOOP. LOOP AT ls_component-view_metadata ASSIGNING . -definition-author = sy-uname. -definition-createdon = sy-datum. recover_view( ). ENDLOOP. READ TABLE ls_component-comp_metadata-descriptions INTO ls_description INDEX 1. IF sy-subrc = 0. zcl_abapgit_sotr_handler=>create_sotr( iv_package = iv_package io_xml = io_xml ). ENDIF. add_with_inactive_parts( ). deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_wd ). deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_wc iv_longtext_name = c_longtext_name_wc ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_component_name TYPE wdy_component-component_name. SELECT SINGLE component_name FROM wdy_component INTO lv_component_name WHERE component_name = ms_item-obj_name. "#EC CI_GENBUFF rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_component TYPE wdy_component_metadata, ls_comp TYPE wdy_ctlr_compo_vrs, lv_object TYPE dokil-object, lt_object TYPE STANDARD TABLE OF dokil-object WITH DEFAULT KEY, lt_dokil TYPE STANDARD TABLE OF dokil WITH DEFAULT KEY, ls_description TYPE wdy_ext_ctx_map. ls_component = read( ). io_xml->add( iv_name = 'COMPONENT' ig_data = ls_component ). io_xml->add( ig_data = mt_components iv_name = 'COMPONENTS' ). io_xml->add( ig_data = mt_sources iv_name = 'SOURCES' ). READ TABLE ls_component-comp_metadata-descriptions INTO ls_description INDEX 1. IF sy-subrc = 0. zcl_abapgit_sotr_handler=>read_sotr( iv_pgmid = 'LIMU' iv_object = 'WDYV' iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params io_xml = io_xml ). ENDIF. serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_wd ). LOOP AT mt_components INTO ls_comp. lv_object = ls_comp-component_name. lv_object+30 = ls_comp-controller_name. COLLECT lv_object INTO lt_object. ENDLOOP. IF lt_object IS NOT INITIAL. IF mo_i18n_params->ms_params-main_language_only = abap_true. SELECT * FROM dokil INTO TABLE lt_dokil FOR ALL ENTRIES IN lt_object WHERE id = c_longtext_id_wc AND object = lt_object-table_line AND masterlang = abap_true ORDER BY PRIMARY KEY. ELSE. SELECT * FROM dokil INTO TABLE lt_dokil FOR ALL ENTRIES IN lt_object WHERE id = c_longtext_id_wc AND object = lt_object-table_line ORDER BY PRIMARY KEY. ENDIF. serialize_longtexts( ii_xml = io_xml it_dokil = lt_dokil iv_longtext_id = c_longtext_id_wc iv_longtext_name = c_longtext_name_wc ). ENDIF. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_WDYA IMPLEMENTATION. METHOD read. DATA: li_app TYPE REF TO if_wdy_md_application, li_map TYPE REF TO if_object_map, lo_prop TYPE REF TO cl_wdy_md_application_property, ls_prop LIKE LINE OF et_properties, lv_name TYPE wdy_application_name. CLEAR es_app. CLEAR et_properties. lv_name = ms_item-obj_name. TRY. li_app = cl_wdy_md_application=>get_object_by_key( name = lv_name version = 'A' ). CATCH cx_wdy_md_not_existing. RETURN. CATCH cx_wdy_md_permission_failure. zcx_abapgit_exception=>raise( 'WDYA, permission failure' ). ENDTRY. li_app->if_wdy_md_object~get_definition( IMPORTING definition = es_app ). CLEAR: es_app-author, es_app-createdon, es_app-changedby, es_app-changedon. li_map = li_app->get_properties( ). DO li_map->size( ) TIMES. lo_prop ?= li_map->get_by_position( sy-index ). lo_prop->get_definition( IMPORTING definition = ls_prop ). APPEND ls_prop TO et_properties. ENDDO. ENDMETHOD. METHOD save. DATA: li_prop TYPE REF TO if_wdy_md_application_property, lo_app TYPE REF TO cl_wdy_md_application. FIELD-SYMBOLS: LIKE LINE OF it_properties. TRY. CREATE OBJECT lo_app EXPORTING name = is_app-application_name definition = is_app devclass = iv_package. LOOP AT it_properties ASSIGNING . li_prop = lo_app->if_wdy_md_application~create_property( -name ). li_prop->set_value( -value ). ENDLOOP. tadir_insert( iv_package ). lo_app->if_wdy_md_lockable_object~save_to_database( ). CATCH cx_wdy_md_exception. zcx_abapgit_exception=>raise( 'error saving WDYA' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: li_app TYPE REF TO if_wdy_md_application, ls_app TYPE wdy_application, lv_name TYPE wdy_application_name. lv_name = ms_item-obj_name. TRY. li_app = cl_wdy_md_application=>get_object_by_key( name = lv_name version = 'A' ). li_app->if_wdy_md_object~get_definition( IMPORTING definition = ls_app ). IF ls_app-changedby IS INITIAL. rv_user = ls_app-author. ELSE. rv_user = ls_app-changedby. ENDIF. CATCH cx_root. rv_user = c_user_unknown. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: li_app TYPE REF TO if_wdy_md_application, lv_objkey TYPE wdy_wb_appl_name, lv_type TYPE seu_type, lv_name TYPE wdy_application_name. lv_name = ms_item-obj_name. TRY. li_app = cl_wdy_md_application=>get_object_by_key( name = lv_name version = 'A' ). li_app->if_wdy_md_object~delete( ). li_app->if_wdy_md_lockable_object~save_to_database( ). * method save_to_database calls function module TR_TADIR_INTERFACE * with test mode = X, so it does not delete the TADIR entry. * Instead the standard code uses RS_TREE_OBJECT_PLACEMENT to delete * the TADIR entry lv_objkey = ms_item-obj_name. CONCATENATE 'O' swbm_c_type_wdy_application INTO lv_type. CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' EXPORTING object = lv_objkey type = lv_type operation = 'DELETE'. CATCH cx_wdy_md_not_existing. RETURN. CATCH cx_wdy_md_exception. zcx_abapgit_exception=>raise( 'WDYA, error deleting' ). ENDTRY. delete_longtexts( c_longtext_id_wdya ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_app TYPE wdy_application, lt_properties TYPE wdy_app_property_table. io_xml->read( EXPORTING iv_name = 'APP' CHANGING cg_data = ls_app ). io_xml->read( EXPORTING iv_name = 'PROPERTIES' CHANGING cg_data = lt_properties ). save( is_app = ls_app it_properties = lt_properties iv_package = iv_package ). zcl_abapgit_sotr_handler=>create_sotr( iv_package = iv_package io_xml = io_xml ). deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_wdya ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_name TYPE wdy_application_name. lv_name = ms_item-obj_name. TRY. cl_wdy_md_application=>get_object_by_key( name = lv_name version = 'A' ). rv_bool = abap_true. CATCH cx_wdy_md_not_existing. rv_bool = abap_false. CATCH cx_wdy_md_permission_failure. zcx_abapgit_exception=>raise( 'WDYA, permission failure' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_app TYPE wdy_application, lt_properties TYPE wdy_app_property_table. read( IMPORTING es_app = ls_app et_properties = lt_properties ). io_xml->add( iv_name = 'APP' ig_data = ls_app ). io_xml->add( iv_name = 'PROPERTIES' ig_data = lt_properties ). zcl_abapgit_sotr_handler=>read_sotr( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params io_xml = io_xml ). serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_wdya ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_wdcc IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: ls_outline TYPE wdy_cfg_outline_data, ls_config_key TYPE wdy_config_key. ls_config_key-config_id = ms_item-obj_name+0(32). ls_config_key-config_type = ms_item-obj_name+32(2). ls_config_key-config_var = ms_item-obj_name+34(6). TRY. cl_wdr_cfg_persistence_utils=>read_comp_config_from_db( EXPORTING config_key = ls_config_key IMPORTING outline_data = ls_outline ). CATCH cx_static_check. zcx_abapgit_exception=>raise( 'Error Reading Component Config from DB: ' && ms_item-obj_name ). ENDTRY. rv_user = ls_outline-changedby. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_config_key TYPE wdy_config_key, lv_subrc TYPE sysubrc. ls_config_key-config_id = ms_item-obj_name+0(32). ls_config_key-config_type = ms_item-obj_name+32(2). ls_config_key-config_var = ms_item-obj_name+34(6). TRY. " does not exist in 702 CALL METHOD cl_wdr_cfg_persistence_utils=>('DELETE_CONFIGURATION') EXPORTING config_key = ls_config_key RECEIVING subrc = lv_subrc. IF lv_subrc <> 0. zcx_abapgit_exception=>raise( 'Error deleting WDCC: ' && ms_item-obj_name ). ENDIF. CATCH cx_root. zcx_abapgit_exception=>raise( 'Object type WDCC not supported for this release' ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_config_id TYPE c LENGTH 32, lv_config_type TYPE n LENGTH 2, lv_config_var TYPE c LENGTH 6, lt_otr_texts TYPE TABLE OF wdy_config_compt, ls_orig_config TYPE wdy_config_data, lt_config_datt TYPE TABLE OF wdy_config_datt, lv_xml_string TYPE string, lv_xml_xstring TYPE xstring. FIELD-SYMBOLS: TYPE any. io_xml->read( EXPORTING iv_name = 'CONFIG_ID' CHANGING cg_data = ls_orig_config-config_id ). io_xml->read( EXPORTING iv_name = 'CONFIG_TYPE' CHANGING cg_data = ls_orig_config-config_type ). io_xml->read( EXPORTING iv_name = 'CONFIG_VAR' CHANGING cg_data = ls_orig_config-config_var ). lv_config_id = ls_orig_config-config_id. lv_config_type = ls_orig_config-config_type. lv_config_var = ls_orig_config-config_var. ASSIGN COMPONENT 'CONFIG_IDPAR' OF STRUCTURE ls_orig_config TO . IF sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'CONFIG_IDPAR' CHANGING cg_data = ). ELSE. ii_log->add_error( iv_msg = |Object type WDCC not supported for this release| is_item = ms_item ). RETURN. ENDIF. ASSIGN COMPONENT 'CONFIG_TYPEPAR' OF STRUCTURE ls_orig_config TO . IF sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'CONFIG_TYPEPAR' CHANGING cg_data = ). ENDIF. ASSIGN COMPONENT 'CONFIG_VARPAR' OF STRUCTURE ls_orig_config TO . IF sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'CONFIG_VARPAR' CHANGING cg_data = ). ENDIF. io_xml->read( EXPORTING iv_name = 'WDA_COMPONENT' CHANGING cg_data = ls_orig_config-component ). lv_xml_string = mo_files->read_string( iv_extra = 'comp_config' iv_ext = 'xml' ). TRY. lv_xml_string = zcl_abapgit_xml_pretty=>print( iv_xml = lv_xml_string iv_ignore_errors = abap_false iv_unpretty = abap_true ). CATCH zcx_abapgit_exception. zcx_abapgit_exception=>raise( 'Error Un-Pretty Printing WDCC XML Content: ' && ms_item-obj_name ). ENDTRY. REPLACE FIRST OCCURRENCE OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' IN lv_xml_string WITH ''. ASSERT sy-subrc = 0. lv_xml_xstring = zcl_abapgit_convert=>string_to_xstring( lv_xml_string ). ls_orig_config-xcontent = lv_xml_xstring. ASSIGN COMPONENT 'PARENT' OF STRUCTURE ls_orig_config TO . IF sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'PARENT' CHANGING cg_data = ). ENDIF. io_xml->read( EXPORTING iv_name = 'RELID' CHANGING cg_data = ls_orig_config-relid ). SELECT SINGLE author createdon FROM wdy_config_data INTO (ls_orig_config-author, ls_orig_config-createdon) WHERE config_id = lv_config_id AND config_type = lv_config_type AND config_var = lv_config_var. IF ls_orig_config-author IS INITIAL. ls_orig_config-author = sy-uname. ENDIF. ls_orig_config-changedby = sy-uname. ls_orig_config-changedon = sy-datum. IF ls_orig_config-createdon IS INITIAL. ls_orig_config-createdon = sy-datum. ENDIF. CALL FUNCTION 'ENQUEUE_E_WDY_CONFCOMP' EXPORTING mode_wdy_config_data = 'E' "if_wdr_cfg_constants=>c_lock_mode_exclusive config_id = lv_config_id config_type = lv_config_type config_var = lv_config_var x_config_id = 'X' x_config_type = 'X' x_config_var = 'X' EXCEPTIONS foreign_lock = 1 system_failure = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error Enqueueing Component Config: ' && ms_item-obj_name ). ENDIF. " CL_WDR_CFG_PERSISTENCE_UTILS=>SAVE_COMP_CONFIG_TO_DB does not exist in 702 so we save directly to DB DELETE FROM wdy_config_data WHERE config_id = ls_orig_config-config_id AND config_type = ls_orig_config-config_type AND config_var = ls_orig_config-config_var. MODIFY wdy_config_data FROM ls_orig_config. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error Updating WDY_CONFIG_DATA for Component Config ' && ms_item-obj_name ). ENDIF. io_xml->read( EXPORTING iv_name = 'OTR_TEXT' CHANGING cg_data = lt_otr_texts ). IF lt_otr_texts IS NOT INITIAL. DELETE FROM wdy_config_compt WHERE config_id = ls_orig_config-config_id AND config_type = ls_orig_config-config_type AND config_var = ls_orig_config-config_var. MODIFY wdy_config_compt FROM TABLE lt_otr_texts. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error Updating WDY_CONFIG_COMPT for Component Config ' && ms_item-obj_name ). ENDIF. ENDIF. io_xml->read( EXPORTING iv_name = 'DESCR_LANG' CHANGING cg_data = lt_config_datt ). IF lt_config_datt IS NOT INITIAL. DELETE FROM wdy_config_datt WHERE config_id = ls_orig_config-config_id AND config_type = ls_orig_config-config_type AND config_var = ls_orig_config-config_var. MODIFY wdy_config_datt FROM TABLE lt_config_datt. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error Updating WDY_CONFIG_DATT for Component Config ' && ms_item-obj_name ). ENDIF. ENDIF. CALL FUNCTION 'DEQUEUE_E_WDY_CONFCOMP' EXPORTING mode_wdy_config_data = 'E' "if_wdr_cfg_constants=>c_lock_mode_exclusive config_id = lv_config_id config_type = lv_config_type config_var = lv_config_var x_config_id = 'X' x_config_type = 'X' x_config_var = 'X'. tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_outline TYPE wdy_cfg_outline_data, ls_config_key TYPE wdy_config_key. ls_config_key-config_id = ms_item-obj_name+0(32). ls_config_key-config_type = ms_item-obj_name+32(2). ls_config_key-config_var = ms_item-obj_name+34(6). TRY. cl_wdr_cfg_persistence_utils=>read_comp_config_from_db( EXPORTING config_key = ls_config_key IMPORTING outline_data = ls_outline ). CATCH cx_static_check. rv_bool = abap_false. RETURN. ENDTRY. rv_bool = abap_true. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = abap_true. ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lt_enq TYPE STANDARD TABLE OF seqg3, lv_subrc TYPE sysubrc, lv_garg TYPE eqegraarg. lv_garg = ms_item-obj_name. CALL FUNCTION 'ENQUEUE_READ' EXPORTING gclient = sy-mandt gname = 'WDY_CONFIG_DATA' garg = lv_garg IMPORTING subrc = lv_subrc TABLES enq = lt_enq EXCEPTIONS communication_failure = 2 OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error check object lock WDCC: ' && ms_item-obj_name ). ENDIF. rv_is_locked = boolc( lines( lt_enq ) > 0 ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_xml_xstring TYPE xstring, lt_otr_texts TYPE TABLE OF wdy_config_compt, lt_cc_text TYPE TABLE OF wdy_config_datt, ls_orig_config TYPE wdy_config_data, ls_outline TYPE wdy_cfg_outline_data, ls_config_key TYPE wdy_config_key, lv_xml_string TYPE string. FIELD-SYMBOLS: TYPE any. io_xml->add( iv_name = 'OBJECT_NAME' ig_data = ms_item-obj_name ). ls_config_key-config_id = ms_item-obj_name+0(32). ls_config_key-config_type = ms_item-obj_name+32(2). ls_config_key-config_var = ms_item-obj_name+34(6). TRY. " original_config_data does not exist in 702 CALL METHOD cl_wdr_cfg_persistence_utils=>('READ_COMP_CONFIG_FROM_DB') EXPORTING config_key = ls_config_key IMPORTING xml_xcontent = lv_xml_xstring original_config_data = ls_orig_config outline_data = ls_outline. CATCH cx_static_check. zcx_abapgit_exception=>raise( 'Error Reading Component Config from DB: ' && ms_item-obj_name ). CATCH cx_root. zcx_abapgit_exception=>raise( 'Object type WDCC not supported for this release' ). ENDTRY. io_xml->add( iv_name = 'CONFIG_ID' ig_data = ls_orig_config-config_id ). io_xml->add( iv_name = 'CONFIG_TYPE' ig_data = ls_orig_config-config_type ). io_xml->add( iv_name = 'CONFIG_VAR' ig_data = ls_orig_config-config_var ). io_xml->add( iv_name = 'WDA_COMPONENT' ig_data = ls_orig_config-component ). ASSIGN COMPONENT 'CONFIG_IDPAR' OF STRUCTURE ls_orig_config TO . IF sy-subrc = 0. io_xml->add( iv_name = 'CONFIG_IDPAR' ig_data = ). ENDIF. ASSIGN COMPONENT 'CONFIG_TYPEPAR' OF STRUCTURE ls_orig_config TO . IF sy-subrc = 0. io_xml->add( iv_name = 'CONFIG_TYPEPAR' ig_data = ). ENDIF. ASSIGN COMPONENT 'CONFIG_VARPAR' OF STRUCTURE ls_orig_config TO . IF sy-subrc = 0. io_xml->add( iv_name = 'CONFIG_VARPAR' ig_data = ). ENDIF. ASSIGN COMPONENT 'PARENT' OF STRUCTURE ls_orig_config TO . IF sy-subrc = 0. io_xml->add( iv_name = 'PARENT' ig_data = ). ENDIF. io_xml->add( iv_name = 'RELID' ig_data = ls_orig_config-relid ). lv_xml_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xml_xstring ). IF lv_xml_string IS NOT INITIAL. TRY. lv_xml_string = zcl_abapgit_xml_pretty=>print( iv_xml = lv_xml_string iv_ignore_errors = abap_false ). CATCH zcx_abapgit_exception. zcx_abapgit_exception=>raise( 'Error Pretty Printing WDCC XML Content: ' && ms_item-obj_name ). ENDTRY. REPLACE FIRST OCCURRENCE OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' IN lv_xml_string WITH ''. ASSERT sy-subrc = 0. ENDIF. mo_files->add_string( iv_extra = 'comp_config' iv_ext = 'xml' iv_string = lv_xml_string ). SELECT * FROM wdy_config_compt INTO TABLE lt_otr_texts WHERE config_id = ls_orig_config-config_id AND config_type = ls_orig_config-config_type AND config_var = ls_orig_config-config_var ORDER BY PRIMARY KEY. IF lt_otr_texts IS NOT INITIAL. io_xml->add( iv_name = 'OTR_TEXT' ig_data = lt_otr_texts ). ENDIF. SELECT * FROM wdy_config_datt INTO TABLE lt_cc_text WHERE config_id = ls_orig_config-config_id AND config_type = ls_orig_config-config_type AND config_var = ls_orig_config-config_var ORDER BY PRIMARY KEY. IF lt_cc_text IS NOT INITIAL. io_xml->add( iv_name = 'DESCR_LANG' ig_data = lt_cc_text ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_wdca IMPLEMENTATION. METHOD check. FIELD-SYMBOLS: TYPE LINE OF cts_messages. LOOP AT it_messages ASSIGNING WHERE severity = 'E'. zcx_abapgit_exception=>raise( -text ). ENDLOOP. ENDMETHOD. METHOD delete. DATA: lo_cfg TYPE REF TO cl_wdr_cfg_persistence_appl, lx_err TYPE REF TO cx_wd_configuration, lt_messages TYPE cts_messages, ls_key TYPE wdy_config_key, ls_outline TYPE wdy_cfg_outline_data, lv_operation TYPE i, lv_name TYPE wdy_md_object_name, lv_exists TYPE wdy_boolean. ls_key = ms_item-obj_name. TRY. CREATE OBJECT lo_cfg EXPORTING config_key = ls_key object_name = lv_name. MOVE-CORRESPONDING ls_key TO ls_outline. lo_cfg->check_config_existent( EXPORTING i_outline_data = ls_outline i_only_current_layer = abap_false i_is_original = abap_true IMPORTING e_is_existent = lv_exists ). IF lv_exists = abap_false. RETURN. ENDIF. lo_cfg->set_transport( trkorr = iv_transport devclass = iv_package ). lv_operation = if_wdr_cfg_constants=>c_cts_operation-e_delete. " First call, check, second call, delete DO 2 TIMES. lo_cfg->do_next_step( IMPORTING e_messages = lt_messages CHANGING c_operation = lv_operation ). check( lt_messages ). ENDDO. CATCH cx_wd_configuration INTO lx_err. IF lx_err->textid = cx_wd_configuration=>conf_config_not_exist. RETURN. ELSE. zcx_abapgit_exception=>raise( 'WDCA, delete error:' && lx_err->get_text( ) ). ENDIF. ENDTRY. ENDMETHOD. METHOD read. DATA: lo_cfg TYPE REF TO cl_wdr_cfg_persistence_appl, ls_key TYPE wdy_config_key, lv_exists TYPE abap_bool, lx_err TYPE REF TO cx_wd_configuration, lv_name TYPE wdy_md_object_name. FIELD-SYMBOLS: LIKE LINE OF et_data, LIKE LINE OF -appl_params. CLEAR: es_outline, et_data. ls_key = ms_item-obj_name. TRY. CREATE OBJECT lo_cfg EXPORTING config_key = ls_key object_name = lv_name. MOVE-CORRESPONDING ls_key TO es_outline. lo_cfg->check_config_existent( EXPORTING i_outline_data = es_outline i_only_current_layer = abap_false i_is_original = abap_true IMPORTING e_is_existent = lv_exists ). IF lv_exists = abap_false. RETURN. ENDIF. es_outline = lo_cfg->read_outline_data( ). CLEAR: es_outline-devclass, es_outline-author, es_outline-createdon, es_outline-changedby, es_outline-changedon. et_data = lo_cfg->read_data( ). " Clear descriptions since they are release and language-specific LOOP AT et_data ASSIGNING . LOOP AT -appl_params ASSIGNING . CLEAR -description. ENDLOOP. ENDLOOP. CATCH cx_wd_configuration INTO lx_err. zcx_abapgit_exception=>raise( 'WDCA, read error:' && lx_err->get_text( ) ). ENDTRY. ENDMETHOD. METHOD save. DATA: lo_cfg TYPE REF TO cl_wdr_cfg_persistence_appl, lx_err TYPE REF TO cx_wd_configuration, lt_messages TYPE cts_messages, ls_key TYPE wdy_config_key, ls_data LIKE LINE OF it_data, lv_operation TYPE i, lv_name TYPE wdy_md_object_name, lv_exists TYPE wdy_boolean. MOVE-CORRESPONDING is_outline TO ls_key. TRY. CREATE OBJECT lo_cfg EXPORTING config_key = ls_key object_name = lv_name. READ TABLE it_data INDEX 1 INTO ls_data. ASSERT sy-subrc = 0. lo_cfg->check_config_existent( EXPORTING i_outline_data = is_outline i_only_current_layer = abap_false i_is_original = abap_true IMPORTING e_is_existent = lv_exists ). CATCH cx_wd_configuration ##NO_HANDLER. " Ignore ENDTRY. TRY. lo_cfg->set_transport( trkorr = iv_transport devclass = iv_package ). lo_cfg->set_save_data( ls_data ). lo_cfg->set_config_description( is_outline ). IF lv_exists = abap_false. lv_operation = if_wdr_cfg_constants=>c_cts_operation-e_create. ELSE. lv_operation = if_wdr_cfg_constants=>c_cts_operation-e_save. ENDIF. " First call, check, second call, create/save DO 2 TIMES. lo_cfg->do_next_step( IMPORTING e_messages = lt_messages CHANGING c_operation = lv_operation ). check( lt_messages ). ENDDO. CATCH cx_wd_configuration INTO lx_err. zcx_abapgit_exception=>raise( 'WDCA, save error:' && lx_err->get_text( ) ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA ls_key TYPE wdy_config_key. ls_key = ms_item-obj_name. SELECT SINGLE changedby FROM wdy_config_appl INTO rv_user WHERE config_id = ls_key-config_id AND config_type = ls_key-config_type AND config_var = ls_key-config_var. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. delete( iv_package = iv_package iv_transport = iv_transport ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_outline TYPE wdy_cfg_outline_data, lt_data TYPE wdy_cfg_persist_data_appl_tab, lt_config_appt TYPE TABLE OF wdy_config_appt, lv_xml_string TYPE string, lv_xml_xstring TYPE xstring. io_xml->read( EXPORTING iv_name = 'OUTLINE' CHANGING cg_data = ls_outline ). io_xml->read( EXPORTING iv_name = 'DATA' CHANGING cg_data = lt_data ). save( is_outline = ls_outline it_data = lt_data iv_package = iv_package iv_transport = iv_transport ). TRY. lv_xml_string = mo_files->read_string( iv_extra = 'appl_config' iv_ext = 'xml' ). TRY. lv_xml_string = zcl_abapgit_xml_pretty=>print( iv_xml = lv_xml_string iv_ignore_errors = abap_false iv_unpretty = abap_true ). CATCH zcx_abapgit_exception. zcx_abapgit_exception=>raise( 'Error Un-Pretty Printing WDCA XML Content: ' && ms_item-obj_name ). ENDTRY. REPLACE FIRST OCCURRENCE OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' IN lv_xml_string WITH ''. ASSERT sy-subrc = 0. lv_xml_xstring = zcl_abapgit_convert=>string_to_xstring( lv_xml_string ). UPDATE wdy_config_appl SET xcontent = lv_xml_xstring WHERE config_id = ls_outline-config_id AND config_type = ls_outline-config_type AND config_var = ls_outline-config_var. CATCH zcx_abapgit_exception. " File not found ENDTRY. io_xml->read( EXPORTING iv_name = 'DESCR_LANG' CHANGING cg_data = lt_config_appt ). IF lt_config_appt IS NOT INITIAL. DELETE FROM wdy_config_appt WHERE config_id = ls_outline-config_id AND config_type = ls_outline-config_type AND config_var = ls_outline-config_var. MODIFY wdy_config_appt FROM TABLE lt_config_appt. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error Updating WDY_CONFIG_APPT for Component Config ' && ms_item-obj_name ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_wdy_config_appl TYPE wdy_config_appl. DATA: ls_wdy_config_key TYPE wdy_config_key. ls_wdy_config_key = ms_item-obj_name. SELECT SINGLE * FROM wdy_config_appl INTO ls_wdy_config_appl WHERE config_id = ls_wdy_config_key-config_id AND config_type = ls_wdy_config_key-config_type AND config_var = ls_wdy_config_key-config_var. "#EC CI_GENBUFF rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_outline TYPE wdy_cfg_outline_data, lt_data TYPE wdy_cfg_persist_data_appl_tab, lt_cc_text TYPE TABLE OF wdy_config_appt, lv_xml_xstring TYPE xstring, lv_xml_string TYPE string. read( IMPORTING es_outline = ls_outline et_data = lt_data ). IF ls_outline IS INITIAL. RETURN. ENDIF. io_xml->add( iv_name = 'OUTLINE' ig_data = ls_outline ). io_xml->add( iv_name = 'DATA' ig_data = lt_data ). SELECT SINGLE xcontent INTO lv_xml_xstring FROM wdy_config_appl WHERE config_id = ls_outline-config_id AND config_type = ls_outline-config_type AND config_var = ls_outline-config_var. lv_xml_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xml_xstring ). IF lv_xml_string IS NOT INITIAL. TRY. lv_xml_string = zcl_abapgit_xml_pretty=>print( iv_xml = lv_xml_string iv_ignore_errors = abap_false ). CATCH zcx_abapgit_exception. zcx_abapgit_exception=>raise( 'Error Pretty Printing WDCA XML Content: ' && ms_item-obj_name ). ENDTRY. REPLACE FIRST OCCURRENCE OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' IN lv_xml_string WITH ''. ASSERT sy-subrc = 0. ENDIF. mo_files->add_string( iv_extra = 'appl_config' iv_ext = 'xml' iv_string = lv_xml_string ). SELECT * FROM wdy_config_appt INTO TABLE lt_cc_text WHERE config_id = ls_outline-config_id AND config_type = ls_outline-config_type AND config_var = ls_outline-config_var ORDER BY PRIMARY KEY. IF lt_cc_text IS NOT INITIAL. io_xml->add( iv_name = 'DESCR_LANG' ig_data = lt_cc_text ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_wapa IMPLEMENTATION. METHOD create_new_application. DATA: ls_item LIKE ms_item, lv_objkey TYPE seu_objkey. cl_o2_api_application=>create_new( EXPORTING p_application_data = is_attributes p_nodes = it_nodes p_navgraph = it_navgraph IMPORTING p_application = ro_bsp EXCEPTIONS object_already_existing = 1 object_just_created = 2 not_authorized = 3 undefined_name = 4 author_not_existing = 5 action_cancelled = 6 error_occured = 7 invalid_parameter = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |WAPA - error from create_new: { sy-subrc }| ). ENDIF. ro_bsp->save( ). ro_bsp->set_changeable( p_changeable = abap_false p_complete_application = abap_true ). ls_item-obj_type = 'WAPD'. ls_item-obj_name = ms_item-obj_name. zcl_abapgit_objects_activation=>add_item( ls_item ). lv_objkey = ls_item-obj_name. * todo, hmm, the WAPD is not added to the worklist during activation cl_o2_api_application=>activate( lv_objkey ). ENDMETHOD. METHOD create_new_page. cl_o2_api_pages=>create_new_page( EXPORTING p_pageattrs = is_page_attributes IMPORTING p_page = ro_page EXCEPTIONS object_already_exists = 1 invalid_name = 2 error_occured = 3 o2appl_not_existing = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error { sy-subrc } from CL_O2_API_PAGES=>CREATE_NEW_PAGE| ). ENDIF. ENDMETHOD. METHOD delete_superfluous_pages. DATA: ls_pagekey TYPE o2pagkey. FIELD-SYMBOLS: LIKE LINE OF it_local_pages. " delete local pages which doesn't exist remotely LOOP AT it_local_pages ASSIGNING . READ TABLE it_remote_pages WITH KEY attributes-pagekey = -pagekey TRANSPORTING NO FIELDS. IF sy-subrc <> 0. " page exists locally but not remotely -> delete ls_pagekey-applname = -applname. ls_pagekey-pagekey = -pagekey. cl_o2_page=>delete_page_for_application( EXPORTING p_pagekey = ls_pagekey EXCEPTIONS object_not_existing = 1 error_occured = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error { sy-subrc } from CL_O2_PAGE=>DELETE_PAGE_FOR_APPLICATION| ). ENDIF. ENDIF. ENDLOOP. ENDMETHOD. METHOD get_page_content. DATA: lt_content TYPE o2pageline_table, lv_string TYPE string. io_page->get_page( IMPORTING p_content = lt_content EXCEPTIONS invalid_call = 1 page_deleted = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |WAPA - error from get_page_content| ). ENDIF. CONCATENATE LINES OF lt_content INTO lv_string SEPARATED BY cl_abap_char_utilities=>newline RESPECTING BLANKS. rv_content = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). ENDMETHOD. METHOD read_page. DATA: lv_name TYPE o2applname, ls_pagekey TYPE o2pagkey, lv_content TYPE xstring, lv_extra TYPE string, lv_ext TYPE string, lo_page TYPE REF TO cl_o2_api_pages. lv_name = ms_item-obj_name. ls_pagekey-applname = lv_name. ls_pagekey-pagekey = is_page-pagekey. cl_o2_api_pages=>load( EXPORTING p_pagekey = ls_pagekey IMPORTING p_page = lo_page ). lo_page->get_attrs( IMPORTING p_attrs = rs_page-attributes ). IF rs_page-attributes-pagetype <> so2_controller. lo_page->get_event_handlers( IMPORTING p_ev_handler = rs_page-event_handlers EXCEPTIONS page_deleted = 1 invalid_call = 2 ). ASSERT sy-subrc = 0. lo_page->get_parameters( IMPORTING p_parameters = rs_page-parameters EXCEPTIONS page_deleted = 1 invalid_call = 2 OTHERS = 3 ). ASSERT sy-subrc = 0. lo_page->get_type_source( IMPORTING p_source = rs_page-types EXCEPTIONS page_deleted = 1 invalid_call = 2 OTHERS = 3 ). ASSERT sy-subrc = 0. lv_content = get_page_content( lo_page ). SPLIT is_page-pagename AT '.' INTO lv_extra lv_ext. REPLACE ALL OCCURRENCES OF '/' IN lv_ext WITH '_-'. REPLACE ALL OCCURRENCES OF '/' IN lv_extra WITH '_-'. IF iv_no_files_add = abap_false. mo_files->add_raw( iv_extra = lv_extra iv_ext = lv_ext iv_data = lv_content ). ENDIF. CLEAR: rs_page-attributes-implclass. ENDIF. CLEAR: rs_page-attributes-author, rs_page-attributes-createdon, rs_page-attributes-changedby, rs_page-attributes-changedon, rs_page-attributes-changetime, rs_page-attributes-gendate, rs_page-attributes-gentime, rs_page-attributes-devclass. ENDMETHOD. METHOD to_page_content. DATA: lv_string TYPE string. lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( iv_content ). SPLIT lv_string AT cl_abap_char_utilities=>newline INTO TABLE rt_content. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_name TYPE o2applname, lt_pages TYPE STANDARD TABLE OF o2pagdir WITH DEFAULT KEY, ls_latest LIKE LINE OF lt_pages. lv_name = ms_item-obj_name. SELECT * FROM o2pagdir INTO TABLE lt_pages WHERE applname = lv_name ORDER BY changedon DESCENDING changetime DESCENDING. IF sy-subrc <> 0. rv_user = c_user_unknown. RETURN. ENDIF. READ TABLE lt_pages INDEX 1 INTO ls_latest. ASSERT sy-subrc = 0. rv_user = ls_latest-changedby. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_name TYPE o2applname, lo_bsp TYPE REF TO cl_o2_api_application, ls_pagekey TYPE o2pagkey, lv_object TYPE seu_objkey, lt_pages TYPE o2pagelist, lt_local_mimes TYPE o2pagename_table. FIELD-SYMBOLS: LIKE LINE OF lt_pages, TYPE o2pagename. lv_name = ms_item-obj_name. cl_o2_api_application=>load( EXPORTING p_application_name = lv_name IMPORTING p_application = lo_bsp EXCEPTIONS object_not_existing = 1 permission_failure = 2 error_occured = 3 ). ASSERT sy-subrc = 0. lo_bsp->set_changeable( p_changeable = abap_true p_complete_application = abap_true ). cl_o2_api_pages=>get_all_pages( EXPORTING p_applname = lv_name p_version = c_active IMPORTING p_pages = lt_pages ). LOOP AT lt_pages ASSIGNING . CLEAR ls_pagekey. ls_pagekey-applname = lv_name. ls_pagekey-pagekey = -pagekey. cl_o2_page=>delete_page_for_application( EXPORTING p_pagekey = ls_pagekey EXCEPTIONS object_not_existing = 1 error_occured = 2 ). ASSERT sy-subrc = 0. ENDLOOP. lo_bsp->get_local_mimes( IMPORTING p_local_mimes = lt_local_mimes EXCEPTIONS object_invalid = 1 object_deleted = 2 error_occured = 3 OTHERS = 4 ). LOOP AT lt_local_mimes ASSIGNING . CLEAR ls_pagekey. ls_pagekey-applname = -applname. ls_pagekey-pagekey = -pagekey. cl_o2_page=>delete_page_for_application( EXPORTING p_pagekey = ls_pagekey EXCEPTIONS object_not_existing = 1 error_occured = 2 ). ASSERT sy-subrc = 0. ENDLOOP. lo_bsp->delete( EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 action_cancelled = 4 permission_failure = 5 error_occured = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |WAPA - error from delete: { sy-subrc }| ). ENDIF. * release lock lv_object = lv_name. cl_o2_api_application=>call_access_permission( p_mode = 'FREE' p_object = lv_object p_complete_application = abap_true ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_bsp TYPE REF TO cl_o2_api_application, ls_attributes TYPE o2applattr, lt_nodes TYPE o2applnode_table, lt_navgraph TYPE o2applgrap_table, lv_obj_name TYPE string, lv_extra TYPE string, lv_ext TYPE string, lo_page TYPE REF TO cl_o2_api_pages, lt_pages_info TYPE ty_pages_tt, ls_pagekey TYPE o2pagkey, ls_local_page TYPE ty_page, lt_remote_content TYPE o2pageline_table, lt_local_content TYPE o2pageline_table, lt_local_pages TYPE o2pagelist. FIELD-SYMBOLS: LIKE LINE OF lt_pages_info. io_xml->read( EXPORTING iv_name = 'ATTRIBUTES' CHANGING cg_data = ls_attributes ). io_xml->read( EXPORTING iv_name = 'NAVGRAPH' CHANGING cg_data = lt_navgraph ). io_xml->read( EXPORTING iv_name = 'PAGES' CHANGING cg_data = lt_pages_info ). ls_attributes-devclass = iv_package. cl_o2_api_application=>load( EXPORTING p_application_name = ls_attributes-applname " Application Name IMPORTING p_application = lo_bsp " Instance Created EXCEPTIONS object_not_existing = 1 permission_failure = 2 error_occured = 3 OTHERS = 4 ). CASE sy-subrc. WHEN 0. cl_o2_api_pages=>get_all_pages( EXPORTING p_applname = ls_attributes-applname p_version = c_active IMPORTING p_pages = lt_local_pages ). WHEN 1. lo_bsp = create_new_application( is_attributes = ls_attributes it_nodes = lt_nodes it_navgraph = lt_navgraph ). WHEN OTHERS. zcx_abapgit_exception=>raise( |Error { sy-subrc } from CL_O2_API_APPLICATION=>LOAD| ). ENDCASE. LOOP AT lt_pages_info ASSIGNING . ls_pagekey-applname = -attributes-applname. ls_pagekey-pagekey = -attributes-pagekey. cl_o2_api_pages=>load( EXPORTING p_pagekey = ls_pagekey IMPORTING p_page = lo_page EXCEPTIONS object_not_existing = 1 version_not_existing = 2 OTHERS = 3 ). CASE sy-subrc. WHEN 0. ls_local_page = read_page( is_page = -attributes iv_no_files_add = abap_true ). WHEN 1. lo_page = create_new_page( -attributes ). WHEN 2. " Do nothing... WHEN OTHERS. zcx_abapgit_exception=>raise( |Error { sy-subrc } from CL_O2_API_PAGES=>LOAD| ). ENDCASE. SPLIT -attributes-pagename AT '.' INTO lv_extra lv_ext. REPLACE ALL OCCURRENCES OF '/' IN lv_extra WITH '_-'. REPLACE ALL OCCURRENCES OF '/' IN lv_ext WITH '_-'. lt_remote_content = to_page_content( mo_files->read_raw( iv_extra = lv_extra iv_ext = lv_ext ) ). lt_local_content = to_page_content( get_page_content( lo_page ) ). IF ls_local_page = AND lt_local_content = lt_remote_content. " no changes -> nothing to do CONTINUE. ENDIF. IF -attributes-pagetype <> so2_controller. lo_page->set_page( lt_remote_content ). lo_page->set_event_handlers( -event_handlers ). lo_page->set_parameters( -parameters ). lo_page->set_type_source( -types ). ENDIF. lo_page->save( p_with_all_texts = abap_true ). lv_obj_name = cl_wb_object_type=>get_concatenated_key_from_id( p_key_component1 = -attributes-applname p_key_component2 = -attributes-pagekey p_external_id = 'WG ' ). zcl_abapgit_objects_activation=>add( iv_type = 'WAPP' iv_name = lv_obj_name ). ENDLOOP. delete_superfluous_pages( it_local_pages = lt_local_pages it_remote_pages = lt_pages_info ). zcl_abapgit_sotr_handler=>create_sotr( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_name TYPE o2applname. lv_name = ms_item-obj_name. cl_o2_api_application=>load( EXPORTING p_application_name = lv_name EXCEPTIONS object_not_existing = 1 permission_failure = 2 error_occured = 3 ). rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_name TYPE o2applname, ls_attributes TYPE o2applattr, lt_navgraph TYPE o2applgrap_table, lt_pages TYPE o2pagelist, lt_pages_info TYPE ty_pages_tt, lo_bsp TYPE REF TO cl_o2_api_application. FIELD-SYMBOLS: LIKE LINE OF lt_pages. lv_name = ms_item-obj_name. cl_o2_api_application=>load( EXPORTING p_application_name = lv_name IMPORTING p_application = lo_bsp EXCEPTIONS object_not_existing = 1 permission_failure = 2 error_occured = 3 ). IF sy-subrc <> 0. RETURN. ENDIF. lo_bsp->get_attributes( EXPORTING p_version = c_active IMPORTING p_attributes = ls_attributes ). CLEAR: ls_attributes-author, ls_attributes-createdon, ls_attributes-changedby, ls_attributes-changedon, ls_attributes-devclass. io_xml->add( iv_name = 'ATTRIBUTES' ig_data = ls_attributes ). lo_bsp->get_navgraph( EXPORTING p_version = c_active IMPORTING p_navgraph = lt_navgraph ). io_xml->add( iv_name = 'NAVGRAPH' ig_data = lt_navgraph ). cl_o2_api_pages=>get_all_pages( EXPORTING p_applname = lv_name p_version = c_active IMPORTING p_pages = lt_pages ). LOOP AT lt_pages ASSIGNING . APPEND read_page( ) TO lt_pages_info. ENDLOOP. io_xml->add( iv_name = 'PAGES' ig_data = lt_pages_info ). zcl_abapgit_sotr_handler=>read_sotr( iv_pgmid = 'LIMU' iv_object = 'WAPP' iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params io_xml = io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_w3xx_super IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). ms_key-relid = ms_item-obj_type+2(2). ms_key-objid = ms_item-obj_name. ENDMETHOD. METHOD find_param. FIELD-SYMBOLS LIKE LINE OF it_params. READ TABLE it_params ASSIGNING WITH KEY name = iv_name. IF sy-subrc > 0. zcx_abapgit_exception=>raise( |W3xx: Cannot find { iv_name } for { ms_key-objid }| ). ENDIF. rv_value = -value. ENDMETHOD. METHOD get_ext. rv_ext = find_param( it_params = it_params iv_name = c_param_names-fileext ). SHIFT rv_ext LEFT DELETING LEADING '.'. ENDMETHOD. METHOD normalize_params. FIELD-SYMBOLS LIKE LINE OF ct_params. " Ensure filesize param exists READ TABLE ct_params ASSIGNING WITH KEY name = c_param_names-filesize. IF sy-subrc <> 0. APPEND INITIAL LINE TO ct_params ASSIGNING . -name = c_param_names-filesize. ENDIF. LOOP AT ct_params ASSIGNING . -relid = ms_key-relid. " Ensure param key = object key -objid = ms_key-objid. IF -name = c_param_names-filesize. " Patch filesize = real file size -value = iv_size. CONDENSE -value. ENDIF. ENDLOOP. ENDMETHOD. METHOD strip_params. FIELD-SYMBOLS LIKE LINE OF ct_params. " Remove path from filename find_param( it_params = ct_params iv_name = c_param_names-filename ). " Check exists READ TABLE ct_params ASSIGNING WITH KEY name = c_param_names-filename. -value = zcl_abapgit_path=>get_filename_from_syspath( |{ -value }| ). " Clear id and object name LOOP AT ct_params ASSIGNING . CLEAR: -relid, -objid. ENDLOOP. " Clear version & filesize DELETE ct_params WHERE name = c_param_names-version. DELETE ct_params WHERE name = c_param_names-filesize. " Avoid diffs due to different order SORT ct_params. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE chname INTO rv_user FROM wwwdata WHERE relid = ms_key-relid AND objid = ms_key-objid AND srtf2 = 0. IF sy-subrc IS NOT INITIAL OR rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. CALL FUNCTION 'WWWDATA_DELETE' EXPORTING key = ms_key EXCEPTIONS wrong_object_type = 1 delete_error = 2. IF sy-subrc IS NOT INITIAL. zcx_abapgit_exception=>raise( 'Cannot delete W3xx data' ). ENDIF. CALL FUNCTION 'WWWPARAMS_DELETE_ALL' EXPORTING key = ms_key EXCEPTIONS delete_error = 1. IF sy-subrc IS NOT INITIAL. zcx_abapgit_exception=>raise( 'Cannot delete W3xx params' ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA lv_base64str TYPE string. DATA lt_w3params TYPE STANDARD TABLE OF wwwparams. DATA lv_xstring TYPE xstring. DATA lt_w3mime TYPE STANDARD TABLE OF w3mime. DATA lt_w3html TYPE STANDARD TABLE OF w3html. DATA lv_size TYPE i. io_xml->read( EXPORTING iv_name = 'TEXT' CHANGING cg_data = ms_key-text ). io_xml->read( EXPORTING iv_name = 'PARAMS' CHANGING cg_data = lt_w3params ). CASE io_xml->get_metadata( )-version. WHEN 'v1.0.0'. io_xml->read( EXPORTING iv_name = 'DATA' CHANGING cg_data = lv_base64str ). lv_xstring = cl_http_utility=>decode_x_base64( lv_base64str ). WHEN 'v2.0.0'. lv_xstring = mo_files->read_raw( iv_extra = 'data' iv_ext = get_ext( lt_w3params ) ). WHEN OTHERS. zcx_abapgit_exception=>raise( 'W3xx: Unknown serializer version' ). ENDCASE. CASE ms_key-relid. WHEN 'MI'. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = lv_xstring IMPORTING output_length = lv_size TABLES binary_tab = lt_w3mime. WHEN 'HT'. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = lv_xstring IMPORTING output_length = lv_size TABLES binary_tab = lt_w3mime. CALL FUNCTION 'SCMS_BINARY_TO_TEXT' EXPORTING input_length = lv_size IMPORTING output_length = lv_size TABLES binary_tab = lt_w3mime text_tab = lt_w3html EXCEPTIONS failed = 1. IF sy-subrc IS NOT INITIAL. zcx_abapgit_exception=>raise( 'Cannot update W3xx params' ). ENDIF. CLEAR lt_w3mime. WHEN OTHERS. zcx_abapgit_exception=>raise( 'Wrong W3xx type' ). ENDCASE. " Update size of file based on actual data file size, prove param object name normalize_params( EXPORTING iv_size = lv_size CHANGING ct_params = lt_w3params ). CALL FUNCTION 'WWWPARAMS_UPDATE' TABLES params = lt_w3params EXCEPTIONS update_error = 1. IF sy-subrc IS NOT INITIAL. zcx_abapgit_exception=>raise( 'Cannot update W3xx params' ). ENDIF. ms_key-tdate = sy-datum. ms_key-ttime = sy-uzeit. ms_key-chname = sy-uname. ms_key-devclass = iv_package. CALL FUNCTION 'WWWDATA_EXPORT' EXPORTING key = ms_key TABLES mime = lt_w3mime html = lt_w3html EXCEPTIONS wrong_object_type = 1 export_error = 2. IF sy-subrc IS NOT INITIAL. zcx_abapgit_exception=>raise( 'Cannot upload W3xx data' ). ENDIF. tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. SELECT SINGLE objid INTO ms_key-objid FROM wwwdata WHERE relid = ms_key-relid AND objid = ms_key-objid AND srtf2 = 0. IF sy-subrc IS NOT INITIAL. RETURN. ENDIF. rv_bool = abap_true. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). rs_metadata-version = 'v2.0.0'. " Serialization v2, separate data file ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_object TYPE eqegraarg. lv_object = |{ ms_item-obj_type+2(2) }{ ms_item-obj_name }|. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_WWW_HTML' iv_argument = lv_object ). ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_bdcdata TYPE bdcdata, lt_bdcdata TYPE ty_bdcdata. ls_bdcdata-program = 'SAPMWWW0'. ls_bdcdata-dynpro = '0100'. ls_bdcdata-dynbegin = 'X'. APPEND ls_bdcdata TO lt_bdcdata. change_bdc_jump_data( CHANGING ct_bdcdata = lt_bdcdata ). CLEAR ls_bdcdata. ls_bdcdata-fnam = 'BDC_OKCODE'. ls_bdcdata-fval = '=CRO1'. APPEND ls_bdcdata TO lt_bdcdata. ls_bdcdata-program = 'RSWWWSHW'. ls_bdcdata-dynpro = '1000'. ls_bdcdata-dynbegin = 'X'. APPEND ls_bdcdata TO lt_bdcdata. CLEAR ls_bdcdata. ls_bdcdata-fnam = 'SO_OBJID-LOW'. ls_bdcdata-fval = ms_item-obj_name. APPEND ls_bdcdata TO lt_bdcdata. CLEAR ls_bdcdata. ls_bdcdata-fnam = 'BDC_OKCODE'. ls_bdcdata-fval = '=ONLI'. APPEND ls_bdcdata TO lt_bdcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SMW0' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA lt_w3mime TYPE STANDARD TABLE OF w3mime. DATA lt_w3html TYPE STANDARD TABLE OF w3html. DATA lt_w3params TYPE STANDARD TABLE OF wwwparams. DATA lv_xstring TYPE xstring. DATA lv_size TYPE i. SELECT SINGLE * INTO CORRESPONDING FIELDS OF ms_key FROM wwwdata WHERE relid = ms_key-relid AND objid = ms_key-objid AND srtf2 = 0. IF sy-subrc IS NOT INITIAL. RETURN. ENDIF. CALL FUNCTION 'WWWDATA_IMPORT' EXPORTING key = ms_key TABLES mime = lt_w3mime html = lt_w3html EXCEPTIONS wrong_object_type = 1 import_error = 2. IF sy-subrc IS NOT INITIAL. zcx_abapgit_exception=>raise( 'Cannot read W3xx data' ). ENDIF. CALL FUNCTION 'WWWPARAMS_READ_ALL' EXPORTING type = ms_key-relid objid = ms_key-objid TABLES params = lt_w3params EXCEPTIONS entry_not_exists = 1. IF sy-subrc IS NOT INITIAL. zcx_abapgit_exception=>raise( 'Cannot read W3xx data' ). ENDIF. lv_size = find_param( it_params = lt_w3params iv_name = c_param_names-filesize ). " Clean params (remove version, filesize & clear filename from path) strip_params( CHANGING ct_params = lt_w3params ). CASE ms_key-relid. WHEN 'MI'. CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' EXPORTING input_length = lv_size IMPORTING buffer = lv_xstring TABLES binary_tab = lt_w3mime EXCEPTIONS failed = 1. WHEN 'HT'. CALL FUNCTION 'SCMS_TEXT_TO_XSTRING' IMPORTING buffer = lv_xstring TABLES text_tab = lt_w3html EXCEPTIONS failed = 1. WHEN OTHERS. zcx_abapgit_exception=>raise( 'Wrong W3xx type' ). ENDCASE. IF sy-subrc IS NOT INITIAL. zcx_abapgit_exception=>raise( 'Cannot convert W3xx to xstring' ). ENDIF. io_xml->add( iv_name = 'NAME' ig_data = ms_key-objid ). io_xml->add( iv_name = 'TEXT' ig_data = ms_key-text ). SORT lt_w3params. io_xml->add( iv_name = 'PARAMS' ig_data = lt_w3params ). " Serialization v2, separate data file. 'extra' added to prevent conflict with .xml mo_files->add_raw( iv_data = lv_xstring iv_extra = 'data' iv_ext = get_ext( lt_w3params ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_w3mi IMPLEMENTATION. METHOD change_bdc_jump_data. DATA: ls_bdcdata LIKE LINE OF ct_bdcdata. ls_bdcdata-fnam = 'RADIO_HT'. ls_bdcdata-fval = ' '. APPEND ls_bdcdata TO ct_bdcdata. CLEAR ls_bdcdata. ls_bdcdata-fnam = 'RADIO_MI'. ls_bdcdata-fval = 'X'. APPEND ls_bdcdata TO ct_bdcdata. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_w3ht IMPLEMENTATION. METHOD change_bdc_jump_data. DATA: ls_bdcdata LIKE LINE OF ct_bdcdata. ls_bdcdata-fnam = 'RADIO_HT'. ls_bdcdata-fval = 'X'. APPEND ls_bdcdata TO ct_bdcdata. CLEAR ls_bdcdata. ls_bdcdata-fnam = 'RADIO_MI'. ls_bdcdata-fval = ' '. APPEND ls_bdcdata TO ct_bdcdata. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_view IMPLEMENTATION. METHOD deserialize_texts. DATA: lv_name TYPE ddobjname, lt_i18n_langs TYPE TABLE OF langu, lt_dd25_texts TYPE ty_dd25_texts, ls_dd25v_tmp TYPE dd25v. FIELD-SYMBOLS: TYPE langu, LIKE LINE OF lt_dd25_texts. lv_name = ms_item-obj_name. ii_xml->read( EXPORTING iv_name = 'I18N_LANGS' CHANGING cg_data = lt_i18n_langs ). ii_xml->read( EXPORTING iv_name = 'DD25_TEXTS' CHANGING cg_data = lt_dd25_texts ). mo_i18n_params->trim_saplang_list( CHANGING ct_sap_langs = lt_i18n_langs ). SORT lt_i18n_langs. SORT lt_dd25_texts BY ddlanguage. LOOP AT lt_i18n_langs ASSIGNING . " View description ls_dd25v_tmp = is_dd25v. READ TABLE lt_dd25_texts ASSIGNING WITH KEY ddlanguage = . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |DD25_TEXTS cannot find lang { } in XML| ). ENDIF. MOVE-CORRESPONDING TO ls_dd25v_tmp. CALL FUNCTION 'DDIF_VIEW_PUT' EXPORTING name = lv_name dd25v_wa = ls_dd25v_tmp EXCEPTIONS view_not_found = 1 name_inconsistent = 2 view_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD read_view. DATA: lv_name TYPE ddobjname. lv_name = ms_item-obj_name. CALL FUNCTION 'DDIF_VIEW_GET' EXPORTING name = lv_name state = 'A' langu = iv_language IMPORTING gotstate = ev_state dd25v_wa = es_dd25v dd09l_wa = es_dd09l TABLES dd26v_tab = et_dd26v dd27p_tab = et_dd27p dd28j_tab = et_dd28j dd28v_tab = et_dd28v EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD serialize_texts. DATA: lv_index TYPE i, ls_dd25v TYPE dd25v, lt_dd25_texts TYPE ty_dd25_texts, lt_i18n_langs TYPE TABLE OF langu, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, LIKE LINE OF lt_dd25_texts. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. " Collect additional languages, skip main lang - it was serialized already lt_language_filter = mo_i18n_params->build_language_filter( ). SELECT DISTINCT ddlanguage AS langu INTO TABLE lt_i18n_langs FROM dd25v WHERE viewname = ms_item-obj_name AND ddlanguage IN lt_language_filter AND ddlanguage <> mv_language ORDER BY langu. "#EC CI_SUBRC LOOP AT lt_i18n_langs ASSIGNING . lv_index = sy-tabix. CLEAR: ls_dd25v. TRY. read_view( EXPORTING iv_language = IMPORTING es_dd25v = ls_dd25v ). CATCH zcx_abapgit_exception. CONTINUE. ENDTRY. IF ls_dd25v-ddlanguage IS INITIAL. DELETE lt_i18n_langs INDEX lv_index. " Don't save this lang CONTINUE. ENDIF. APPEND INITIAL LINE TO lt_dd25_texts ASSIGNING . MOVE-CORRESPONDING ls_dd25v TO . ENDLOOP. SORT lt_i18n_langs ASCENDING. SORT lt_dd25_texts BY ddlanguage ASCENDING. IF lines( lt_i18n_langs ) > 0. ii_xml->add( iv_name = 'I18N_LANGS' ig_data = lt_i18n_langs ). ii_xml->add( iv_name = 'DD25_TEXTS' ig_data = lt_dd25_texts ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE as4user FROM dd25l INTO rv_user WHERE viewname = ms_item-obj_name AND as4local = 'A' AND as4vers = '0000'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. delete_ddic( 'V' ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_name TYPE ddobjname, ls_dd25v TYPE dd25v, ls_dd09l TYPE dd09l, lt_dd26v TYPE TABLE OF dd26v, lt_dd27p TYPE TABLE OF dd27p, lt_dd28j TYPE TABLE OF dd28j, lt_dd28v TYPE TABLE OF dd28v. FIELD-SYMBOLS: LIKE LINE OF lt_dd27p. io_xml->read( EXPORTING iv_name = 'DD25V' CHANGING cg_data = ls_dd25v ). io_xml->read( EXPORTING iv_name = 'DD09L' CHANGING cg_data = ls_dd09l ). io_xml->read( EXPORTING iv_name = 'DD26V_TABLE' CHANGING cg_data = lt_dd26v ). io_xml->read( EXPORTING iv_name = 'DD27P_TABLE' CHANGING cg_data = lt_dd27p ). io_xml->read( EXPORTING iv_name = 'DD28J_TABLE' CHANGING cg_data = lt_dd28j ). io_xml->read( EXPORTING iv_name = 'DD28V_TABLE' CHANGING cg_data = lt_dd28v ). lv_name = ms_item-obj_name. " type conversion LOOP AT lt_dd27p ASSIGNING . -objpos = sy-tabix. -viewname = lv_name. " rollname seems to be mandatory in the API, but is typically not defined in the VIEW SELECT SINGLE rollname FROM dd03l INTO -rollname WHERE tabname = -tabname AND fieldname = -fieldname. IF -rollnamevi IS INITIAL. -rollnamevi = -rollname. ENDIF. ENDLOOP. corr_insert( iv_package = iv_package ig_object_class = 'DICT' ). CALL FUNCTION 'DDIF_VIEW_PUT' EXPORTING name = lv_name dd25v_wa = ls_dd25v dd09l_wa = ls_dd09l TABLES dd26v_tab = lt_dd26v dd27p_tab = lt_dd27p dd28j_tab = lt_dd28j dd28v_tab = lt_dd28v EXCEPTIONS view_not_found = 1 name_inconsistent = 2 view_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF mo_i18n_params->is_lxe_applicable( ) = abap_false. deserialize_texts( ii_xml = io_xml is_dd25v = ls_dd25v ). ENDIF. deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_view ). zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_viewname TYPE dd25l-viewname, lv_ddl_view TYPE abap_bool. SELECT SINGLE viewname FROM dd25l INTO lv_viewname WHERE viewname = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). IF rv_bool = abap_true. TRY. CALL METHOD ('CL_DD_DDL_UTILITIES')=>('CHECK_FOR_DDL_VIEW') EXPORTING objname = lv_viewname RECEIVING is_ddl_view = lv_ddl_view. IF lv_ddl_view = abap_true. rv_bool = abap_false. ENDIF. CATCH cx_root ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECT=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_dd25v TYPE dd25v, lv_state TYPE ddgotstate, ls_dd09l TYPE dd09l, lt_dd26v TYPE ty_dd26v, lt_dd27p TYPE ty_dd27p, lt_dd28j TYPE ty_dd28j, lt_dd28v TYPE ty_dd28v. FIELD-SYMBOLS: LIKE LINE OF lt_dd27p. read_view( EXPORTING iv_language = mv_language IMPORTING ev_state = lv_state es_dd25v = ls_dd25v es_dd09l = ls_dd09l et_dd26v = lt_dd26v et_dd27p = lt_dd27p et_dd28j = lt_dd28j et_dd28v = lt_dd28v ). IF ls_dd25v IS INITIAL OR lv_state <> 'A'. RETURN. ENDIF. CLEAR: ls_dd25v-as4user, ls_dd25v-as4date, ls_dd25v-as4time. CLEAR: ls_dd09l-as4user, ls_dd09l-as4date, ls_dd09l-as4time. LOOP AT lt_dd27p ASSIGNING . CLEAR: -ddtext, -reptext, -scrtext_s, -scrtext_m, -scrtext_l, -outputlen, -decimals, -lowercase, -convexit, -signflag, -flength, -domname, -datatype, -entitytab, -inttype, -intlen, -headlen, -scrlen1, -scrlen2, -scrlen3, -memoryid. IF -rollchange = abap_false. CLEAR -rollnamevi. ENDIF. CLEAR -ddlanguage. CLEAR -rollname. CLEAR -viewname. CLEAR -objpos. ENDLOOP. io_xml->add( iv_name = 'DD25V' ig_data = ls_dd25v ). io_xml->add( iv_name = 'DD09L' ig_data = ls_dd09l ). io_xml->add( ig_data = lt_dd26v iv_name = 'DD26V_TABLE' ). io_xml->add( ig_data = lt_dd27p iv_name = 'DD27P_TABLE' ). io_xml->add( ig_data = lt_dd28j iv_name = 'DD28J_TABLE' ). io_xml->add( ig_data = lt_dd28v iv_name = 'DD28V_TABLE' ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. serialize_texts( io_xml ). ENDIF. serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_view ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_vcls IMPLEMENTATION. METHOD is_locked. DATA: ls_rstable_key TYPE rstable, " Lock argument for table RSTABLE lv_argument TYPE eqegraarg. " Set Values for generic table lock ls_rstable_key-tabname = iv_tabname. ls_rstable_key-varkey = iv_argument. " include all sub keys lv_argument = ls_rstable_key. lv_argument = lv_argument && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_TABLEE' iv_argument = lv_argument ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE author FROM vcldir INTO rv_user WHERE vclname = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. * Do the same as in VIEWCLUSTER_SAVE_DEFINITION DATA: lv_vclname TYPE vcl_name. lv_vclname = ms_item-obj_name. DELETE FROM vcldir WHERE vclname = lv_vclname. "#EC CI_SUBRC DELETE FROM vcldirt WHERE vclname = lv_vclname. "#EC CI_NOFIRST "#EC CI_SUBRC DELETE FROM vclstruc WHERE vclname = lv_vclname. "#EC CI_SUBRC DELETE FROM vclstruct WHERE vclname = lv_vclname. "#EC CI_NOFIRST "#EC CI_SUBRC DELETE FROM vclstrudep WHERE vclname = lv_vclname. "#EC CI_SUBRC DELETE FROM vclmf WHERE vclname = lv_vclname. "#EC CI_SUBRC corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_vcldir_entry TYPE v_vcldir, lt_vclstruc TYPE TABLE OF v_vclstruc, lt_vclstrudep TYPE TABLE OF v_vclstdep, lt_vclmf TYPE TABLE OF v_vclmf, lv_objectname TYPE ob_object. io_xml->read( EXPORTING iv_name = 'VCLDIR' CHANGING cg_data = ls_vcldir_entry ). io_xml->read( EXPORTING iv_name = 'VLCSTRUC_TAB' CHANGING cg_data = lt_vclstruc ). io_xml->read( EXPORTING iv_name = 'VCLSTRUDEP_TAB' CHANGING cg_data = lt_vclstrudep ). io_xml->read( EXPORTING iv_name = 'lt_vclstrudep' CHANGING cg_data = lt_vclmf ). ls_vcldir_entry-author = sy-uname. ls_vcldir_entry-changedate = sy-datum. CALL FUNCTION 'VIEWCLUSTER_SAVE_DEFINITION' EXPORTING vcldir_entry = ls_vcldir_entry TABLES vclstruc_tab = lt_vclstruc vclstrudep_tab = lt_vclstrudep vclmf_tab = lt_vclmf. corr_insert( iv_package ). lv_objectname = ls_vcldir_entry-vclname. CALL FUNCTION 'OBJ_GENERATE' EXPORTING iv_objectname = lv_objectname iv_objecttype = c_cluster_type iv_maint_mode = c_mode_insert iv_devclass = iv_package EXCEPTIONS illegal_call = 1 object_not_found = 2 generate_error = 3 transport_error = 4 object_enqueue_failed = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA lv_changedate TYPE vcldir-changedate. SELECT SINGLE changedate INTO lv_changedate FROM vcldir WHERE vclname = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. DATA lv_changedate TYPE vcldir-changedate. SELECT SINGLE changedate INTO lv_changedate FROM vcldir WHERE vclname = ms_item-obj_name. * see logic in function module VIEWCLUSTER_GET_DEFINITION rv_active = boolc( lv_changedate IS NOT INITIAL ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_argument TYPE seqg3-garg, lv_argument_langu TYPE seqg3-garg. lv_argument = ms_item-obj_name. lv_argument_langu = |@{ ms_item-obj_name }|. "Check all relevant maintain tables for view clusters IF is_locked( iv_tabname = 'VCLDIR' iv_argument = lv_argument ) = abap_true OR is_locked( iv_tabname = 'VCLDIRT' iv_argument = lv_argument_langu ) = abap_true OR is_locked( iv_tabname = 'VCLSTRUC' iv_argument = lv_argument ) = abap_true OR is_locked( iv_tabname = 'VCLSTRUCT' iv_argument = lv_argument_langu ) = abap_true OR is_locked( iv_tabname = 'VCLMF' iv_argument = lv_argument ) = abap_true. rv_is_locked = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_bcdata TYPE bdcdata, lt_bcdata TYPE STANDARD TABLE OF bdcdata. ls_bcdata-program = 'SAPMSVIM'. ls_bcdata-dynpro = '0050'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'VIMDYNFLDS-VIEWNAME'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'VIMDYNFLDS-STRUCT_MNT'. ls_bcdata-fval = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=CLUS'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-program = 'SAPMSVIM'. ls_bcdata-dynpro = '0052 '. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'VIMDYNFLDS-VCLNAME'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=CLSH'. APPEND ls_bcdata TO lt_bcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SE54' it_bdcdata = lt_bcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_vclname TYPE vcl_name, ls_vcldir_entry TYPE v_vcldir, lt_vclstruc TYPE TABLE OF v_vclstruc, lt_vclstrudep TYPE TABLE OF v_vclstdep, lt_vclmf TYPE TABLE OF v_vclmf. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. lv_vclname = ms_item-obj_name. CALL FUNCTION 'VIEWCLUSTER_GET_DEFINITION' EXPORTING vclname = lv_vclname IMPORTING vcldir_entry = ls_vcldir_entry TABLES vclstruc_tab = lt_vclstruc vclstrudep_tab = lt_vclstrudep vclmf_tab = lt_vclmf EXCEPTIONS viewcluster_not_found = 1 incomplete_viewcluster = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. SORT lt_vclstrudep BY vclname object objfield. CLEAR ls_vcldir_entry-author. CLEAR ls_vcldir_entry-changedate. io_xml->add( iv_name = 'VCLDIR' ig_data = ls_vcldir_entry ). io_xml->add( iv_name = 'VLCSTRUC_TAB' ig_data = lt_vclstruc ). io_xml->add( iv_name = 'VCLSTRUDEP_TAB' ig_data = lt_vclstrudep ). io_xml->add( iv_name = 'VCLMF_TAB' ig_data = lt_vclmf ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ueno IMPLEMENTATION. METHOD build_text_name. TYPES BEGIN OF ty_text_name. TYPES id TYPE c LENGTH 4. TYPES entity TYPE c LENGTH 26. TYPES modifier TYPE c LENGTH 2. TYPES END OF ty_text_name. DATA ls_text_name TYPE ty_text_name. ls_text_name-id = iv_id. ls_text_name-entity = mv_entity_id. ls_text_name-modifier = 'A%'. rv_result = ls_text_name. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_entity_id = is_item-obj_name. ENDMETHOD. METHOD delete_docu_uen. DATA lt_dm02l TYPE STANDARD TABLE OF dm02l WITH DEFAULT KEY. DATA ls_dm02l TYPE dm02l. SELECT * FROM dm02l INTO TABLE lt_dm02l WHERE entid = mv_entity_id ORDER BY PRIMARY KEY. LOOP AT lt_dm02l INTO ls_dm02l. CALL FUNCTION 'SDU_DOCU_DELETE' EXPORTING key1 = ls_dm02l-entid key2 = ls_dm02l-as4local key3 = '00' langu = mv_language obj_id = 'UENC' "Entity Comments EXCEPTIONS ret_code = 0. CALL FUNCTION 'SDU_DOCU_DELETE' EXPORTING key1 = ls_dm02l-entid key2 = ls_dm02l-as4local key3 = '00' langu = mv_language obj_id = 'UEND' "Entity Definition EXCEPTIONS ret_code = 0. CALL FUNCTION 'SDU_DOCU_DELETE' EXPORTING key1 = ls_dm02l-entid key2 = ls_dm02l-as4local key3 = '00' langu = mv_language obj_id = 'UENE' "Entity Example EXCEPTIONS ret_code = 0. ENDLOOP. ENDMETHOD. METHOD delete_docu_url. DATA lt_dm42s TYPE STANDARD TABLE OF dm42s WITH DEFAULT KEY. DATA ls_dm42s LIKE LINE OF lt_dm42s. SELECT * FROM dm42s INTO TABLE lt_dm42s WHERE entidto = mv_entity_id ORDER BY PRIMARY KEY. LOOP AT lt_dm42s INTO ls_dm42s. CALL FUNCTION 'SDU_DOCU_DELETE' EXPORTING langu = mv_language obj_id = 'URL1' key1 = ls_dm42s-entidto key2 = ls_dm42s-as4local key3 = ls_dm42s-entidfrom key4 = ls_dm42s-ebrolnr EXCEPTIONS ret_code = 0. CALL FUNCTION 'SDU_DOCU_DELETE' EXPORTING langu = mv_language obj_id = 'URL2' key1 = ls_dm42s-entidto key2 = ls_dm42s-as4local key3 = ls_dm42s-entidfrom key4 = ls_dm42s-ebrolnr EXCEPTIONS ret_code = 0. CALL FUNCTION 'SDU_DOCU_DELETE' EXPORTING langu = mv_language obj_id = 'URLC' key1 = ls_dm42s-entidto key2 = ls_dm42s-as4local key3 = ls_dm42s-entidfrom key4 = ls_dm42s-ebrolnr EXCEPTIONS ret_code = 0. ENDLOOP. ENDMETHOD. METHOD delete_docu_usp. DATA lt_dm45l TYPE STANDARD TABLE OF dm45l WITH DEFAULT KEY. DATA ls_dm45l LIKE LINE OF lt_dm45l. SELECT * FROM dm45l INTO TABLE lt_dm45l WHERE entid = ms_item-obj_name ORDER BY PRIMARY KEY. LOOP AT lt_dm45l INTO ls_dm45l. CALL FUNCTION 'SDU_DOCU_DELETE' EXPORTING langu = mv_language obj_id = 'USPD' key1 = ls_dm45l-entid key2 = ls_dm45l-as4local key3 = ls_dm45l-spezid EXCEPTIONS ret_code = 0. ENDLOOP. ENDMETHOD. METHOD deserialize_docu_uen. DATA lt_docu TYPE ty_docu_lines. io_xml->read( EXPORTING iv_name = 'DOCU_UENC' CHANGING cg_data = lt_docu ). deserialize_docu_xxxx( lt_docu ). CLEAR lt_docu. io_xml->read( EXPORTING iv_name = 'DOCU_UEND' CHANGING cg_data = lt_docu ). deserialize_docu_xxxx( lt_docu ). CLEAR lt_docu. io_xml->read( EXPORTING iv_name = 'DOCU_UENE' CHANGING cg_data = lt_docu ). deserialize_docu_xxxx( lt_docu ). ENDMETHOD. METHOD deserialize_docu_url. DATA lt_docu TYPE ty_docu_lines. io_xml->read( EXPORTING iv_name = 'DOCU_URL1' CHANGING cg_data = lt_docu ). deserialize_docu_xxxx( lt_docu ). CLEAR lt_docu. io_xml->read( EXPORTING iv_name = 'DOCU_URL2' CHANGING cg_data = lt_docu ). deserialize_docu_xxxx( lt_docu ). CLEAR lt_docu. io_xml->read( EXPORTING iv_name = 'DOCU_URLC' CHANGING cg_data = lt_docu ). deserialize_docu_xxxx( lt_docu ). ENDMETHOD. METHOD deserialize_docu_usp. DATA lt_docu TYPE ty_docu_lines. io_xml->read( EXPORTING iv_name = 'DOCU_USPD' CHANGING cg_data = lt_docu ). deserialize_docu_xxxx( lt_docu ). ENDMETHOD. METHOD deserialize_docu_xxxx. DATA ls_docu LIKE LINE OF it_docu. DATA lv_objname TYPE lxeobjname. DATA lv_change_flag TYPE char1. DATA lv_error_status TYPE lxestatprc. LOOP AT it_docu INTO ls_docu. ls_docu-header-tdfuser = sy-uname. ls_docu-header-tdfdate = sy-datum. ls_docu-header-tdftime = sy-uzeit. ls_docu-header-tdfreles = sy-saprl. ls_docu-header-tdluser = sy-uname. ls_docu-header-tdldate = sy-datum. ls_docu-header-tdltime = sy-uzeit. ls_docu-header-tdlreles = sy-saprl. lv_objname = ls_docu-header-tdname. CALL FUNCTION 'LXE_OBJ_DOKU_PUT_XSTRING' EXPORTING slang = mv_language tlang = ls_docu-language objtype = ls_docu-header-tdid objname = lv_objname header = ls_docu-header content = ls_docu-content IMPORTING change_flag = lv_change_flag pstatus = lv_error_status. ENDLOOP. ENDMETHOD. METHOD get_field_rules. DATA: lt_fields TYPE TABLE OF string, lv_fields TYPE string, lv_table TYPE tabname, lv_field TYPE string, lv_rule TYPE string, lv_rule_iter TYPE string, lv_fill_rule TYPE zif_abapgit_field_rules=>ty_fill_rule, lv_prefix TYPE fieldname, lv_suffix TYPE fieldname. ro_result = zcl_abapgit_field_rules=>create( ). " Many tables and fields with date,time,user so we encode them APPEND 'DM02L,FL,DTU' TO lt_fields. APPEND 'DM02T,L,DTU' TO lt_fields. APPEND 'DM03S,FL,DTU' TO lt_fields. APPEND 'DM25L,FL,DTU' TO lt_fields. APPEND 'DM26L,FL,DTU' TO lt_fields. APPEND 'DM42S,FL,DTU' TO lt_fields. APPEND 'DM42T,L,DTU' TO lt_fields. APPEND 'DM43T,L,DU' TO lt_fields. APPEND 'DM45L,FL,DTU' TO lt_fields. APPEND 'DM45T,L,DTU' TO lt_fields. APPEND 'DM46S,FL,DTU' TO lt_fields. LOOP AT lt_fields INTO lv_fields. SPLIT lv_fields AT ',' INTO lv_table lv_field lv_rule_iter. DO strlen( lv_field ) TIMES. CASE lv_field(1). WHEN 'F'. lv_prefix = 'FST'. WHEN 'L'. lv_prefix = 'LST'. ENDCASE. lv_rule = lv_rule_iter. DO strlen( lv_rule ) TIMES. CASE lv_rule(1). WHEN 'D'. lv_suffix = 'DATE'. lv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date. WHEN 'T'. lv_suffix = 'TIME'. lv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time. WHEN 'U'. lv_suffix = 'USER'. lv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user. ENDCASE. ro_result->add( iv_table = lv_table iv_field = lv_prefix && lv_suffix iv_fill_rule = lv_fill_rule ). SHIFT lv_rule LEFT. ENDDO. SHIFT lv_field LEFT. ENDDO. ENDLOOP. ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD is_name_permitted. " It is unlikely that a serialized entity will have a name that is not permitted. However " there may be reservations in TRESE which could prohibit the entity name. " So to be safe, we check. Tx SD11 does this check. CALL FUNCTION 'SDU_SAA_CHECK' EXPORTING obj_name = ms_item-obj_name obj_type = ms_item-obj_type EXCEPTIONS wrong_type = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD serialize_docu_uen. DATA lt_docu TYPE ty_docu_lines. lt_docu = serialize_docu_xxxx( 'UENC' ). io_xml->add( iv_name = 'DOCU_UENC' ig_data = lt_docu ). lt_docu = serialize_docu_xxxx( 'UEND' ). io_xml->add( iv_name = 'DOCU_UEND' ig_data = lt_docu ). lt_docu = serialize_docu_xxxx( 'UENE' ). io_xml->add( iv_name = 'DOCU_UENE' ig_data = lt_docu ). ENDMETHOD. METHOD serialize_docu_url. DATA lt_docu TYPE ty_docu_lines. lt_docu = serialize_docu_xxxx( 'URL1' ). io_xml->add( iv_name = 'DOCU_URL1' ig_data = lt_docu ). lt_docu = serialize_docu_xxxx( 'URL2' ). io_xml->add( iv_name = 'DOCU_URL2' ig_data = lt_docu ). lt_docu = serialize_docu_xxxx( 'URLC' ). io_xml->add( iv_name = 'DOCU_URLC' ig_data = lt_docu ). ENDMETHOD. METHOD serialize_docu_usp. DATA lt_docu TYPE ty_docu_lines. lt_docu = serialize_docu_xxxx( 'USPD' ). io_xml->add( iv_name = 'DOCU_USPD' ig_data = lt_docu ). ENDMETHOD. METHOD serialize_docu_xxxx. DATA ls_docu TYPE ty_docu. DATA ls_dokvl TYPE dokvl. DATA lt_dokvl TYPE STANDARD TABLE OF dokvl. DATA lv_error_status TYPE lxestatprc. DATA lv_objname TYPE lxeobjname. ls_dokvl-object = build_text_name( iv_id ). SELECT id object langu FROM dokvl INTO CORRESPONDING FIELDS OF TABLE lt_dokvl WHERE id = c_text_object_type AND object LIKE ls_dokvl-object ORDER BY id object langu ##TOO_MANY_ITAB_FIELDS. LOOP AT lt_dokvl INTO ls_dokvl. ls_docu-language = ls_dokvl-langu. lv_objname = ls_dokvl-object. " You are reminded that this function gets the most recent version of the texts. CALL FUNCTION 'LXE_OBJ_DOKU_GET_XSTRING' EXPORTING lang = ls_docu-language objtype = c_text_object_type objname = lv_objname IMPORTING header = ls_docu-header content = ls_docu-content itf = ls_docu-itf pstatus = lv_error_status. CHECK lv_error_status = 'S'. "Success " Administrative information is not CLEAR ls_docu-header-tdfuser. CLEAR ls_docu-header-tdfdate. CLEAR ls_docu-header-tdftime. CLEAR ls_docu-header-tdfreles. CLEAR ls_docu-header-tdluser. CLEAR ls_docu-header-tdldate. CLEAR ls_docu-header-tdltime. CLEAR ls_docu-header-tdlreles. APPEND ls_docu TO rt_result. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE lstuser INTO rv_user FROM dm02l WHERE entid = mv_entity_id AND as4local = c_active_state. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. " The deletion of the documentation occurs before the deletion of " the associated tables - otherwise we don't know what " documentation needs deletion delete_docu_uen( ). delete_docu_url( ). delete_docu_usp( ). " the deletion of the tables of the entity get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. " Is the entity type name compliant with naming conventions? " Entity Type have their own conventions. is_name_permitted( ). get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). deserialize_docu_uen( io_xml ). deserialize_docu_url( io_xml ). deserialize_docu_usp( io_xml ). " You are reminded that entity types are not relevant for activation. ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDUM' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " The function module listed below do not open a new window - so we revert to BDC. " CALL FUNCTION 'SDU_MODEL_SHOW' " CALL FUNCTION 'RS_TOOL_ACCESS' DATA lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMUD00'. -dynpro = '0100'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=SHOW'. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'RSUD3-ENTI'. -fval = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'RSUD3-OBJ_KEY'. -fval = ms_item-obj_name. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SD11' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). serialize_docu_uen( io_xml ). serialize_docu_url( io_xml ). serialize_docu_usp( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_udmo IMPLEMENTATION. METHOD access_free. " Release the lock on the object. CALL FUNCTION 'RS_ACCESS_PERMISSION' EXPORTING mode = 'FREE' object = ms_object_type object_class = c_transport_object_class EXCEPTIONS canceled_in_corr = 1 enqueued_by_user = 2 enqueue_system_failure = 3 illegal_parameter_values = 4 locked_by_author = 5 no_modify_permission = 6 no_show_permission = 7 permission_failure = 8 request_language_denied = 9 OTHERS = 10. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ELSE. rv_result = abap_true. ENDIF. ENDMETHOD. METHOD access_modify. * You are reminded that mode modify is the same as insert, with one important difference: * Mode INSERT is intended for newly created objects, for which a TADIR entry does not yet * exist. In that case, the system shows a pop-up for the entry of the package, which isn't * desirable when the SAPGUI is not available. * In the context of abapGit, the package is known. CALL FUNCTION 'RS_ACCESS_PERMISSION' EXPORTING authority_check = abap_true global_lock = abap_true mode = 'MODIFY' object = ms_object_type object_class = c_transport_object_class EXCEPTIONS canceled_in_corr = 1 enqueued_by_user = 2 enqueue_system_failure = 3 illegal_parameter_values = 4 locked_by_author = 5 no_modify_permission = 6 no_show_permission = 7 permission_failure = 8 request_language_denied = 9 OTHERS = 10. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ELSE. rv_result = abap_true. ENDIF. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). " Conversion to Data model mv_data_model = is_item-obj_name. " Default activation state is active mv_activation_state = c_active_state. " Derive the data model's text object mv_text_object = 'UDMD' && is_item-obj_name. " And set the text object to active mv_text_object+30(1) = mv_activation_state. mv_lxe_text_name = mv_text_object. " Correction and Transport System object ms_object_type-objtype = c_correction_object_type. ms_object_type-objname = is_item-obj_name. ENDMETHOD. METHOD corr_insert. DATA lv_obj_name TYPE tadir-obj_name. " You are reminded that SUDM - Data Model has no part objects e.g. no LIMU " Therefore global lock is always appropriate " You are reminded that the main language (in TADIR) is taken from MV_LANGUAGE. lv_obj_name = ms_object_type. zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( iv_object = c_transport_object_class iv_obj_name = lv_obj_name iv_package = iv_package iv_language = mv_language ). ENDMETHOD. METHOD deserialize_entities. DATA lt_udmo_entities TYPE STANDARD TABLE OF dm41s WITH DEFAULT KEY. DATA ls_udmo_entity LIKE LINE OF lt_udmo_entities. io_xml->read( EXPORTING iv_name = 'UDMO_ENTITIES' CHANGING cg_data = lt_udmo_entities ). LOOP AT lt_udmo_entities INTO ls_udmo_entity. CALL FUNCTION 'SDU_DMO_ENT_PUT' EXPORTING object = ls_udmo_entity EXCEPTIONS OTHERS = 0. ENDLOOP. ENDMETHOD. METHOD deserialize_long_texts. DATA BEGIN OF ls_udmo_long_text. DATA language TYPE dm40t-sprache. DATA header TYPE thead. DATA content TYPE xstring. DATA END OF ls_udmo_long_text. DATA lt_udmo_long_texts LIKE STANDARD TABLE OF ls_udmo_long_text. DATA ls_header TYPE thead. io_xml->read( EXPORTING iv_name = 'UDMO_LONG_TEXTS' CHANGING cg_data = lt_udmo_long_texts ). LOOP AT lt_udmo_long_texts INTO ls_udmo_long_text. ls_udmo_long_text-header-tdfuser = sy-uname. ls_udmo_long_text-header-tdfdate = sy-datum. ls_udmo_long_text-header-tdftime = sy-uzeit. " You are reminded that the target system may already have some texts in " existence. So we determine the highest existent version. CLEAR ls_header-tdversion. SELECT MAX( dokversion ) INTO ls_header-tdversion FROM dokhl WHERE id = c_lxe_text_type AND object = mv_text_object AND langu = ls_udmo_long_text-language. " Increment the version ls_header-tdversion = ls_header-tdversion + 1. ls_udmo_long_text-header-tdversion = ls_header-tdversion. " This function module takes care of the variation in text processing between various objects. CALL FUNCTION 'LXE_OBJ_DOKU_PUT_XSTRING' EXPORTING slang = mv_language tlang = ls_udmo_long_text-language objtype = c_lxe_text_type objname = mv_lxe_text_name header = ls_udmo_long_text-header content = ls_udmo_long_text-content. ENDLOOP. ENDMETHOD. METHOD deserialize_model. DATA ls_dm40l TYPE dm40l. io_xml->read( EXPORTING iv_name = 'DM40L' CHANGING cg_data = ls_dm40l ). " See SDU_MODEL_PUT GET TIME. ls_dm40l-flg_frame = abap_true. ls_dm40l-fstdate = sy-datum. ls_dm40l-fsttime = sy-uzeit. ls_dm40l-fstuser = sy-uname. ls_dm40l-lstdate = sy-datum. ls_dm40l-lsttime = sy-uzeit. ls_dm40l-lstuser = sy-uname. MODIFY dm40l FROM ls_dm40l. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from SDU_MODEL_PUT' ). ENDIF. ENDMETHOD. METHOD deserialize_short_texts. DATA lt_udmo_texts TYPE STANDARD TABLE OF ty_udmo_text_type WITH DEFAULT KEY. DATA ls_udmo_text TYPE ty_udmo_text_type. DATA ls_dm40t TYPE dm40t. " Deserialize the XML io_xml->read( EXPORTING iv_name = 'UDMO_TEXTS' CHANGING cg_data = lt_udmo_texts ). " For every text provided LOOP AT lt_udmo_texts INTO ls_udmo_text. " Does the text already exist? This is the same logic as used " in the FM SDU_MODEL_PUT SELECT SINGLE * FROM dm40t INTO ls_dm40t WHERE sprache = ls_udmo_text-sprache AND dmoid = ls_udmo_text-dmoid AND as4local = mv_activation_state. IF sy-subrc = 0. " There is already an active description for this language " but the provided description differs IF ls_dm40t-langbez <> ls_udmo_text-langbez. ls_dm40t-langbez = ls_udmo_text-langbez. ls_dm40t-lstdate = sy-datum. ls_dm40t-lsttime = sy-uzeit. ls_dm40t-lstuser = sy-uname. MODIFY dm40t FROM ls_dm40t. ENDIF. ELSE. " There is no EXISTING active description in this language ls_dm40t-as4local = ls_udmo_text-as4local. ls_dm40t-dmoid = ls_udmo_text-dmoid. ls_dm40t-langbez = ls_udmo_text-langbez. ls_dm40t-lstdate = sy-datum. ls_dm40t-lsttime = sy-uzeit. ls_dm40t-lstuser = sy-uname. ls_dm40t-sprache = ls_udmo_text-sprache. INSERT dm40t FROM ls_dm40t. ENDIF. ENDLOOP. ENDMETHOD. METHOD is_name_permitted. " It is unlikely that a serialized data model will have a name that is not permitted. However " there may be reservations in TRESE which could prohibit the data model name. " So to be safe, we check. Tx SD11 does this check. CALL FUNCTION 'SDU_SAA_CHECK' EXPORTING obj_name = ms_object_type-objname obj_type = ms_object_type-objtype EXCEPTIONS wrong_type = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD serialize_entities. DATA lt_udmo_entities TYPE STANDARD TABLE OF dm41s WITH DEFAULT KEY. FIELD-SYMBOLS TYPE dm41s. SELECT * FROM dm41s INTO TABLE lt_udmo_entities WHERE dmoid = mv_data_model AND as4local = mv_activation_state ORDER BY PRIMARY KEY. LOOP AT lt_udmo_entities ASSIGNING . " You are reminded that administrative information, such as last changed by user, date, time is not serialized. CLEAR -lstuser. CLEAR -lstdate. CLEAR -lsttime. CLEAR -fstuser. CLEAR -fstdate. CLEAR -fsttime. ENDLOOP. " You are reminded that descriptions in other languages do not have to be in existence, although they may. IF lines( lt_udmo_entities ) > 0. io_xml->add( iv_name = 'UDMO_ENTITIES' ig_data = lt_udmo_entities ). ENDIF. ENDMETHOD. METHOD serialize_long_texts. " The model has short texts in multiple languages. These are held in DM40T. " The model has a long description also in a main language, with other long descriptions " maintained as translations using SE63 Translation Editor. All of these long texts are held in DOK* TYPES BEGIN OF ty_language_type. TYPES language TYPE dm40t-sprache. TYPES END OF ty_language_type. DATA BEGIN OF ls_udmo_long_text. DATA language TYPE dm40t-sprache. DATA header TYPE thead. DATA content TYPE xstring. DATA END OF ls_udmo_long_text. DATA lt_udmo_long_texts LIKE STANDARD TABLE OF ls_udmo_long_text. DATA lt_udmo_languages TYPE STANDARD TABLE OF ty_language_type. DATA ls_udmo_language LIKE LINE OF lt_udmo_languages. DATA: lv_error_status TYPE lxestatprc. " In which languages are the short texts are maintained. SELECT sprache AS language FROM dm40t INTO TABLE lt_udmo_languages WHERE dmoid = mv_data_model AND as4local = mv_activation_state ORDER BY sprache ASCENDING. "#EC CI_NOFIRST " For every language for which a short text is maintained, LOOP AT lt_udmo_languages INTO ls_udmo_language. CLEAR ls_udmo_long_text. CLEAR lv_error_status. ls_udmo_long_text-language = ls_udmo_language-language. " You are reminded that this function gets the most recent version of the texts. CALL FUNCTION 'LXE_OBJ_DOKU_GET_XSTRING' EXPORTING lang = ls_udmo_language-language objtype = c_lxe_text_type objname = mv_lxe_text_name IMPORTING header = ls_udmo_long_text-header content = ls_udmo_long_text-content pstatus = lv_error_status. CHECK lv_error_status = 'S'. "Success " Administrative information is not serialized CLEAR ls_udmo_long_text-header-tdfuser. CLEAR ls_udmo_long_text-header-tdfdate. CLEAR ls_udmo_long_text-header-tdftime. CLEAR ls_udmo_long_text-header-tdluser. CLEAR ls_udmo_long_text-header-tdldate. CLEAR ls_udmo_long_text-header-tdltime. APPEND ls_udmo_long_text TO lt_udmo_long_texts. ENDLOOP. " You are reminded that long texts do not have to be in existence IF lines( lt_udmo_long_texts ) > 0. io_xml->add( iv_name = 'UDMO_LONG_TEXTS' ig_data = lt_udmo_long_texts ). ENDIF. ENDMETHOD. METHOD serialize_model. DATA ls_dm40l TYPE dm40l. " See SDU_MODEL_GET. SELECT SINGLE * FROM dm40l INTO ls_dm40l WHERE dmoid = mv_data_model AND as4local = mv_activation_state. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from UDMO - model serialisation' ). ENDIF. " You are reminded that administrative data is not serialized. CLEAR ls_dm40l-lstdate. CLEAR ls_dm40l-lsttime. CLEAR ls_dm40l-lstuser. CLEAR ls_dm40l-fstdate. CLEAR ls_dm40l-fsttime. CLEAR ls_dm40l-fstuser. io_xml->add( iv_name = 'DM40L' ig_data = ls_dm40l ). ENDMETHOD. METHOD serialize_short_texts. DATA lt_udmo_texts TYPE STANDARD TABLE OF ty_udmo_text_type WITH DEFAULT KEY. " You are reminded that administrative information, such as last changed by user, date, time is not serialized. " You are reminded that active short texts of all (existent) languages are serialized. SELECT sprache dmoid as4local langbez FROM dm40t INTO CORRESPONDING FIELDS OF TABLE lt_udmo_texts WHERE dmoid = mv_data_model AND as4local = mv_activation_state ORDER BY sprache ASCENDING. "#EC CI_NOFIRST " You are reminded that descriptions in other languages do not have to be in existence. IF lines( lt_udmo_texts ) > 0. io_xml->add( iv_name = 'UDMO_TEXTS' ig_data = lt_udmo_texts ). ENDIF. ENDMETHOD. METHOD update_tree. CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' EXPORTING object = mv_data_model operation = 'INSERT' type = c_correction_object_type. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE lstuser INTO rv_user FROM dm40l WHERE dmoid = mv_data_model AND as4local = mv_activation_state. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. * You are reminded that this function model checks for * - permissions * - locks * - connection to transport and correction system * - deletion of data model, model relations and all documentation * - update of object tree * - releasing of lock CALL FUNCTION 'RPY_DATAMODEL_DELETE' EXPORTING model_name = mv_data_model EXCEPTIONS cancelled = 1 permission_error = 2 not_found = 3 is_used = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. * You are reminded that this method checks for * - validity of data model name with regard to naming conventions * - permissions and locks * - connection to transport and correction system * - insert of data model, model relations and all documentation * - update of object tree * - releasing of lock * Is the data model name compliant with naming conventions? is_name_permitted( ). * Access Permission granted? access_modify( ). * Connection to transport and correction system corr_insert( iv_package ). * Insert the data model, relations and documentation TRY. deserialize_model( io_xml ). deserialize_entities( io_xml ). deserialize_short_texts( io_xml ). deserialize_long_texts( io_xml ). update_tree( ). access_free( ). CATCH zcx_abapgit_exception. access_free( ). zcx_abapgit_exception=>raise( 'Error in deserialization of UDMO' ). ENDTRY. " You are reminded that data models are not relevant for activation. ENDMETHOD. METHOD zif_abapgit_object~exists. " See Function Module SDU_MODEL_EXISTS SELECT COUNT( * ) FROM dm40l WHERE dmoid = mv_data_model AND as4local = mv_activation_state. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDUM' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " The function module listed below do not open a new window - so we revert to BDC. " CALL FUNCTION 'SDU_MODEL_SHOW' " CALL FUNCTION 'RS_TOOL_ACCESS' DATA lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMUD00'. -dynpro = '0100'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=SHOW'. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'RSUD3-DATM'. -fval = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'RSUD3-OBJ_KEY'. -fval = ms_item-obj_name. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SD11' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. serialize_model( io_xml ). serialize_entities( io_xml ). serialize_short_texts( io_xml ). serialize_long_texts( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ucsa IMPLEMENTATION. METHOD clear_dynamic_fields. FIELD-SYMBOLS: TYPE any. ASSIGN COMPONENT 'HEADER' OF STRUCTURE cg_complete_comm_assembly TO . ASSERT sy-subrc = 0. clear_field( EXPORTING iv_fieldname = 'CREATEDBY' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'CREATEDON' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'CREATEDAT' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'CHANGEDBY' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'CHANGEDON' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'CHANGEDAT' CHANGING cg_header = ). ENDMETHOD. METHOD clear_field. FIELD-SYMBOLS: TYPE any. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cg_header TO . ASSERT sy-subrc = 0. CLEAR . ENDMETHOD. METHOD get_persistence. CALL METHOD ('CL_UCON_SA_DB_PERSIST')=>('IF_UCON_SA_PERSIST~GET_INSTANCE') EXPORTING id = iv_id RECEIVING instance = ro_persistence. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_id TYPE ty_id, lx_root TYPE REF TO cx_root, lo_persistence TYPE REF TO object, lr_complete_comm_assembly TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any. lv_id = ms_item-obj_name. TRY. CREATE DATA lr_complete_comm_assembly TYPE ('UCONSERVASCOMPLETE'). ASSIGN lr_complete_comm_assembly->* TO . ASSERT sy-subrc = 0. lo_persistence = get_persistence( lv_id ). CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~LOAD') EXPORTING version = c_version-active language = mv_language IMPORTING sa = . ASSIGN COMPONENT 'CHANGEDBY' OF STRUCTURE TO . IF sy-subrc = 0. rv_user = . ENDIF. CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_id TYPE ty_id, lx_root TYPE REF TO cx_root, lv_text TYPE string, lo_persistence TYPE REF TO object. TRY. lv_id = ms_item-obj_name. lo_persistence = get_persistence( lv_id ). CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~DELETE') EXPORTING version = c_version-active. CATCH cx_root INTO lx_root. lv_text = lx_root->get_text( ). zcx_abapgit_exception=>raise( lv_text ). ENDTRY. tadir_delete( ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_id TYPE ty_id, lx_root TYPE REF TO cx_root, lv_text TYPE string, lo_persistence TYPE REF TO object, lr_complete_comm_assembly TYPE REF TO data. FIELD-SYMBOLS: TYPE any. TRY. CREATE DATA lr_complete_comm_assembly TYPE ('UCONSERVASCOMPLETE'). ASSIGN lr_complete_comm_assembly->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'UCSA' CHANGING cg_data = ). lv_id = ms_item-obj_name. lo_persistence = get_persistence( lv_id ). CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~CREATE'). CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~SAVE') EXPORTING sa = version = c_version-active. tadir_insert( iv_package ). CATCH cx_root INTO lx_root. lv_text = lx_root->get_text( ). zcx_abapgit_exception=>raise( lv_text ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_id TYPE ty_id, lo_persistence TYPE REF TO object. lv_id = ms_item-obj_name. TRY. lo_persistence = get_persistence( lv_id ). " Interface IF_UCON_SA_PERSIST and other objects are not present " in lower NetWeaver releases. Therefore we have to call them " dynamically to be downward compatible. CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~LOAD') EXPORTING version = c_version-active language = mv_language. CATCH cx_root. rv_bool = abap_false. RETURN. ENDTRY. rv_bool = abap_true. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_id TYPE ty_id, lx_root TYPE REF TO cx_root, lo_persistence TYPE REF TO object, lr_complete_comm_assembly TYPE REF TO data. FIELD-SYMBOLS: TYPE any. lv_id = ms_item-obj_name. TRY. CREATE DATA lr_complete_comm_assembly TYPE ('UCONSERVASCOMPLETE'). ASSIGN lr_complete_comm_assembly->* TO . ASSERT sy-subrc = 0. lo_persistence = get_persistence( lv_id ). CALL METHOD lo_persistence->('IF_UCON_SA_PERSIST~LOAD') EXPORTING version = c_version-active language = mv_language IMPORTING sa = . clear_dynamic_fields( CHANGING cg_complete_comm_assembly = ). io_xml->add( iv_name = 'UCSA' ig_data = ). CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_type IMPLEMENTATION. METHOD create. DATA: lv_progname TYPE reposrc-progname, lv_typegroup TYPE rsedd0-typegroup. lv_typegroup = ms_item-obj_name. CALL FUNCTION 'RS_DD_TYGR_INSERT_SOURCES' EXPORTING typegroupname = lv_typegroup ddtext = iv_ddtext corrnum = '' devclass = iv_devclass TABLES source = it_source EXCEPTIONS already_exists = 1 not_executed = 2 permission_failure = 3 object_not_specified = 4 illegal_name = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CONCATENATE c_prefix lv_typegroup INTO lv_progname. UPDATE progdir SET uccheck = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard WHERE name = lv_progname. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error setting uccheck' ). ENDIF. ENDMETHOD. METHOD read. DATA: lv_typdname TYPE rsedd0-typegroup, lt_psmodisrc TYPE TABLE OF smodisrc, lt_psmodilog TYPE TABLE OF smodilog, lt_ptrdir TYPE TABLE OF trdir. SELECT SINGLE ddtext FROM ddtypet INTO ev_ddtext WHERE typegroup = ms_item-obj_name AND ddlanguage = mv_language. lv_typdname = ms_item-obj_name. " Get active version, ignore errors if not found CALL FUNCTION 'TYPD_GET_OBJECT' EXPORTING typdname = lv_typdname TABLES psmodisrc = lt_psmodisrc psmodilog = lt_psmodilog psource = et_source ptrdir = lt_ptrdir EXCEPTIONS version_not_found = 1 reps_not_exist = 2 OTHERS = 3 ##FM_SUBRC_OK. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lv_prog TYPE progname. CONCATENATE '%_C' ms_item-obj_name INTO lv_prog. SELECT SINGLE unam FROM reposrc INTO rv_user WHERE progname = lv_prog AND r3state = 'A'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. delete_ddic( 'G' ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_ddtext TYPE ddtypet-ddtext, lt_source TYPE abaptxt255_tab, lv_progname TYPE reposrc-progname, lv_typegroup TYPE rsedd0-typegroup. lv_typegroup = ms_item-obj_name. io_xml->read( EXPORTING iv_name = 'DDTEXT' CHANGING cg_data = lv_ddtext ). lt_source = mo_files->read_abap( ). IF zif_abapgit_object~exists( ) = abap_false. create( iv_ddtext = lv_ddtext it_source = lt_source iv_devclass = iv_package ). ELSE. CONCATENATE c_prefix lv_typegroup INTO lv_progname. zcl_abapgit_factory=>get_sap_report( )->insert_report( iv_name = lv_progname iv_package = iv_package iv_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard it_source = lt_source ). ENDIF. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_progname TYPE progname, lv_state TYPE r3state. lv_progname = |%_C{ ms_item-obj_name }|. SELECT SINGLE state FROM progdir INTO lv_state WHERE name = lv_progname. "#EC CI_NOORDER IF lv_state IS NOT INITIAL. rv_bool = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECT=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_ddtext TYPE ddtypet-ddtext, lt_source TYPE abaptxt255_tab. read( IMPORTING ev_ddtext = lv_ddtext et_source = lt_source ). IF lt_source IS INITIAL. RETURN. ENDIF. io_xml->add( iv_name = 'DDTEXT' ig_data = lv_ddtext ). mo_files->add_abap( lt_source ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ttyp IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. SELECT SINGLE as4user FROM dd40l INTO rv_user WHERE typename = ms_item-obj_name AND as4local = 'A'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. delete_ddic( 'A' ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_name TYPE ddobjname, lt_dd42v TYPE dd42v_tab, lt_dd43v TYPE dd43v_tab, ls_dd40v TYPE dd40v, lv_msg TYPE string. io_xml->read( EXPORTING iv_name = 'DD40V' CHANGING cg_data = ls_dd40v ). io_xml->read( EXPORTING iv_name = 'DD42V' CHANGING cg_data = lt_dd42v ). io_xml->read( EXPORTING iv_name = 'DD43V' CHANGING cg_data = lt_dd43v ). corr_insert( iv_package = iv_package ig_object_class = 'DICT' ). lv_name = ms_item-obj_name. " type conversion CALL FUNCTION 'DDIF_TTYP_PUT' EXPORTING name = lv_name dd40v_wa = ls_dd40v TABLES dd42v_tab = lt_dd42v dd43v_tab = lt_dd43v EXCEPTIONS ttyp_not_found = 1 name_inconsistent = 2 ttyp_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. lv_msg = |Error in DDIF_TTYP_PUT on object { lv_name }|. CASE sy-subrc. WHEN 1. lv_msg = lv_msg && | (TTYP_NOT_FOUND)|. WHEN 2. lv_msg = lv_msg && | (NAME_INCONSISTENT)|. WHEN 3. lv_msg = lv_msg && | (TTYP_INCONSISTENT)|. WHEN 4. lv_msg = lv_msg && | (PUT_FAILURE)|. WHEN 5. lv_msg = lv_msg && | (PUT_REFUSED)|. WHEN OTHERS. ENDCASE. zcx_abapgit_exception=>raise( lv_msg ). ENDIF. deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_ttyp ). zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_typename TYPE dd40l-typename. SELECT SINGLE typename FROM dd40l INTO lv_typename WHERE typename = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECT=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_name TYPE ddobjname, lv_state TYPE ddgotstate, lt_dd42v TYPE dd42v_tab, lt_dd43v TYPE dd43v_tab, ls_dd40v TYPE dd40v. lv_name = ms_item-obj_name. CALL FUNCTION 'DDIF_TTYP_GET' EXPORTING name = lv_name state = 'A' langu = mv_language IMPORTING gotstate = lv_state dd40v_wa = ls_dd40v TABLES dd42v_tab = lt_dd42v dd43v_tab = lt_dd43v EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF ls_dd40v IS INITIAL OR lv_state <> 'A'. RETURN. ENDIF. CLEAR: ls_dd40v-as4user, ls_dd40v-as4date, ls_dd40v-as4time. IF NOT ls_dd40v-rowkind IS INITIAL. CLEAR ls_dd40v-typelen. ENDIF. io_xml->add( iv_name = 'DD40V' ig_data = ls_dd40v ). io_xml->add( iv_name = 'DD42V' ig_data = lt_dd42v ). io_xml->add( iv_name = 'DD43V' ig_data = lt_dd43v ). serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_ttyp ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_tran IMPLEMENTATION. METHOD add_data. DATA: ls_bcdata LIKE LINE OF mt_bcdata. ls_bcdata-fnam = iv_fnam. ls_bcdata-fval = iv_fval. APPEND ls_bcdata TO mt_bcdata. ENDMETHOD. METHOD call_se93. DATA: lt_message TYPE STANDARD TABLE OF bdcmsgcoll. DATA lv_msg TYPE string. FIELD-SYMBOLS: TYPE bdcmsgcoll. CALL FUNCTION 'ABAP4_CALL_TRANSACTION' EXPORTING tcode = 'SE93' mode_val = 'N' TABLES using_tab = mt_bcdata mess_tab = lt_message EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error deserializing { ms_item-obj_type } { ms_item-obj_name }| ). ENDIF. LOOP AT lt_message ASSIGNING WHERE msgtyp CA 'EAX'. MESSAGE ID -msgid TYPE -msgtyp NUMBER -msgnr WITH -msgv1 -msgv2 -msgv3 -msgv4 INTO lv_msg. zcx_abapgit_exception=>raise_t100( ). ENDLOOP. ENDMETHOD. METHOD clear_functiongroup_globals. TYPES ty_param_vari TYPE abap_bool. DATA lt_error_list TYPE STANDARD TABLE OF rsmp_check WITH DEFAULT KEY. FIELD-SYMBOLS TYPE ty_param_vari. " only way to clear global fields in function group CALL FUNCTION 'RS_TRANSACTION_INCONSISTENCIES' EXPORTING transaction_code = 'ZTHISTCODENEVEREXIST' TABLES error_list = lt_error_list EXCEPTIONS object_not_found = 1 OTHERS = 2. IF sy-subrc <> 0. "Expected - fine " but there is no other way to clear this field ASSIGN ('(SAPLSEUK)PARAM_VARI') TO . IF sy-subrc = 0. CLEAR . ENDIF. ENDIF. ENDMETHOD. METHOD deserialize_oo_transaction. " You should remember that we don't use batch input just for fun, " but because FM RPY_TRANSACTION_INSERT doesn't support OO transactions. DATA: ls_bcdata TYPE bdcdata. CLEAR mt_bcdata. ls_bcdata-program = 'SAPLSEUK'. ls_bcdata-dynpro = '0390'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO mt_bcdata. add_data( iv_fnam = 'TSTC-TCODE' iv_fval = is_tstc-tcode ). IF zif_abapgit_object~exists( ) = abap_true. add_data( iv_fnam = 'BDC_OKCODE' iv_fval = '=CHNG' ). ELSE. add_data( iv_fnam = 'BDC_OKCODE' iv_fval = '=ADD' ). ENDIF. ls_bcdata-program = 'SAPLSEUK'. ls_bcdata-dynpro = '0300'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO mt_bcdata. add_data( iv_fnam = 'TSTCT-TTEXT' iv_fval = is_tstct-ttext ). add_data( iv_fnam = 'RSSTCD-S_CLASS' iv_fval = 'X' ). add_data( iv_fnam = 'BDC_OKCODE' iv_fval = '=ENTR' ). ls_bcdata-program = 'SAPLSEUK'. ls_bcdata-dynpro = '0360'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO mt_bcdata. add_data( iv_fnam = 'RSSTCD-S_TRFRAME' iv_fval = is_rsstcd-s_trframe ). add_data( iv_fnam = 'RSSTCD-S_UPDTASK' iv_fval = is_rsstcd-s_updtask ). add_data( iv_fnam = 'BDC_OKCODE' iv_fval = '=TR_FRAMEWORK' ). ls_bcdata-program = 'SAPLSEUK'. ls_bcdata-dynpro = '0360'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO mt_bcdata. add_data( iv_fnam = 'RSSTCD-CLASSNAME' iv_fval = is_rsstcd-classname ). add_data( iv_fnam = 'RSSTCD-METHOD' iv_fval = is_rsstcd-method ). IF is_rsstcd-s_local IS NOT INITIAL. add_data( iv_fnam = 'RSSTCD-S_LOCAL' iv_fval = is_rsstcd-s_local ). ENDIF. IF is_rsstcd-s_updlok IS NOT INITIAL. add_data( iv_fnam = 'RSSTCD-S_UPDLOK' iv_fval = is_rsstcd-s_updlok ). ENDIF. add_data( iv_fnam = 'TSTC-PGMNA' iv_fval = is_tstc-pgmna ). IF is_tstcc-s_webgui = '2'. add_data( iv_fnam = 'G_IAC_EWT' iv_fval = abap_true ). add_data( iv_fnam = 'BDC_OKCODE' iv_fval = 'MAKE_PROFI' ). ls_bcdata-program = 'SAPLSEUK'. ls_bcdata-dynpro = '0360'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO mt_bcdata. ELSEIF is_tstcc-s_webgui IS NOT INITIAL. add_data( iv_fnam = 'TSTCC-S_WEBGUI' iv_fval = is_tstcc-s_webgui ). ENDIF. IF is_tstcc-s_pervas IS NOT INITIAL. add_data( iv_fnam = 'TSTCC-S_PERVAS' iv_fval = is_tstcc-s_pervas ). ENDIF. IF is_tstcc-s_service IS NOT INITIAL. add_data( iv_fnam = 'TSTCC-S_SERVICE' iv_fval = is_tstcc-s_service ). ENDIF. IF is_tstcc-s_platin IS NOT INITIAL. add_data( iv_fnam = 'TSTCC-S_PLATIN' iv_fval = is_tstcc-s_platin ). ENDIF. IF is_tstcc-s_win32 IS NOT INITIAL. add_data( iv_fnam = 'TSTCC-S_WIN32' iv_fval = is_tstcc-s_win32 ). ENDIF. add_data( iv_fnam = 'BDC_OKCODE' iv_fval = '=WB_SAVE' ). ls_bcdata-program = 'SAPLSTRD'. ls_bcdata-dynpro = '0100'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO mt_bcdata. add_data( iv_fnam = 'KO007-L_DEVCLASS' iv_fval = iv_package ). add_data( iv_fnam = 'BDC_OKCODE' iv_fval = '=ADD' ). ls_bcdata-program = 'BDC_OKCODE'. ls_bcdata-dynpro = '0360'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO mt_bcdata. add_data( iv_fnam = 'BDC_OKCODE' iv_fval = '=WB_BACK' ). ls_bcdata-program = 'BDC_OKCODE'. ls_bcdata-dynpro = '0360'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO mt_bcdata. add_data( iv_fnam = 'BDC_OKCODE' iv_fval = '=WB_BACK' ). call_se93( ). ENDMETHOD. METHOD deserialize_texts. DATA lt_tpool_i18n TYPE TABLE OF tstct. FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. " Read XML-files data ii_xml->read( EXPORTING iv_name = 'I18N_TPOOL' CHANGING cg_data = lt_tpool_i18n ). mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'SPRSL' CHANGING ct_tab = lt_tpool_i18n ). " Force t-code name (security reasons) LOOP AT lt_tpool_i18n ASSIGNING . -tcode = ms_item-obj_name. ENDLOOP. IF lines( lt_tpool_i18n ) > 0. MODIFY tstct FROM TABLE lt_tpool_i18n. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Update of t-code translations failed' ). ENDIF. ENDIF. ENDMETHOD. METHOD is_variant_transaction. rv_variant_transaction = boolc( is_tstcp-param(1) = '@' ). ENDMETHOD. METHOD save_authorizations. CONSTANTS: lc_hex_chk TYPE x VALUE '04'. DATA: ls_transaction TYPE tstc. transaction_read( EXPORTING iv_transaction = iv_transaction IMPORTING es_transaction = ls_transaction ). DELETE FROM tstca WHERE tcode = iv_transaction. IF ls_transaction IS NOT INITIAL. INSERT tstca FROM TABLE it_authorizations. ls_transaction-cinfo = ls_transaction-cinfo + lc_hex_chk. UPDATE tstc SET cinfo = ls_transaction-cinfo WHERE tcode = ls_transaction-tcode. ENDIF. ENDMETHOD. METHOD serialize_texts. DATA lt_tpool_i18n TYPE TABLE OF tstct. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. " Skip main language - it was already serialized " Don't serialize t-code itself SELECT sprsl ttext INTO CORRESPONDING FIELDS OF TABLE lt_tpool_i18n FROM tstct WHERE sprsl <> mv_language AND tcode = ms_item-obj_name ORDER BY sprsl ##TOO_MANY_ITAB_FIELDS. "#EC CI_GENBUFF mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'SPRSL' CHANGING ct_tab = lt_tpool_i18n ). IF lines( lt_tpool_i18n ) > 0. SORT lt_tpool_i18n BY sprsl ASCENDING. ii_xml->add( iv_name = 'I18N_TPOOL' ig_data = lt_tpool_i18n ). ENDIF. ENDMETHOD. METHOD set_oo_parameters. DATA: ls_param LIKE LINE OF it_rsparam. IF cs_rsstcd-call_tcode = c_oo_tcode. cs_rsstcd-s_trframe = c_true. LOOP AT it_rsparam INTO ls_param. CASE ls_param-field. WHEN c_oo_frclass. cs_rsstcd-classname = ls_param-value. WHEN c_oo_frmethod. cs_rsstcd-method = ls_param-value. WHEN c_oo_frupdtask. IF ls_param-value = c_oo_synchron. cs_rsstcd-s_upddir = c_true. cs_rsstcd-s_updtask = c_false. cs_rsstcd-s_updlok = c_false. ELSEIF ls_param-value = c_oo_asynchron. cs_rsstcd-s_upddir = c_false. cs_rsstcd-s_updtask = c_true. cs_rsstcd-s_updlok = c_false. ELSE. cs_rsstcd-s_upddir = c_false. cs_rsstcd-s_updtask = c_false. cs_rsstcd-s_updlok = c_true. ENDIF. ENDCASE. ENDLOOP. ENDIF. ENDMETHOD. METHOD shift_param. DATA: ls_param LIKE LINE OF ct_rsparam, lv_fdpos TYPE sy-fdpos, lv_length TYPE i. FIELD-SYMBOLS TYPE any. DO 254 TIMES. IF cs_tstcp-param = space. EXIT. ENDIF. CLEAR ls_param. IF cs_tstcp-param CA '='. CHECK sy-fdpos <> 0. ASSIGN cs_tstcp-param(sy-fdpos) TO . ls_param-field = . IF ls_param-field(1) = space. SHIFT ls_param-field. ENDIF. lv_fdpos = sy-fdpos + 1. SHIFT cs_tstcp-param BY lv_fdpos PLACES. IF cs_tstcp-param CA ';'. IF sy-fdpos <> 0. ASSIGN cs_tstcp-param(sy-fdpos) TO . ls_param-value = . IF ls_param-value(1) = space. SHIFT ls_param-value. ENDIF. ENDIF. lv_fdpos = sy-fdpos + 1. SHIFT cs_tstcp-param BY lv_fdpos PLACES. APPEND ls_param TO ct_rsparam. ELSE. lv_length = strlen( cs_tstcp-param ). CHECK lv_length > 0. ASSIGN cs_tstcp-param(lv_length) TO . ls_param-value = . IF ls_param-value(1) = space. SHIFT ls_param-value. ENDIF. lv_length = lv_length + 1. SHIFT cs_tstcp-param BY lv_length PLACES. APPEND ls_param TO ct_rsparam. ENDIF. ENDIF. ENDDO. ENDMETHOD. METHOD split_parameters. * see subroutine split_parameters in include LSEUKF01 DATA: lv_off TYPE i, lv_fdpos TYPE sy-fdpos, lv_param_beg TYPE i. CLEAR cs_rsstcd-s_vari. IF cs_tstcp-param(1) = '\'. " OO-Transaction without FR split_parameters_comp( EXPORTING ig_type = c_oo_program ig_param = cs_tstcp-param CHANGING cg_value = cs_tstc-pgmna ). split_parameters_comp( EXPORTING ig_type = c_oo_class ig_param = cs_tstcp-param CHANGING cg_value = cs_rsstcd-classname ). split_parameters_comp( EXPORTING ig_type = c_oo_method ig_param = cs_tstcp-param CHANGING cg_value = cs_rsstcd-method ). IF NOT cs_tstc-pgmna IS INITIAL. cs_rsstcd-s_local = c_true. ENDIF. RETURN. ELSEIF cs_tstcp-param(1) = '@'. " Transaction variant cs_rsstcd-s_vari = c_true. IF cs_tstcp-param(2) = '@@'. cs_rsstcd-s_ind_vari = c_true. lv_off = 2. ELSE. CLEAR cs_rsstcd-s_ind_vari. lv_off = 1. ENDIF. IF cs_tstcp-param CA ' '. ENDIF. lv_fdpos = sy-fdpos - lv_off. IF lv_fdpos > 0. cs_rsstcd-call_tcode = cs_tstcp-param+lv_off(sy-fdpos). lv_fdpos = lv_fdpos + 1 + lv_off. cs_rsstcd-variant = cs_tstcp-param+lv_fdpos. ENDIF. ELSEIF cs_tstcp-param(1) = '/'. cs_rsstcd-st_tcode = c_true. cs_rsstcd-st_prog = space. IF cs_tstcp-param+1(1) = '*'. cs_rsstcd-st_skip_1 = c_true. ELSE. CLEAR cs_rsstcd-st_skip_1. ENDIF. IF cs_tstcp-param CA ' '. ENDIF. lv_param_beg = sy-fdpos + 1. lv_fdpos = sy-fdpos - 2. IF lv_fdpos > 0. cs_rsstcd-call_tcode = cs_tstcp-param+2(lv_fdpos). ENDIF. SHIFT cs_tstcp-param BY lv_param_beg PLACES. ELSE. cs_rsstcd-st_tcode = space. cs_rsstcd-st_prog = c_true. ENDIF. shift_param( CHANGING ct_rsparam = ct_rsparam cs_tstcp = cs_tstcp ). set_oo_parameters( EXPORTING it_rsparam = ct_rsparam CHANGING cs_rsstcd = cs_rsstcd ). ENDMETHOD. METHOD split_parameters_comp. DATA: lv_off TYPE i. IF ig_param CS ig_type. lv_off = sy-fdpos + strlen( ig_type ). cg_value = ig_param+lv_off. IF cg_value CA '\'. CLEAR cg_value+sy-fdpos. ENDIF. ENDIF. ENDMETHOD. METHOD transaction_read. DATA: lt_tcodes TYPE TABLE OF tstc, lt_gui_attr TYPE TABLE OF tstcc. CLEAR: es_transaction, es_gui_attr. CALL FUNCTION 'RPY_TRANSACTION_READ' EXPORTING transaction = iv_transaction TABLES tcodes = lt_tcodes gui_attributes = lt_gui_attr EXCEPTIONS permission_error = 1 cancelled = 2 not_found = 3 object_not_found = 4 OTHERS = 5. IF sy-subrc = 4 OR sy-subrc = 3. RETURN. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. READ TABLE lt_tcodes INDEX 1 INTO es_transaction. ASSERT sy-subrc = 0. READ TABLE lt_gui_attr INDEX 1 INTO es_gui_attr. ASSERT sy-subrc = 0. ENDMETHOD. METHOD zif_abapgit_object~changed_by. " Changed-by-user is not stored in transaction metadata " Instead, use owner of last transport or object directory DATA lv_transport TYPE trkorr. lv_transport = zcl_abapgit_factory=>get_cts_api( )->get_transport_for_object( ms_item ). IF lv_transport IS NOT INITIAL. SELECT SINGLE as4user FROM e070 INTO rv_user WHERE trkorr = lv_transport. ELSE. SELECT SINGLE author FROM tadir INTO rv_user WHERE pgmid = 'R3TR' AND object = ms_item-obj_type AND obj_name = ms_item-obj_name. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_transaction TYPE tstc-tcode. lv_transaction = ms_item-obj_name. CALL FUNCTION 'RPY_TRANSACTION_DELETE' EXPORTING transaction = lv_transaction EXCEPTIONS not_excecuted = 1 object_not_found = 0 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. CONSTANTS: lc_hex_tra TYPE x VALUE '00', * lc_hex_men TYPE x VALUE '01', lc_hex_par TYPE x VALUE '02', lc_hex_rep TYPE x VALUE '80', * lc_hex_rpv TYPE x VALUE '10', lc_hex_obj TYPE x VALUE '08'. DATA: lv_dynpro TYPE d020s-dnum, ls_tstc TYPE tstc, lv_type TYPE rglif-docutype, ls_tstct TYPE tstct, ls_tstcc TYPE tstcc, ls_tstcp TYPE tstcp, lt_tstca TYPE ty_tstca, lt_param_values TYPE ty_param_values, ls_rsstcd TYPE rsstcd. IF zif_abapgit_object~exists( ) = abap_true. zif_abapgit_object~delete( iv_package = iv_package iv_transport = iv_transport ). ENDIF. io_xml->read( EXPORTING iv_name = 'TSTC' CHANGING cg_data = ls_tstc ). io_xml->read( EXPORTING iv_name = 'TSTCC' CHANGING cg_data = ls_tstcc ). io_xml->read( EXPORTING iv_name = 'TSTCT' CHANGING cg_data = ls_tstct ). io_xml->read( EXPORTING iv_name = 'TSTCP' CHANGING cg_data = ls_tstcp ). io_xml->read( EXPORTING iv_name = 'AUTHORIZATIONS' CHANGING cg_data = lt_tstca ). lv_dynpro = ls_tstc-dypno. IF ls_tstc-cinfo O lc_hex_rep. lv_type = c_variant_type-report. ELSEIF ls_tstc-cinfo O lc_hex_obj. lv_type = c_variant_type-object. ELSEIF ls_tstc-cinfo O lc_hex_par. IF is_variant_transaction( ls_tstcp ) = abap_true. lv_type = c_variant_type-variant. ELSE. lv_type = c_variant_type-parameters. ENDIF. ELSEIF ls_tstc-cinfo O lc_hex_tra. lv_type = c_variant_type-dialog. ELSE. zcx_abapgit_exception=>raise( 'Transaction, unknown CINFO' ). ENDIF. IF ls_tstcp IS NOT INITIAL. split_parameters( CHANGING ct_rsparam = lt_param_values cs_rsstcd = ls_rsstcd cs_tstcp = ls_tstcp cs_tstc = ls_tstc ). ENDIF. CASE lv_type. WHEN c_variant_type-object. deserialize_oo_transaction( iv_package = iv_package is_tstc = ls_tstc is_tstcc = ls_tstcc is_tstct = ls_tstct is_rsstcd = ls_rsstcd ). WHEN OTHERS. clear_functiongroup_globals( ). corr_insert( iv_package ). CALL FUNCTION 'RPY_TRANSACTION_INSERT' EXPORTING transaction = ls_tstc-tcode program = ls_tstc-pgmna dynpro = lv_dynpro language = mv_language development_class = iv_package transaction_type = lv_type shorttext = ls_tstct-ttext called_transaction = ls_rsstcd-call_tcode called_transaction_skip = ls_rsstcd-st_skip_1 variant = ls_rsstcd-variant cl_independend = ls_rsstcd-s_ind_vari html_enabled = ls_tstcc-s_webgui java_enabled = ls_tstcc-s_platin wingui_enabled = ls_tstcc-s_win32 suppress_corr_insert = abap_true TABLES param_values = lt_param_values EXCEPTIONS cancelled = 1 already_exist = 2 permission_error = 3 name_not_allowed = 4 name_conflict = 5 illegal_type = 6 object_inconsistent = 7 db_access_error = 8 OTHERS = 9. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDCASE. IF lt_tstca IS NOT INITIAL. save_authorizations( iv_transaction = ls_tstc-tcode it_authorizations = lt_tstca ). ENDIF. IF mo_i18n_params->is_lxe_applicable( ) = abap_false. deserialize_texts( io_xml ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_tcode TYPE tstc-tcode. SELECT SINGLE tcode FROM tstc INTO lv_tcode WHERE tcode = ms_item-obj_name. "#EC CI_GENBUFF rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' iv_argument = ms_item-obj_name iv_prefix = 'TN' ). ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPLSEUK'. -dynpro = '0390'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=SHOW'. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'TSTC-TCODE'. -fval = ms_item-obj_name. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SE93' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_transaction TYPE tstc-tcode, ls_tcode TYPE tstc, ls_tstct TYPE tstct, ls_tstcp TYPE tstcp, lt_tstca TYPE ty_tstca, ls_gui_attr TYPE tstcc. lv_transaction = ms_item-obj_name. transaction_read( EXPORTING iv_transaction = lv_transaction IMPORTING es_transaction = ls_tcode es_gui_attr = ls_gui_attr ). IF ls_tcode IS INITIAL. RETURN. ENDIF. SELECT SINGLE * FROM tstct INTO ls_tstct WHERE sprsl = mv_language AND tcode = lv_transaction. "#EC CI_SUBRC "#EC CI_GENBUFF SELECT SINGLE * FROM tstcp INTO ls_tstcp WHERE tcode = lv_transaction. "#EC CI_SUBRC "#EC CI_GENBUFF SELECT * FROM tstca INTO TABLE lt_tstca WHERE tcode = lv_transaction ORDER BY PRIMARY KEY. IF sy-subrc <> 0. CLEAR: lt_tstca. ENDIF. io_xml->add( iv_name = 'TSTC' ig_data = ls_tcode ). io_xml->add( iv_name = 'TSTCC' ig_data = ls_gui_attr ). io_xml->add( iv_name = 'TSTCT' ig_data = ls_tstct ). IF ls_tstcp IS NOT INITIAL. io_xml->add( iv_name = 'TSTCP' ig_data = ls_tstcp ). ENDIF. io_xml->add( iv_name = 'AUTHORIZATIONS' ig_data = lt_tstca ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. serialize_texts( io_xml ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_tobj IMPLEMENTATION. METHOD delete_extra. DELETE FROM tddat WHERE tabname = iv_tabname. DELETE FROM tvdir WHERE tabname = iv_tabname. DELETE FROM tvimf WHERE tabname = iv_tabname. ENDMETHOD. METHOD read_extra. SELECT SINGLE * FROM tddat INTO rs_tobj-tddat WHERE tabname = iv_tabname. SELECT SINGLE * FROM tvdir INTO rs_tobj-tvdir WHERE tabname = iv_tabname. CLEAR: rs_tobj-tvdir-gendate, rs_tobj-tvdir-gentime, rs_tobj-tvdir-devclass. SELECT * FROM tvimf INTO TABLE rs_tobj-tvimf WHERE tabname = iv_tabname ORDER BY PRIMARY KEY. ENDMETHOD. METHOD update_extra. DATA: lt_current_tvimf TYPE STANDARD TABLE OF tvimf. FIELD-SYMBOLS: TYPE tvimf. MODIFY tddat FROM is_tobj-tddat. MODIFY tvdir FROM is_tobj-tvdir. SELECT * INTO TABLE lt_current_tvimf FROM tvimf WHERE tabname = is_tobj-tddat-tabname ORDER BY PRIMARY KEY. LOOP AT lt_current_tvimf ASSIGNING . READ TABLE is_tobj-tvimf WITH KEY tabname = -tabname event = -event TRANSPORTING NO FIELDS. IF sy-subrc <> 0. DELETE FROM tvimf WHERE tabname = -tabname AND event = -event. ENDIF. ENDLOOP. MODIFY tvimf FROM TABLE is_tobj-tvimf. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_type_pos TYPE i. lv_type_pos = strlen( ms_item-obj_name ) - 1. SELECT SINGLE luser FROM objh INTO rv_user WHERE objectname = ms_item-obj_name(lv_type_pos) AND objecttype = ms_item-obj_name+lv_type_pos. "#EC CI_GENBUFF IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_objh TYPE objh, lv_type_pos TYPE i. lv_type_pos = strlen( ms_item-obj_name ) - 1. ls_objh-objectname = ms_item-obj_name(lv_type_pos). ls_objh-objecttype = ms_item-obj_name+lv_type_pos. IF ls_objh-objecttype = 'L'. zcx_abapgit_exception=>raise( |Use transaction SOBJ to delete transport objects { ls_objh-objectname }| ). ENDIF. CALL FUNCTION 'OBJ_GENERATE' EXPORTING iv_korrnum = iv_transport iv_objectname = ls_objh-objectname iv_objecttype = ls_objh-objecttype iv_maint_mode = 'D' EXCEPTIONS illegal_call = 1 object_not_found = 2 generate_error = 3 transport_error = 4 object_enqueue_failed = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. delete_extra( ls_objh-objectname ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_objh TYPE objh, ls_objt TYPE objt, lt_objs TYPE tt_objs, lt_objsl TYPE tt_objsl, lt_objm TYPE tt_objm, ls_tobj TYPE ty_tobj. io_xml->read( EXPORTING iv_name = 'OBJH' CHANGING cg_data = ls_objh ). io_xml->read( EXPORTING iv_name = 'OBJT' CHANGING cg_data = ls_objt ). io_xml->read( EXPORTING iv_name = 'OBJS' CHANGING cg_data = lt_objs ). io_xml->read( EXPORTING iv_name = 'OBJSL' CHANGING cg_data = lt_objsl ). io_xml->read( EXPORTING iv_name = 'OBJM' CHANGING cg_data = lt_objm ). CALL FUNCTION 'OBJ_GENERATE' EXPORTING iv_korrnum = iv_transport iv_objectname = ls_objh-objectname iv_objecttype = ls_objh-objecttype iv_maint_mode = 'I' iv_objecttext = ls_objt-ddtext iv_objcateg = ls_objh-objcateg iv_objtransp = ls_objh-objtransp iv_devclass = iv_package TABLES tt_v_obj_s = lt_objs tt_objm = lt_objm EXCEPTIONS illegal_call = 1 object_not_found = 2 generate_error = 3 transport_error = 4 object_enqueue_failed = 5 OTHERS = 6. IF sy-subrc <> 0. * TOBJ has to be saved/generated after the DDIC tables have been * activated - fixed with late deserialization zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'OBJ_SET_IMPORTABLE' EXPORTING iv_objectname = ls_objh-objectname iv_objecttype = ls_objh-objecttype iv_importable = ls_objh-importable EXCEPTIONS object_not_defined = 1 invalid = 2 transport_error = 3 object_enqueue_failed = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. * fm OBJ_GENERATE takes the defaults from the DDIC object * set OBJTRANSP directly, should be okay looking at the code in OBJ_SET_IMPORTABLE * locking has been done in OBJ_SET_IMPORTABLE plus recording of transport UPDATE objh SET objtransp = ls_objh-objtransp WHERE objectname = ls_objh-objectname AND objecttype = ls_objh-objecttype. io_xml->read( EXPORTING iv_name = 'TOBJ' CHANGING cg_data = ls_tobj ). ls_tobj-tvdir-gendate = sy-datum. ls_tobj-tvdir-gentime = sy-uzeit. ls_tobj-tvdir-devclass = iv_package. update_extra( ls_tobj ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_objectname TYPE objh-objectname, lv_type_pos TYPE i. lv_type_pos = strlen( ms_item-obj_name ) - 1. SELECT SINGLE objectname FROM objh INTO lv_objectname WHERE objectname = ms_item-obj_name(lv_type_pos) AND objecttype = ms_item-obj_name+lv_type_pos. "#EC CI_GENBUFF rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lv_object_name TYPE e071-obj_name. lv_object_name = ms_item-obj_name. CALL FUNCTION 'TR_OBJECT_JUMP_TO_TOOL' EXPORTING iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = lv_object_name EXCEPTIONS jump_not_possible = 1 OTHERS = 2. rv_exit = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_objh TYPE objh, ls_objt TYPE objt, lt_objs TYPE tt_objs, lt_objsl TYPE tt_objsl, lt_objm TYPE tt_objm, ls_tobj TYPE ty_tobj, lv_type_pos TYPE i. lv_type_pos = strlen( ms_item-obj_name ) - 1. ls_objh-objectname = ms_item-obj_name(lv_type_pos). ls_objh-objecttype = ms_item-obj_name+lv_type_pos. CALL FUNCTION 'CTO_OBJECT_GET' EXPORTING iv_objectname = ls_objh-objectname iv_objecttype = ls_objh-objecttype iv_language = mv_language iv_sel_objt = abap_true iv_sel_objs = abap_true iv_sel_objsl = abap_true iv_sel_objm = abap_true IMPORTING es_objh = ls_objh es_objt = ls_objt TABLES tt_objs = lt_objs tt_objsl = lt_objsl tt_objm = lt_objm EXCEPTIONS object_not_defined = 1 OTHERS = 2. IF sy-subrc = 1. RETURN. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CLEAR: ls_objh-luser, ls_objh-ldate. SORT lt_objs BY objectname objecttype tabname. SORT lt_objsl BY objectname objecttype trwcount. SORT lt_objm BY objectname objecttype method. io_xml->add( iv_name = 'OBJH' ig_data = ls_objh ). io_xml->add( iv_name = 'OBJT' ig_data = ls_objt ). io_xml->add( iv_name = 'OBJS' ig_data = lt_objs ). io_xml->add( iv_name = 'OBJSL' ig_data = lt_objsl ). io_xml->add( iv_name = 'OBJM' ig_data = lt_objm ). ls_tobj = read_extra( ls_objh-objectname ). IF ls_tobj-tvdir-detail = ``. " to prevent xslt serialization error, " force clear if numc field is empty CLEAR ls_tobj-tvdir-detail. ENDIF. io_xml->add( iv_name = 'TOBJ' ig_data = ls_tobj ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sxci IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. SELECT SINGLE uname FROM sxc_attr INTO rv_user WHERE imp_name = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_implementation_name TYPE rsexscrn-imp_name. lv_implementation_name = ms_item-obj_name. CALL FUNCTION 'SXO_IMPL_DELETE' EXPORTING imp_name = lv_implementation_name no_dialog = abap_true EXCEPTIONS imp_not_existing = 1 action_canceled = 2 access_failure = 3 data_inconsistency = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_badi_definition TYPE badi_data, lo_filter_object TYPE REF TO cl_badi_flt_struct, lo_filter_values_object TYPE REF TO cl_badi_flt_values_alv, lv_korrnum TYPE trkorr, lv_filter_type_enhanceability TYPE rsexscrn-flt_ext, lv_package TYPE devclass, ls_classic_badi_implementation TYPE ty_classic_badi_implementation. io_xml->read( EXPORTING iv_name = 'SXCI' CHANGING cg_data = ls_classic_badi_implementation ). CALL FUNCTION 'SXO_BADI_READ' EXPORTING exit_name = ls_classic_badi_implementation-implementation_data-exit_name IMPORTING badi = ls_badi_definition filter_obj = lo_filter_object EXCEPTIONS read_failure = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. lv_package = iv_package. CREATE OBJECT lo_filter_values_object EXPORTING filter_object = lo_filter_object filter_values = ls_classic_badi_implementation-filters. CALL FUNCTION 'SXO_IMPL_SAVE' EXPORTING impl = ls_classic_badi_implementation-implementation_data flt_ext = lv_filter_type_enhanceability filter_val_obj = lo_filter_values_object genflag = abap_true no_dialog = abap_true TABLES fcodes_to_insert = ls_classic_badi_implementation-function_codes cocos_to_insert = ls_classic_badi_implementation-control_composites intas_to_insert = ls_classic_badi_implementation-customer_includes sscrs_to_insert = ls_classic_badi_implementation-screens CHANGING korrnum = lv_korrnum devclass = lv_package EXCEPTIONS save_failure = 1 action_canceled = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'SXO_IMPL_ACTIVE' EXPORTING imp_name = ls_classic_badi_implementation-implementation_data-imp_name no_dialog = abap_true EXCEPTIONS badi_not_existing = 1 imp_not_existing = 2 already_active = 3 data_inconsistency = 4 activation_not_admissable = 5 action_canceled = 6 access_failure = 7 OTHERS = 8. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_implementation_name TYPE rsexscrn-imp_name. lv_implementation_name = ms_item-obj_name. CALL FUNCTION 'SXV_IMP_EXISTS' EXPORTING imp_name = lv_implementation_name EXCEPTIONS not_existing = 1 data_inconsistency = 2 OTHERS = 3. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). "Note: SAP does not show inactive classic BAdIs as "Inactive objects" in SE80 "Therefore, rv_active will always be true. The implementation state (runtime "behaviour of the BAdI) will be serialized as part of the XML ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_implementation_name TYPE rsexscrn-imp_name, lv_exit_name TYPE rsexscrn-exit_name, lo_filter_object TYPE REF TO cl_badi_flt_struct, ls_badi_definition TYPE badi_data, lo_filter_values_object TYPE REF TO cl_badi_flt_values_alv, lt_methods TYPE seex_mtd_table, ls_classic_badi_implementation TYPE ty_classic_badi_implementation. lv_implementation_name = ms_item-obj_name. CALL FUNCTION 'SXV_EXIT_FOR_IMP' EXPORTING imp_name = lv_implementation_name IMPORTING exit_name = lv_exit_name TABLES filters = ls_classic_badi_implementation-filters EXCEPTIONS data_inconsistency = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'SXO_BADI_READ' EXPORTING exit_name = lv_exit_name IMPORTING badi = ls_badi_definition filter_obj = lo_filter_object TABLES fcodes = ls_classic_badi_implementation-function_codes cocos = ls_classic_badi_implementation-control_composites intas = ls_classic_badi_implementation-customer_includes scrns = ls_classic_badi_implementation-screens methods = lt_methods EXCEPTIONS read_failure = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'SXO_IMPL_FOR_BADI_READ' EXPORTING imp_name = lv_implementation_name exit_name = lv_exit_name inter_name = ls_badi_definition-inter_name filter_obj = lo_filter_object no_create_filter_values_obj = abap_true IMPORTING impl = ls_classic_badi_implementation-implementation_data filter_values_obj = lo_filter_values_object TABLES fcodes = ls_classic_badi_implementation-function_codes cocos = ls_classic_badi_implementation-control_composites intas = ls_classic_badi_implementation-customer_includes scrns = ls_classic_badi_implementation-screens CHANGING methods = lt_methods EXCEPTIONS read_failure = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CLEAR: ls_classic_badi_implementation-implementation_data-aname, ls_classic_badi_implementation-implementation_data-adate, ls_classic_badi_implementation-implementation_data-atime, ls_classic_badi_implementation-implementation_data-uname, ls_classic_badi_implementation-implementation_data-udate, ls_classic_badi_implementation-implementation_data-utime. io_xml->add( iv_name = 'SXCI' ig_data = ls_classic_badi_implementation ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_suso IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_objectname = ms_item-obj_name. ENDMETHOD. METHOD delete_documentation. DATA: lv_docu_obj TYPE dokhl-object, lv_dummy TYPE sy-langu. lv_docu_obj = mv_objectname. SELECT SINGLE langu FROM dokil INTO lv_dummy WHERE id = 'UO' "#EC CI_GENBUFF AND object = lv_docu_obj. "#EC CI_NOORDER IF sy-subrc = 0. CALL FUNCTION 'DOKU_DELETE_ALL' EXPORTING doku_id = 'UO' doku_object = lv_docu_obj suppress_transport = space EXCEPTIONS header_without_text = 1 index_without_header = 2 no_authority_for_devclass_xxxx = 3 no_docu_found = 4 object_is_already_enqueued = 5 object_is_enqueued_by_corr = 6 techn_enqueue_problem = 7 user_break = 8 OTHERS = 9. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. ENDMETHOD. METHOD pre_check. CONSTANTS: lc_act_delete TYPE activ_auth VALUE '06'. DATA: lv_act_head TYPE activ_auth, lo_suso TYPE REF TO object, lv_failed TYPE abap_bool, lv_suso_collect_in_cts TYPE i, ls_clskey TYPE seoclskey. " Downport: CL_SUSO_GEN doesn't exist in 702 ls_clskey-clsname = |CL_SUSO_GEN|. CALL FUNCTION 'SEO_CLASS_EXISTENCE_CHECK' EXPORTING clskey = ls_clskey EXCEPTIONS not_specified = 1 not_existing = 2 is_interface = 3 no_text = 4 inconsistent = 5 OTHERS = 6. IF sy-subrc = 0. " so these checks are not executed in 702 CREATE OBJECT lo_suso TYPE ('CL_SUSO_GEN'). CALL METHOD lo_suso->('SUSO_LOAD_FROM_DB') EXPORTING id_object = mv_objectname RECEIVING ed_failed = lv_failed. IF lv_failed = abap_true. " Object & does not exist; choose an existing object MESSAGE s111(01) WITH mv_objectname INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL METHOD lo_suso->('GET_SUSO_EDIT_MODE') EXPORTING id_object = mv_objectname id_planed_act = lc_act_delete IMPORTING ed_mode_head = lv_act_head. IF lv_act_head <> lc_act_delete. zcx_abapgit_exception=>raise( |SUSO { mv_objectname }: Delete not allowed. Check where-used in SU21| ). ENDIF. CALL METHOD lo_suso->('SUSO_COLLECT_IN_CTS') EXPORTING id_object = mv_objectname RECEIVING ed_result = lv_suso_collect_in_cts. IF lv_suso_collect_in_cts IS NOT INITIAL. zcx_abapgit_exception=>raise( |SUSO { mv_objectname }: Cannot delete| ). ENDIF. ENDIF. ENDMETHOD. METHOD regenerate_sap_all. DATA: ls_e071 TYPE e071, lt_e071 TYPE STANDARD TABLE OF e071, lt_e071k TYPE STANDARD TABLE OF e071k. ls_e071-pgmid = 'R3TR'. ls_e071-object = ms_item-obj_type. ls_e071-obj_name = ms_item-obj_name. INSERT ls_e071 INTO TABLE lt_e071. CALL FUNCTION 'PRGN_AFTER_IMP_SUSO_SAP_ALL' EXPORTING iv_tarclient = '000' iv_is_upgrade = space TABLES tt_e071 = lt_e071 tt_e071k = lt_e071k. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE modifier FROM tobjvor INTO rv_user WHERE objct = mv_objectname. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. " FM SUSR_DELETE_OBJECT calls the UI. Therefore we reimplement it here. " As the class CL_SUSO_GEN isn't present in 702, we call dynamically and " skip the pre checks on 702 system. That seems ok. pre_check( ). delete_documentation( ). DELETE FROM tobj WHERE objct = mv_objectname. DELETE FROM tobjt WHERE object = mv_objectname. DELETE FROM tactz WHERE brobj = mv_objectname. CALL FUNCTION 'SUPV_DELETE_OBJECT_ASSIGNMENTS' EXPORTING object_name = mv_objectname all_releases = abap_true. CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' EXPORTING object = mv_objectname type = 'SUSO' operation = 'DELETE'. regenerate_sap_all( ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. * see function group SUSA DATA: lv_objectname TYPE trobj_name, ls_tobj TYPE tobj, ls_tobjt TYPE tobjt, ls_tobjvorflg TYPE tobjvorflg, lt_tactz TYPE TABLE OF tactz, lt_tobjvordat TYPE TABLE OF tobjvordat, lt_tobjvor TYPE TABLE OF tobjvor. ASSERT NOT ms_item-obj_name IS INITIAL. io_xml->read( EXPORTING iv_name = 'TOBJ' CHANGING cg_data = ls_tobj ). ls_tobj-bname = sy-uname. io_xml->read( EXPORTING iv_name = 'TOBJT' CHANGING cg_data = ls_tobjt ). io_xml->read( EXPORTING iv_name = 'TOBJVORFLG' CHANGING cg_data = ls_tobjvorflg ). io_xml->read( EXPORTING iv_name = 'TACTZ' CHANGING cg_data = lt_tactz ). io_xml->read( EXPORTING iv_name = 'TOBJVORDAT' CHANGING cg_data = lt_tobjvordat ). io_xml->read( EXPORTING iv_name = 'TOBJVOR' CHANGING cg_data = lt_tobjvor ). tadir_insert( iv_package ). lv_objectname = mv_objectname. CALL FUNCTION 'SUSR_COMMEDITCHECK' EXPORTING objectname = lv_objectname transobjecttype = 'O'. MODIFY tobj FROM ls_tobj. "#EC CI_SUBRC MODIFY tobjt FROM ls_tobjt. "#EC CI_SUBRC MODIFY tobjvorflg FROM ls_tobjvorflg. "#EC CI_SUBRC DELETE FROM tactz WHERE brobj = ms_item-obj_name. "#EC CI_SUBRC INSERT tactz FROM TABLE lt_tactz. "#EC CI_SUBRC DELETE FROM tobjvordat WHERE objct = ms_item-obj_name. "#EC CI_SUBRC INSERT tobjvordat FROM TABLE lt_tobjvordat. "#EC CI_SUBRC DELETE FROM tobjvor WHERE objct = ms_item-obj_name. "#EC CI_SUBRC INSERT tobjvor FROM TABLE lt_tobjvor. "#EC CI_SUBRC deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_suso ). regenerate_sap_all( ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_objct TYPE tobj-objct. SELECT SINGLE objct FROM tobj INTO lv_objct WHERE objct = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. CALL FUNCTION 'SUSR_SHOW_OBJECT' EXPORTING object = mv_objectname. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_tobj TYPE tobj, ls_tobjt TYPE tobjt, ls_tobjvorflg TYPE tobjvorflg, lt_tactz TYPE TABLE OF tactz, lt_tobjvordat TYPE TABLE OF tobjvordat, lt_tobjvor TYPE TABLE OF tobjvor. SELECT SINGLE * FROM tobj INTO ls_tobj WHERE objct = ms_item-obj_name. IF sy-subrc <> 0. RETURN. ENDIF. CLEAR ls_tobj-bname. SELECT SINGLE * FROM tobjt INTO ls_tobjt WHERE object = ms_item-obj_name AND langu = mv_language. "#EC CI_GENBUFF IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'TOBJT no English description' && ' for object (' && ms_item-obj_name && ')' ). ENDIF. SELECT SINGLE * FROM tobjvorflg INTO ls_tobjvorflg WHERE objct = ms_item-obj_name. "#EC CI_SUBRC SELECT * FROM tactz INTO TABLE lt_tactz WHERE brobj = ms_item-obj_name ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF SELECT * FROM tobjvordat INTO TABLE lt_tobjvordat WHERE objct = ms_item-obj_name ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF SELECT * FROM tobjvor INTO TABLE lt_tobjvor WHERE objct = ms_item-obj_name ORDER BY PRIMARY KEY. "#EC CI_SUBRC io_xml->add( iv_name = 'TOBJ' ig_data = ls_tobj ). io_xml->add( iv_name = 'TOBJT' ig_data = ls_tobjt ). io_xml->add( iv_name = 'TOBJVORFLG' ig_data = ls_tobjvorflg ). io_xml->add( ig_data = lt_tactz iv_name = 'TACTZ' ). io_xml->add( ig_data = lt_tobjvordat iv_name = 'TOBJVORDAT' ). io_xml->add( ig_data = lt_tobjvor iv_name = 'TOBJVOR' ). serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_suso ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sush IMPLEMENTATION. METHOD clear_metadata. DATA: BEGIN OF ls_empty_metadata, modifier TYPE c LENGTH 12, " usob_sm-modifier moddate TYPE d, " usob_sm-moddate, modtime TYPE t, " usob_sm-modtime, srcsystem TYPE tadir-srcsystem, author TYPE tadir-author, devclass TYPE tadir-devclass, END OF ls_empty_metadata. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any, TYPE any. MOVE-CORRESPONDING ls_empty_metadata TO cs_data_head. LOOP AT ct_usobx ASSIGNING . MOVE-CORRESPONDING ls_empty_metadata TO . ENDLOOP. LOOP AT ct_usobt ASSIGNING . MOVE-CORRESPONDING ls_empty_metadata TO . ENDLOOP. LOOP AT ct_usobt_ext ASSIGNING . MOVE-CORRESPONDING ls_empty_metadata TO . ENDLOOP. LOOP AT ct_usobx_ext ASSIGNING . MOVE-CORRESPONDING ls_empty_metadata TO . ENDLOOP. ENDMETHOD. METHOD constructor. DATA: lr_data_head TYPE REF TO data. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). TRY. CREATE DATA lr_data_head TYPE ('IF_SU22_ADT_OBJECT=>TS_SU2X_HEAD'). CATCH cx_sy_create_data_error. zcx_abapgit_exception=>raise( |SUSH is not supported in your SAP release| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA ls_key TYPE usobkey. ls_key = ms_item-obj_name. SELECT SINGLE modifier FROM usob_sm INTO rv_user WHERE name = ls_key-name AND type = ls_key-type. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_su22 TYPE REF TO object, ls_key TYPE usobkey, lx_err TYPE REF TO cx_static_check. ASSERT NOT ms_item-obj_name IS INITIAL. ls_key = ms_item-obj_name. TRY. CREATE OBJECT lo_su22 TYPE ('CL_SU22_ADT_OBJECT'). CALL METHOD lo_su22->('IF_SU22_ADT_OBJECT~DELETE') EXPORTING iv_key = ls_key iv_cleanup = abap_true. CATCH cx_static_check INTO lx_err. zcx_abapgit_exception=>raise_with_text( lx_err ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_key TYPE usobkey, lo_su22 TYPE REF TO object, lo_appl TYPE REF TO object, lt_usobx TYPE usobx_t, lt_usobt TYPE usobt_t, lr_appl_head TYPE REF TO data, lr_data_head TYPE REF TO data, lr_data_usobx_ext TYPE REF TO data, lr_data_usobt_ext TYPE REF TO data, lx_err TYPE REF TO cx_static_check, lv_text TYPE string. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE ANY TABLE, TYPE ANY TABLE, TYPE any. ASSERT NOT ms_item-obj_name IS INITIAL. TRY. CREATE DATA lr_data_head TYPE ('IF_SU22_ADT_OBJECT=>TS_SU2X_HEAD'). ASSIGN lr_data_head->* TO . CREATE DATA lr_data_usobx_ext TYPE ('IF_SU22_ADT_OBJECT=>TT_SU2X_X'). ASSIGN lr_data_usobx_ext->* TO . CREATE DATA lr_data_usobt_ext TYPE ('IF_SU22_ADT_OBJECT=>TT_SU2X_T'). ASSIGN lr_data_usobt_ext->* TO . "HEAD io_xml->read( EXPORTING iv_name = 'HEAD' CHANGING cg_data = ). "USOBX io_xml->read( EXPORTING iv_name = 'USOBX' CHANGING cg_data = lt_usobx ). "USOBT io_xml->read( EXPORTING iv_name = 'USOBT' CHANGING cg_data = lt_usobt ). "USOBX_EXT io_xml->read( EXPORTING iv_name = 'USOBX_EXT' CHANGING cg_data = ). "USOBT_EXT io_xml->read( EXPORTING iv_name = 'USOBT_EXT' CHANGING cg_data = ). CREATE OBJECT lo_su22 TYPE ('CL_SU22_ADT_OBJECT'). " check if lead application exists TRY. CALL METHOD lo_su22->('IF_SU22_ADT_OBJECT~CHECK') EXPORTING id_mode = '02' CHANGING cs_head = . CATCH cx_static_check INTO lx_err. lv_text = |Lead application of object { ms_item-obj_name } does not exist|. zcx_abapgit_exception=>raise( lv_text ). ENDTRY. MOVE-CORRESPONDING TO ls_key. CREATE DATA lr_appl_head TYPE ('CL_SU2X=>TS_HEAD'). ASSIGN lr_appl_head->* TO . CREATE OBJECT lo_appl TYPE ('CL_SU22_APPL'). CALL METHOD lo_appl->('GET_DATA') EXPORTING is_key = ls_key IMPORTING es_head = . ASSIGN COMPONENT 'DEVCLASS' OF STRUCTURE TO . IF <> iv_package. lv_text = |Lead application of object { ms_item-obj_name } does not exist in package { }|. zcx_abapgit_exception=>raise( lv_text ). ENDIF. TRY. CALL METHOD lo_su22->('IF_SU22_ADT_OBJECT~UPDATE') EXPORTING is_head = it_usobx = lt_usobx it_usobt = lt_usobt. CATCH cx_static_check INTO lx_err. zcx_abapgit_exception=>raise_with_text( lx_err ). ENDTRY. corr_insert( iv_package ). CATCH cx_static_check INTO lx_err. zcx_abapgit_exception=>raise_with_text( lx_err ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_usobhash TYPE usobhash. SELECT SINGLE * FROM usobhash INTO ls_usobhash "#EC CI_ALL_FIELDS_NEEDED WHERE name = ms_item-obj_name. "#EC CI_SGLSELECT rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_USOBX' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_key TYPE usobkey, lo_su22 TYPE REF TO object, lt_usobx TYPE usobx_t, lt_usobt TYPE usobt_t, lr_head TYPE REF TO data, lr_usobx_ext TYPE REF TO data, lr_usobt_ext TYPE REF TO data, lx_err TYPE REF TO cx_static_check. FIELD-SYMBOLS: TYPE any, TYPE ANY TABLE, TYPE ANY TABLE. ls_key = ms_item-obj_name. TRY. CREATE DATA lr_head TYPE ('IF_SU22_ADT_OBJECT=>TS_SU2X_HEAD'). ASSIGN lr_head->* TO . CREATE DATA lr_usobx_ext TYPE ('IF_SU22_ADT_OBJECT=>TT_SU2X_X'). ASSIGN lr_usobx_ext->* TO . CREATE DATA lr_usobt_ext TYPE ('IF_SU22_ADT_OBJECT=>TT_SU2X_T'). ASSIGN lr_usobt_ext->* TO . CREATE OBJECT lo_su22 TYPE ('CL_SU22_ADT_OBJECT'). TRY. CALL METHOD lo_su22->('IF_SU22_ADT_OBJECT~SELECT') EXPORTING iv_key = ls_key IMPORTING es_head = et_usobx = lt_usobx et_usobt = lt_usobt et_usobx_ext = et_usobt_ext = . CATCH cx_static_check INTO lx_err. zcx_abapgit_exception=>raise_with_text( lx_err ). ENDTRY. clear_metadata( CHANGING cs_data_head = ct_usobx = lt_usobx ct_usobt = lt_usobt ct_usobx_ext = ct_usobt_ext = ). "HEAD io_xml->add( iv_name = 'HEAD' ig_data = ). "USOBX io_xml->add( iv_name = 'USOBX' ig_data = lt_usobx ). "USOBT io_xml->add( iv_name = 'USOBT' ig_data = lt_usobt ). "USOBX_EXT io_xml->add( iv_name = 'USOBX_EXT' ig_data = ). "USOBT_EXT io_xml->add( iv_name = 'USOBT_EXT' ig_data = ). CATCH cx_static_check INTO lx_err. zcx_abapgit_exception=>raise_with_text( lx_err ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_susc IMPLEMENTATION. METHOD delete_class. DELETE FROM tobc WHERE oclss = iv_auth_object_class. DELETE FROM tobct WHERE oclss = iv_auth_object_class. ENDMETHOD. METHOD has_authorization. AUTHORITY-CHECK OBJECT 'S_DEVELOP' ID 'DEVCLASS' DUMMY ID 'OBJTYPE' FIELD 'SUSC' ID 'OBJNAME' FIELD iv_class ID 'P_GROUP' DUMMY ID 'ACTVT' FIELD iv_activity. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( iv_msgid = '01' iv_msgno = '467' ). ENDIF. ENDMETHOD. METHOD is_used. DATA: lv_used_auth_object_class TYPE tobc-oclss. SELECT SINGLE oclss FROM tobj INTO lv_used_auth_object_class WHERE oclss = iv_auth_object_class ##WARN_OK. IF sy-subrc = 0. zcx_abapgit_exception=>raise_t100( iv_msgid = '01' iv_msgno = '212' iv_msgv1 = |{ iv_auth_object_class }| ). ENDIF. ENDMETHOD. METHOD put_delete_to_transport. DATA: lv_tr_object_name TYPE e071-obj_name, lv_tr_return TYPE char1, ls_package_info TYPE tdevc. lv_tr_object_name = ms_item-obj_name. CALL FUNCTION 'SUSR_COMMEDITCHECK' EXPORTING objectname = lv_tr_object_name transobjecttype = c_transobjecttype_class IMPORTING return_from_korr = lv_tr_return. IF lv_tr_return <> 'M'. zcx_abapgit_exception=>raise( |error in SUSC delete at SUSR_COMMEDITCHECK| ). ENDIF. CALL FUNCTION 'TR_DEVCLASS_GET' EXPORTING iv_devclass = ms_item-devclass IMPORTING es_tdevc = ls_package_info EXCEPTIONS OTHERS = 1. IF sy-subrc = 0 AND ls_package_info-korrflag IS INITIAL. tadir_delete( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " not stored by SAP ENDMETHOD. METHOD zif_abapgit_object~delete. CONSTANTS lc_activity_delete_06 TYPE activ_auth VALUE '06'. DATA: lv_auth_object_class TYPE tobc-oclss. lv_auth_object_class = ms_item-obj_name. TRY. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. CATCH zcx_abapgit_exception. RETURN. ENDTRY. has_authorization( iv_class = lv_auth_object_class iv_activity = lc_activity_delete_06 ). is_used( lv_auth_object_class ). delete_class( lv_auth_object_class ). put_delete_to_transport( ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. * see function group SUSA DATA: ls_tobc TYPE tobc, lv_objectname TYPE e071-obj_name, ls_tobct TYPE tobct. io_xml->read( EXPORTING iv_name = 'TOBC' CHANGING cg_data = ls_tobc ). io_xml->read( EXPORTING iv_name = 'TOBCT' CHANGING cg_data = ls_tobct ). tadir_insert( iv_package ). lv_objectname = ms_item-obj_name. CALL FUNCTION 'SUSR_COMMEDITCHECK' EXPORTING objectname = lv_objectname transobjecttype = c_transobjecttype_class. INSERT tobc FROM ls_tobc. "#EC CI_SUBRC * ignore sy-subrc as all fields are key fields MODIFY tobct FROM ls_tobct. "#EC CI_SUBRC ASSERT sy-subrc = 0. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_oclss TYPE tobc-oclss. SELECT SINGLE oclss FROM tobc INTO lv_oclss WHERE oclss = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lv_objclass TYPE tobc-oclss. lv_objclass = ms_item-obj_name. CALL FUNCTION 'SUSR_SHOW_OBJECT_CLASS' EXPORTING objclass = lv_objclass. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_tobc TYPE tobc, ls_tobct TYPE tobct. SELECT SINGLE * FROM tobc INTO ls_tobc WHERE oclss = ms_item-obj_name. IF sy-subrc <> 0. RETURN. ENDIF. SELECT SINGLE * FROM tobct INTO ls_tobct WHERE oclss = ms_item-obj_name AND langu = mv_language. io_xml->add( iv_name = 'TOBC' ig_data = ls_tobc ). io_xml->add( iv_name = 'TOBCT' ig_data = ls_tobct ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sucu IMPLEMENTATION. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " not stored by SAP ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_styl IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: ls_style TYPE ty_style, lv_name TYPE itcda-tdstyle. lv_name = ms_item-obj_name. CALL FUNCTION 'READ_STYLE' EXPORTING style = lv_name IMPORTING style_header = ls_style-header TABLES paragraphs = ls_style-paragraphs strings = ls_style-strings tabs = ls_style-tabs. rv_user = ls_style-header-tdluser. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_style TYPE itcda-tdstyle. lv_style = ms_item-obj_name. CALL FUNCTION 'DELETE_STYLE' EXPORTING style = lv_style language = '*'. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_style TYPE ty_style. io_xml->read( EXPORTING iv_name = 'STYLE' CHANGING cg_data = ls_style ). CALL FUNCTION 'SAVE_STYLE' EXPORTING style_header = ls_style-header TABLES paragraphs = ls_style-paragraphs strings = ls_style-strings tabs = ls_style-tabs. tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_style TYPE ty_style, lv_name TYPE itcda-tdstyle, lv_found TYPE abap_bool. lv_name = ms_item-obj_name. CALL FUNCTION 'READ_STYLE' EXPORTING style = lv_name IMPORTING found = lv_found TABLES paragraphs = ls_style-paragraphs strings = ls_style-strings tabs = ls_style-tabs. rv_bool = boolc( lv_found = abap_true ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_bcdata TYPE bdcdata, lt_bcdata TYPE STANDARD TABLE OF bdcdata. ls_bcdata-program = 'SAPMSSCS'. ls_bcdata-dynpro = '1100'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'RSSCS-TDSTYLE'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'RSSCS-TDSPRAS'. ls_bcdata-fval = mv_language. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'RSSCS-TDHEADEROB'. ls_bcdata-fval = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=SHOW'. APPEND ls_bcdata TO lt_bcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SE72' it_bdcdata = lt_bcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_style TYPE ty_style, lv_name TYPE itcda-tdstyle. lv_name = ms_item-obj_name. CALL FUNCTION 'READ_STYLE' EXPORTING style = lv_name IMPORTING style_header = ls_style-header TABLES paragraphs = ls_style-paragraphs strings = ls_style-strings tabs = ls_style-tabs. CLEAR: ls_style-header-tdfuser, ls_style-header-tdfdate, ls_style-header-tdftime, ls_style-header-tdfreles, ls_style-header-tdluser, ls_style-header-tdldate, ls_style-header-tdltime, ls_style-header-tdlreles. io_xml->add( iv_name = 'STYLE' ig_data = ls_style ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_stvi IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lv_transaction_variant TYPE utcvariant. lv_transaction_variant = ms_item-obj_name. SELECT SINGLE chuser FROM shdtvciu INTO rv_user WHERE tcvariant = lv_transaction_variant. IF sy-subrc <> 0 OR rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_transaction_variant TYPE tcvariant. lv_transaction_variant = ms_item-obj_name. CALL FUNCTION 'RS_HDSYS_DELETE_VARIANT' EXPORTING tcvariant = lv_transaction_variant i_flag_client_independent = abap_true EXCEPTIONS variant_enqueued = 1 no_correction = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_transaction_variant TYPE ty_transaction_variant. io_xml->read( EXPORTING iv_name = 'STVI' CHANGING cg_data = ls_transaction_variant ). CALL FUNCTION 'ENQUEUE_ESTCVARCIU' EXPORTING tcvariant = ls_transaction_variant-shdtvciu-tcvariant EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. MESSAGE e413(ms) WITH ls_transaction_variant-shdtvciu-tcvariant INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. corr_insert( iv_package ). * Populate user details ls_transaction_variant-shdtvciu-crdate = sy-datum. ls_transaction_variant-shdtvciu-cruser = sy-uname. ls_transaction_variant-shdtvciu-chdate = sy-datum. ls_transaction_variant-shdtvciu-chuser = sy-uname. MODIFY shdtvciu FROM ls_transaction_variant-shdtvciu. MODIFY shdttciu FROM TABLE ls_transaction_variant-shdttciu[]. INSERT shdfvguicu FROM TABLE ls_transaction_variant-shdfvguicu[] ACCEPTING DUPLICATE KEYS. INSERT shdtvsvciu FROM TABLE ls_transaction_variant-shdtvsvciu[] ACCEPTING DUPLICATE KEYS. CALL FUNCTION 'DEQUEUE_ESTCVARCIU' EXPORTING tcvariant = ls_transaction_variant-shdtvciu-tcvariant. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_transaction_variant TYPE tcvariant. lv_transaction_variant = ms_item-obj_name. CALL FUNCTION 'RS_HDSYS_EXIST_CHECK_VARIANT' EXPORTING tcvariant = lv_transaction_variant i_flag_client_independent = abap_true EXCEPTIONS no_variant = 1 OTHERS = 2. IF sy-subrc = 0. rv_bool = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_transaction_variant TYPE ty_transaction_variant. ls_transaction_variant-shdtvciu-tcvariant = ms_item-obj_name. CALL FUNCTION 'RS_HDSYS_READ_TC_VARIANT_DB' EXPORTING tcvariant = ls_transaction_variant-shdtvciu-tcvariant flag_client_independent = abap_true IMPORTING header_tcvariant = ls_transaction_variant-shdtvciu TABLES screen_variants = ls_transaction_variant-shdtvsvciu[] inactive_functions = ls_transaction_variant-shdfvguicu[] EXCEPTIONS no_variant = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. * Clear all user details CLEAR: ls_transaction_variant-shdtvciu-crdate, ls_transaction_variant-shdtvciu-cruser, ls_transaction_variant-shdtvciu-chdate, ls_transaction_variant-shdtvciu-chuser. SELECT * FROM shdttciu INTO TABLE ls_transaction_variant-shdttciu[] WHERE tcvariant = ls_transaction_variant-shdtvciu-tcvariant ORDER BY PRIMARY KEY. io_xml->add( iv_name = 'STVI' ig_data = ls_transaction_variant ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ssst IMPLEMENTATION. METHOD validate_font. DATA: lv_tdfamily TYPE tfo01-tdfamily. SELECT SINGLE tdfamily FROM tfo01 INTO lv_tdfamily WHERE tdfamily = iv_tdfamily. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Font family not found' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE lastuser FROM stxsadm INTO rv_user WHERE stylename = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_stylename TYPE tdssname. lv_stylename = ms_item-obj_name. CALL FUNCTION 'SSF_DELETE_STYLE' EXPORTING i_stylename = lv_stylename i_with_dialog = abap_false i_with_confirm_dialog = abap_false EXCEPTIONS no_name = 1 no_style = 2 style_locked = 3 cancelled = 4 no_access_permission = 5 illegal_language = 6 OTHERS = 7. IF sy-subrc <> 0 AND sy-subrc <> 2. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. * see fm SSF_UPLOAD_STYLE DATA: ls_header TYPE ssfcats, ls_new_header TYPE ssfcats, lt_paragraphs TYPE TABLE OF ssfparas, lt_strings TYPE TABLE OF ssfstrings, lt_tabstops TYPE TABLE OF stxstab. FIELD-SYMBOLS: TYPE spras. io_xml->read( EXPORTING iv_name = 'HEADER' CHANGING cg_data = ls_header ). io_xml->read( EXPORTING iv_name = 'SSFPARAS' CHANGING cg_data = lt_paragraphs ). io_xml->read( EXPORTING iv_name = 'SSFSTRINGS' CHANGING cg_data = lt_strings ). io_xml->read( EXPORTING iv_name = 'STXSTAB' CHANGING cg_data = lt_tabstops ). validate_font( ls_header-tdfamily ). CALL FUNCTION 'SSF_READ_STYLE' "Just load FG EXPORTING i_style_name = ls_header-stylename i_style_active_flag = 'A' EXCEPTIONS OTHERS = 0. set_default_package( iv_package ). ASSIGN ('(SAPLSTXBS)MASTER_LANGUAGE') TO . IF sy-subrc = 0. = ls_header-masterlang. ENDIF. tadir_insert( iv_package ). CALL FUNCTION 'SSF_SAVE_STYLE' EXPORTING i_header = ls_header IMPORTING e_header = ls_new_header TABLES i_paragraphs = lt_paragraphs i_strings = lt_strings i_tabstops = lt_tabstops. IF ls_new_header IS NOT INITIAL. CALL FUNCTION 'SSF_ACTIVATE_STYLE' EXPORTING i_stylename = ls_header-stylename redirect_error_msg = abap_true " otherwise warnings write list output EXCEPTIONS no_name = 1 no_style = 2 cancelled = 3 no_access_permission = 4 illegal_language = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_stylename TYPE stxsadm-stylename. SELECT SINGLE stylename FROM stxshead INTO lv_stylename WHERE active = c_style_active AND stylename = ms_item-obj_name AND vari = ''. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_SMSTYLE' iv_argument = |{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_bcdata TYPE bdcdata, lt_bcdata TYPE STANDARD TABLE OF bdcdata. ls_bcdata-program = 'SAPMSSFS'. ls_bcdata-dynpro = '0100'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'SSFSCREENS-SNAME'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=DISPLAY'. APPEND ls_bcdata TO lt_bcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SMARTSTYLES' it_bdcdata = lt_bcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. * see fm SSF_DOWNLOAD_STYLE DATA: lv_style_name TYPE tdssname, ls_header TYPE ssfcats, lt_paragraphs TYPE TABLE OF ssfparas, lt_strings TYPE TABLE OF ssfstrings, lt_tabstops TYPE TABLE OF stxstab. lv_style_name = ms_item-obj_name. CALL FUNCTION 'SSF_READ_STYLE' EXPORTING i_style_name = lv_style_name i_style_active_flag = c_style_active i_style_variant = '%MAIN' i_style_language = mv_language IMPORTING e_header = ls_header TABLES e_paragraphs = lt_paragraphs e_strings = lt_strings e_tabstops = lt_tabstops EXCEPTIONS no_name = 1 no_style = 2 active_style_not_found = 3 inactive_style_not_found = 4 no_variant = 5 no_main_variant = 6 cancelled = 7 no_access_permission = 8 OTHERS = 9. IF sy-subrc = 2. RETURN. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CLEAR ls_header-version. CLEAR ls_header-firstuser. CLEAR ls_header-firstdate. CLEAR ls_header-firsttime. CLEAR ls_header-lastuser. CLEAR ls_header-lastdate. CLEAR ls_header-lasttime. io_xml->add( iv_name = 'HEADER' ig_data = ls_header ). io_xml->add( ig_data = lt_paragraphs iv_name = 'SSFPARAS' ). io_xml->add( ig_data = lt_strings iv_name = 'SSFSTRINGS' ). io_xml->add( ig_data = lt_tabstops iv_name = 'STXSTAB' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ssfo IMPLEMENTATION. METHOD code_item_section_handling. CONSTANTS: lc_node_item TYPE string VALUE 'item'. CONSTANTS: lc_node_text TYPE string VALUE '#text'. IF iv_name IN get_range_node_codes( ). cv_within_code_section = abap_true. ENDIF. IF cv_within_code_section = abap_true. IF iv_name = lc_node_item. TRY. ei_code_item_element ?= ii_node. RETURN. CATCH cx_sy_move_cast_error ##NO_HANDLER. ENDTRY. ELSEIF iv_name NOT IN get_range_node_codes( ) AND iv_name <> lc_node_text. cv_within_code_section = abap_false. ENDIF. ENDIF. RAISE EXCEPTION TYPE zcx_abapgit_exception. ENDMETHOD. METHOD fix_ids. " makes sure ID and IDREF values are the same values for each serialization run " the standard code has a counter that keeps increasing values. " " It is important that IDs and IDREFs which are the same before the fix " are also the same after the fix. TYPES: BEGIN OF ty_id_mapping, old TYPE string, new TYPE string, END OF ty_id_mapping, ty_id_mappings TYPE HASHED TABLE OF ty_id_mapping WITH UNIQUE KEY old. DATA: lv_name TYPE string, li_idref TYPE REF TO if_ixml_node, li_node TYPE REF TO if_ixml_node, li_attr TYPE REF TO if_ixml_named_node_map, li_iterator TYPE REF TO if_ixml_node_iterator, lt_id_mapping TYPE ty_id_mappings, ls_id_mapping LIKE LINE OF lt_id_mapping. li_iterator = ii_xml_doc->create_iterator( ). li_node = li_iterator->get_next( ). WHILE NOT li_node IS INITIAL. lv_name = li_node->get_name( ). IF lv_name = 'NODE' OR lv_name = 'WINDOW'. li_idref = li_node->get_attributes( )->get_named_item( 'IDREF' ). IF li_idref IS BOUND. ls_id_mapping-old = li_idref->get_value( ). READ TABLE lt_id_mapping WITH KEY old = ls_id_mapping-old INTO ls_id_mapping. IF sy-subrc <> 0. lv_name = lines( lt_id_mapping ) + 1. ls_id_mapping-new = condense( lv_name ). INSERT ls_id_mapping INTO TABLE lt_id_mapping. ENDIF. li_idref->set_value( |{ ls_id_mapping-new }| ). ENDIF. ENDIF. li_node = li_iterator->get_next( ). ENDWHILE. li_iterator = ii_xml_doc->create_iterator( ). li_node = li_iterator->get_next( ). WHILE NOT li_node IS INITIAL. lv_name = li_node->get_name( ). IF lv_name = 'NODE' OR lv_name = 'WINDOW'. li_idref = li_node->get_attributes( )->get_named_item( 'ID' ). IF li_idref IS BOUND. ls_id_mapping-old = li_idref->get_value( ). READ TABLE lt_id_mapping WITH KEY old = ls_id_mapping-old INTO ls_id_mapping. IF sy-subrc = 0. li_idref->set_value( |{ ls_id_mapping-new }| ). ELSE. li_attr = li_node->get_attributes( ). li_attr->remove_named_item( 'ID' ). ENDIF. ENDIF. ENDIF. li_node = li_iterator->get_next( ). ENDWHILE. ENDMETHOD. METHOD get_range_node_codes. DATA: ls_range_node_code TYPE LINE OF ty_string_range. IF gt_range_node_codes IS INITIAL. ls_range_node_code-sign = 'I'. ls_range_node_code-option = 'EQ'. ls_range_node_code-low = 'CODE'. INSERT ls_range_node_code INTO TABLE gt_range_node_codes. ls_range_node_code-low = 'GTYPES'. INSERT ls_range_node_code INTO TABLE gt_range_node_codes. ls_range_node_code-low = 'GCODING'. INSERT ls_range_node_code INTO TABLE gt_range_node_codes. ls_range_node_code-low = 'FCODING'. INSERT ls_range_node_code INTO TABLE gt_range_node_codes. ENDIF. rt_range_node_codes = gt_range_node_codes. ENDMETHOD. METHOD handle_attrib_leading_spaces. DATA li_element TYPE REF TO if_ixml_element. DATA lv_leading_spaces TYPE string. DATA lv_coding_line TYPE string. TRY. code_item_section_handling( EXPORTING iv_name = iv_name ii_node = ii_node IMPORTING ei_code_item_element = li_element CHANGING cv_within_code_section = cv_within_code_section ). * for downwards compatibility, this code can be removed sometime in the future lv_leading_spaces = li_element->get_attribute_ns( c_attrib_abapgit_leadig_spaces ). lv_coding_line = li_element->get_value( ). IF strlen( lv_coding_line ) >= 1 AND lv_coding_line(1) <> | |. SHIFT lv_coding_line RIGHT BY lv_leading_spaces PLACES. li_element->set_value( lv_coding_line ). ENDIF. CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. ENDMETHOD. METHOD sort_texts. DATA: li_node TYPE REF TO if_ixml_node, li_item TYPE REF TO if_ixml_node, li_field TYPE REF TO if_ixml_node, li_item_list TYPE REF TO if_ixml_node_list, li_iterator TYPE REF TO if_ixml_node_iterator, li_items TYPE REF TO if_ixml_node_iterator, lv_index TYPE i, lv_field TYPE fieldname, ls_item TYPE stxfobjt, lt_items TYPE STANDARD TABLE OF stxfobjt. FIELD-SYMBOLS TYPE any. li_iterator = ii_xml_doc->create_iterator( ). li_node = li_iterator->get_next( ). WHILE NOT li_node IS INITIAL. IF li_node->get_name( ) = 'T_CAPTION'. " Read all records for T_CAPTION CLEAR lt_items. li_item_list = li_node->get_children( ). li_items = li_item_list->create_iterator( ). DO. li_item = li_items->get_next( ). IF li_item IS INITIAL. EXIT. ENDIF. CLEAR ls_item. li_field = li_item->get_first_child( ). WHILE NOT li_field IS INITIAL. lv_field = li_field->get_name( ). ASSIGN COMPONENT lv_field OF STRUCTURE ls_item TO . ASSERT sy-subrc = 0. = li_field->get_value( ). li_field = li_field->get_next( ). ENDWHILE. INSERT ls_item INTO TABLE lt_items. ENDDO. SORT lt_items. " Write all records back after sorting lv_index = 1. li_items = li_item_list->create_iterator( ). DO. li_item = li_items->get_next( ). IF li_item IS INITIAL. EXIT. ENDIF. READ TABLE lt_items INTO ls_item INDEX lv_index. li_field = li_item->get_first_child( ). WHILE NOT li_field IS INITIAL. lv_field = li_field->get_name( ). ASSIGN COMPONENT lv_field OF STRUCTURE ls_item TO . ASSERT sy-subrc = 0. li_field->set_value( |{ }| ). li_field = li_field->get_next( ). ENDWHILE. lv_index = lv_index + 1. ENDDO. ENDIF. li_node = li_iterator->get_next( ). ENDWHILE. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE lastuser FROM stxfadm INTO rv_user WHERE formname = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_formname TYPE tdsfname. lv_formname = ms_item-obj_name. CALL FUNCTION 'FB_DELETE_FORM' EXPORTING i_formname = lv_formname i_with_dialog = abap_false i_with_confirm_dialog = abap_false EXCEPTIONS no_form = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. * see function module FB_UPLOAD_FORM DATA: li_node TYPE REF TO if_ixml_node, lv_formname TYPE tdsfname, lv_name TYPE string, li_iterator TYPE REF TO if_ixml_node_iterator, lo_sf TYPE REF TO cl_ssf_fb_smart_form, lo_res TYPE REF TO cl_ssf_fb_smart_form, lx_error TYPE REF TO cx_ssf_fb, lv_text TYPE string, lv_within_code_section TYPE abap_bool. CREATE OBJECT lo_sf. * set "created by" and "changed by" to current user li_iterator = io_xml->get_raw( )->get_root_element( )->create_iterator( ). li_node = li_iterator->get_next( ). WHILE NOT li_node IS INITIAL. lv_name = li_node->get_name( ). CASE lv_name. WHEN 'LASTDATE'. li_node->set_value( sy-datum(4) && '-' && sy-datum+4(2) && '-' && sy-datum+6(2) ). WHEN 'LASTTIME'. li_node->set_value( sy-uzeit(2) && ':' && sy-uzeit+2(2) && ':' && sy-uzeit+4(2) ). WHEN 'FIRSTUSER' OR 'LASTUSER'. li_node->set_value( sy-uname && '' ). ENDCASE. handle_attrib_leading_spaces( EXPORTING iv_name = lv_name ii_node = li_node CHANGING cv_within_code_section = lv_within_code_section ). li_node = li_iterator->get_next( ). ENDWHILE. tadir_insert( iv_package ). lv_formname = ms_item-obj_name. TRY. lo_sf->enqueue( suppress_corr_check = space master_language = mv_language mode = 'INSERT' formname = lv_formname ). lo_sf->xml_upload( EXPORTING dom = io_xml->get_raw( )->get_root_element( ) formname = lv_formname language = mv_language CHANGING sform = lo_res ). lo_res->store( im_formname = lo_res->header-formname im_language = mv_language im_active = abap_true ). lo_sf->dequeue( lv_formname ). CATCH cx_ssf_fb INTO lx_error. lv_text = lx_error->get_text( ). zcx_abapgit_exception=>raise( |{ ms_item-obj_type } { ms_item-obj_name }: { lv_text } | ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_formname TYPE stxfadm-formname. SELECT SINGLE formname FROM stxfadm INTO lv_formname WHERE formname = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. DATA: lv_ssfo_formname TYPE tdsfname. DATA lv_inactive TYPE abap_bool. lv_ssfo_formname = ms_item-obj_name. CALL FUNCTION 'SSF_STATUS_INFO' EXPORTING i_formname = lv_ssfo_formname IMPORTING o_inactive = lv_inactive. rv_active = boolc( lv_inactive = abap_false ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_SMFORM' iv_argument = |{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lt_bdcdata TYPE TABLE OF bdcdata, lv_formtype TYPE stxfadm-formtype. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMSSFO'. -dynpro = '0100'. -dynbegin = abap_true. SELECT SINGLE formtype FROM stxfadm INTO lv_formtype WHERE formname = ms_item-obj_name. IF lv_formtype = cssf_formtype_text. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'RB_TX'. -fval = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=RB'. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMSSFO'. -dynpro = '0100'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'SSFSCREEN-TNAME'. -fval = ms_item-obj_name. ELSE. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'SSFSCREEN-FNAME'. -fval = ms_item-obj_name. ENDIF. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=DISPLAY'. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SMARTFORMS' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. * see function module FB_DOWNLOAD_FORM DATA: lo_sf TYPE REF TO cl_ssf_fb_smart_form, lv_name TYPE string, li_node TYPE REF TO if_ixml_node, li_element TYPE REF TO if_ixml_element, li_iterator TYPE REF TO if_ixml_node_iterator, lv_formname TYPE tdsfname, li_ixml TYPE REF TO if_ixml, li_xml_doc TYPE REF TO if_ixml_document. li_ixml = cl_ixml=>create( ). li_xml_doc = li_ixml->create_document( ). CREATE OBJECT lo_sf. lv_formname = ms_item-obj_name. " convert type TRY. lo_sf->load( im_formname = lv_formname im_language = '' ). CATCH cx_ssf_fb. * the smartform is not present in system, or other error occurred RETURN. ENDTRY. lo_sf->xml_download( EXPORTING parent = li_xml_doc CHANGING document = li_xml_doc ). li_iterator = li_xml_doc->create_iterator( ). li_node = li_iterator->get_next( ). WHILE NOT li_node IS INITIAL. lv_name = li_node->get_name( ). IF lv_name = 'DEVCLASS' OR lv_name = 'LASTDATE' OR lv_name = 'LASTTIME'. li_node->set_value( '' ). ENDIF. IF lv_name = 'FIRSTUSER' OR lv_name = 'LASTUSER'. li_node->set_value( 'DUMMY' ). ENDIF. li_node = li_iterator->get_next( ). ENDWHILE. fix_ids( li_xml_doc ). sort_texts( li_xml_doc ). li_element = li_xml_doc->get_root_element( ). li_element->set_attribute( name = 'sf' namespace = 'xmlns' value = 'urn:sap-com:SmartForms:2000:internal-structure' ). li_element->set_attribute( name = 'xmlns' value = 'urn:sap-com:sdixml-ifr:2000' ). io_xml->set_raw( li_xml_doc->get_root_element( ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_srvd IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_metadata TO . IF sy-subrc = 0. CLEAR: . ENDIF. ENDMETHOD. METHOD clear_fields. clear_field( EXPORTING iv_fieldname = 'VERSION' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'CREATED_AT' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'CREATED_BY' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'CHANGED_AT' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'CHANGED_BY' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'RESPONSIBLE' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'PACKAGE_REF' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MASTER_SYSTEM' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'DT_UUID' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'ABAP_LANGUAGE_VERSION' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'ABAP_LANGU_VERSION' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'LINKS' CHANGING cs_metadata = cs_metadata ). ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_service_definition_key = ms_item-obj_name. TRY. CREATE DATA mr_service_definition TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_SRVD_OBJECT_DATA'). CATCH cx_sy_create_error. zcx_abapgit_exception=>raise( |SRVD not supported by your NW release| ). ENDTRY. ENDMETHOD. METHOD get_object_data. DATA: lr_metadata TYPE REF TO data, lr_data TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any, TYPE any. CREATE DATA lr_data TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_SRVD_OBJECT_DATA'). ASSIGN lr_data->* TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA' OF STRUCTURE TO . ASSERT sy-subrc = 0. CREATE DATA lr_metadata TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_METADATA_EXTENDED'). ASSIGN lr_metadata->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = c_xml_parent_name CHANGING cg_data = ). = . ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. = mo_files->read_string( c_source_file ). IF IS INITIAL. = mo_files->read_string( 'assrvd' ). ENDIF. CREATE OBJECT ro_object_data TYPE ('CL_SRVD_WB_OBJECT_DATA'). ro_object_data->set_data( p_data = ). ENDMETHOD. METHOD get_wb_object_operator. DATA: ls_object_type TYPE wbobjtype, lx_error TYPE REF TO cx_root. IF mo_object_operator IS BOUND. ro_object_operator = mo_object_operator. ENDIF. ls_object_type-objtype_tr = 'SRVD'. ls_object_type-subtype_wb = 'SRV'. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') EXPORTING object_type = ls_object_type object_key = mv_service_definition_key RECEIVING result = mo_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ro_object_operator = mo_object_operator. ENDMETHOD. METHOD merge_object_data. DATA: lo_object_data TYPE REF TO object, lo_object_data_old TYPE REF TO if_wb_object_data_model, lr_new TYPE REF TO data, lr_old TYPE REF TO data, lo_wb_object_operator TYPE REF TO object. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any, TYPE any. CREATE OBJECT lo_object_data TYPE ('CL_SRVD_WB_OBJECT_DATA'). lo_object_data = io_object_data. CREATE DATA lr_new TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_SRVD_OBJECT_DATA'). ASSIGN lr_new->* TO . ASSERT sy-subrc = 0. CREATE DATA lr_old TYPE ('CL_SRVD_WB_OBJECT_DATA=>TY_SRVD_OBJECT_DATA'). ASSIGN lr_old->* TO . ASSERT sy-subrc = 0. CALL METHOD lo_object_data->('IF_WB_OBJECT_DATA_MODEL~GET_DATA') EXPORTING p_metadata_only = abap_false p_data_selection = 'AL' IMPORTING p_data = . lo_wb_object_operator = get_wb_object_operator( ). CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data IMPORTING eo_object_data = lo_object_data_old. CALL METHOD lo_object_data_old->('GET_DATA') EXPORTING p_metadata_only = abap_false p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data IMPORTING p_data = . ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . = . ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . = . CREATE OBJECT ro_object_data_merged TYPE ('CL_SRVD_WB_OBJECT_DATA'). CALL METHOD ro_object_data_merged->('SET_DATA') EXPORTING p_data = . ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, li_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = li_object_data_model. rv_user = li_object_data_model->get_changed_by( ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_error TYPE REF TO cx_root, li_wb_object_operator TYPE REF TO object. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') EXPORTING transport_request = iv_transport. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_object_data TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root, lo_wb_object_operator TYPE REF TO object, lo_merged_data_all TYPE REF TO if_wb_object_data_model, lo_merged_data_prop TYPE REF TO if_wb_object_data_model, lo_merged_data_cont TYPE REF TO if_wb_object_data_model, lr_wbobjtype TYPE REF TO data, lr_category TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any. TRY. lo_object_data = get_object_data( io_xml ). lo_wb_object_operator = get_wb_object_operator( ). CREATE DATA lr_wbobjtype TYPE ('WBOBJTYPE'). ASSIGN lr_wbobjtype->* TO . ASSIGN COMPONENT 'OBJTYPE_TR' OF STRUCTURE TO . = 'SRVD'. ASSIGN COMPONENT 'SUBTYPE_WB' OF STRUCTURE TO . = 'SRV'. CREATE DATA lr_category TYPE ('WBADT_RESOURCE_CATEGORY'). ASSIGN lr_category->* TO . CALL METHOD ('CL_BLUE_WB_UTILITY')=>('GET_RESOURCE_CATEGORY') EXPORTING is_object_type = RECEIVING result = . lo_wb_object_operator = get_wb_object_operator( ). tadir_insert( iv_package ). IF zif_abapgit_object~exists( ) = abap_false. CASE . WHEN '1'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = lo_object_data data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data version = 'I' "swbm_version_inactive package = iv_package transport_request = iv_transport. WHEN '2'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_compound_s. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = lo_object_data data_selection = 'P' "if_wb_object_data_selection_co=>c_properties version = 'I' "swbm_version_inactive package = iv_package transport_request = iv_transport. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_object_data data_selection = 'D' "if_wb_object_data_selection_co=>c_data_content version = 'I' "swbm_version_inactive transport_request = iv_transport. WHEN OTHERS. zcx_abapgit_exception=>raise( |Category '{ }' not supported| ). ENDCASE. ELSE. CASE . WHEN '1'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. lo_merged_data_all = merge_object_data( lo_object_data ). CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_merged_data_all data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data version = 'I' "swbm_version_inactive transport_request = iv_transport. WHEN '2'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_compound_s. lo_merged_data_prop = merge_object_data( lo_object_data ). lo_merged_data_cont = merge_object_data( lo_object_data ). CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_merged_data_prop data_selection = 'P' "if_wb_object_data_selection_co=>c_properties version = 'I' "swbm_version_inactive transport_request = iv_transport. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_merged_data_cont data_selection = 'D' "if_wb_object_data_selection_co=>c_data_content version = 'I' "swbm_version_inactive transport_request = iv_transport. WHEN OTHERS. zcx_abapgit_exception=>raise( |Category '{ }' not supported| ). ENDCASE. ENDIF. corr_insert( iv_package ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA lo_object_data TYPE REF TO if_wb_object_data_model. DATA lo_wb_object_operator TYPE REF TO object. TRY. lo_wb_object_operator = get_wb_object_operator( ). CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING data_selection = 'P' IMPORTING eo_object_data = lo_object_data. rv_bool = boolc( lo_object_data IS NOT INITIAL AND lo_object_data->get_object_key( ) IS NOT INITIAL ). CATCH cx_root. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, li_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root, lv_source TYPE string. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE string. ASSIGN mr_service_definition->* TO . ASSERT sy-subrc = 0. TRY. li_wb_object_operator = get_wb_object_operator( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING version = 'A' data_selection = 'AL' IMPORTING "data = eo_object_data = li_object_data_model. CALL METHOD li_object_data_model->('GET_DATA') IMPORTING p_data = . ASSIGN COMPONENT 'METADATA' OF STRUCTURE TO . ASSERT sy-subrc = 0. clear_fields( CHANGING cs_metadata = ). ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. lv_source = . io_xml->add( iv_name = c_xml_parent_name ig_data = ). mo_files->add_string( iv_ext = c_source_file iv_string = lv_source ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_srvb IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_service_binding TO . ASSERT sy-subrc = 0. CLEAR: . ENDMETHOD. METHOD clear_fields. clear_field( EXPORTING iv_fieldname = 'METADATA-VERSION' CHANGING cs_service_binding = cs_service_binding ). clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_AT' CHANGING cs_service_binding = cs_service_binding ). clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_BY' CHANGING cs_service_binding = cs_service_binding ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_AT' CHANGING cs_service_binding = cs_service_binding ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_BY' CHANGING cs_service_binding = cs_service_binding ). clear_field( EXPORTING iv_fieldname = 'METADATA-LANGUAGE' CHANGING cs_service_binding = cs_service_binding ). clear_field( EXPORTING iv_fieldname = 'METADATA-PACKAGE_REF' CHANGING cs_service_binding = cs_service_binding ). clear_field( EXPORTING iv_fieldname = 'METADATA-MASTER_SYSTEM' CHANGING cs_service_binding = cs_service_binding ). clear_field( EXPORTING iv_fieldname = 'METADATA-LINKS' CHANGING cs_service_binding = cs_service_binding ). ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_service_binding_key = ms_item-obj_name. TRY. CREATE DATA mr_service_binding TYPE ('CL_SRVB_OBJECT_DATA=>TY_OBJECT_DATA'). CREATE OBJECT mi_persistence TYPE ('CL_SRVB_OBJECT_PERSIST'). CATCH cx_sy_create_error. zcx_abapgit_exception=>raise( |SRVB not supported by your NW release| ). ENDTRY. mv_is_inactive_supported = is_ai_supported( ). ENDMETHOD. METHOD get_object_data. FIELD-SYMBOLS: TYPE any, TYPE data. ASSIGN mr_service_binding->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'SRVB' CHANGING cg_data = ). " We have to set the language explicitly, " because otherwise the description isn't stored ASSIGN COMPONENT 'METADATA-LANGUAGE' OF STRUCTURE TO . ASSERT sy-subrc = 0. = mv_language. CREATE OBJECT ro_object_data TYPE ('CL_SRVB_OBJECT_DATA'). ro_object_data->set_data( p_data = ). ENDMETHOD. METHOD get_wb_object_operator. DATA: ls_object_type TYPE wbobjtype, lx_error TYPE REF TO cx_root. IF mo_object_operator IS BOUND. ro_object_operator = mo_object_operator. ENDIF. ls_object_type-objtype_tr = 'SRVB'. ls_object_type-subtype_wb = 'SVB'. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') EXPORTING object_type = ls_object_type object_key = mv_service_binding_key RECEIVING result = mo_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ro_object_operator = mo_object_operator. ENDMETHOD. METHOD is_ai_supported. TRY. CREATE OBJECT mr_srvb_svrs_config TYPE ('CL_SRVB_SVRS_CONFIG') EXPORTING iv_objtype = 'SRVB'. CATCH cx_sy_create_error. rv_ai_supported = abap_false. ENDTRY. CALL METHOD mr_srvb_svrs_config->('HAS_INACTIVE_VERSION') RECEIVING rv_has_inactive = rv_ai_supported. ENDMETHOD. METHOD merge_object_data. DATA: lo_object_data TYPE REF TO object, lo_object_data_old TYPE REF TO if_wb_object_data_model, lr_new TYPE REF TO data, lr_old TYPE REF TO data, lo_wb_object_operator TYPE REF TO object. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any, TYPE any. CREATE OBJECT lo_object_data TYPE ('CL_SRVB_OBJECT_DATA'). lo_object_data = io_object_data. CREATE DATA lr_new TYPE ('CL_SRVB_OBJECT_DATA=>TY_OBJECT_DATA'). ASSIGN lr_new->* TO . ASSERT sy-subrc = 0. CREATE DATA lr_old TYPE ('CL_SRVB_OBJECT_DATA=>TY_OBJECT_DATA'). ASSIGN lr_old->* TO . ASSERT sy-subrc = 0. CALL METHOD lo_object_data->('IF_WB_OBJECT_DATA_MODEL~GET_DATA') EXPORTING p_metadata_only = abap_false p_data_selection = 'AL' IMPORTING p_data = . lo_wb_object_operator = get_wb_object_operator( ). CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data IMPORTING eo_object_data = lo_object_data_old. CALL METHOD lo_object_data_old->('GET_DATA') EXPORTING p_metadata_only = abap_false p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data IMPORTING p_data = . ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . = . CREATE OBJECT ro_object_data_merged TYPE ('CL_SRVB_OBJECT_DATA'). CALL METHOD ro_object_data_merged->('SET_DATA') EXPORTING p_data = . ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model. TRY. mi_persistence->get( EXPORTING p_object_key = mv_service_binding_key p_version = 'A' CHANGING p_object_data = li_object_data_model ). rv_user = li_object_data_model->get_changed_by( ). CATCH cx_swb_exception. rv_user = c_user_unknown. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_error TYPE REF TO cx_swb_exception. TRY. mi_persistence->delete( mv_service_binding_key ). CATCH cx_swb_exception INTO lx_error. CALL FUNCTION 'DEQUEUE_ESWB_EO' EXPORTING objtype = ms_item-obj_type objname = ms_item-obj_name. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_object_data TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root, lo_wb_object_operator TYPE REF TO object, lo_merged_data_all TYPE REF TO if_wb_object_data_model, lv_version TYPE r3state. TRY. lo_object_data = get_object_data( io_xml ). lo_wb_object_operator = get_wb_object_operator( ). IF mv_is_inactive_supported = abap_true. lv_version = 'I'. ELSE. lv_version = 'A'. ENDIF. tadir_insert( iv_package ). IF zif_abapgit_object~exists( ) = abap_false. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = lo_object_data data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data version = lv_version package = iv_package transport_request = iv_transport. ELSE. lo_merged_data_all = merge_object_data( lo_object_data ). CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_merged_data_all data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data version = lv_version transport_request = iv_transport. ENDIF. corr_insert( iv_package ). CATCH cx_root INTO lx_error. CALL FUNCTION 'DEQUEUE_ESWB_EO' EXPORTING objtype = ms_item-obj_type objname = ms_item-obj_name. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA lo_object_data TYPE REF TO if_wb_object_data_model. TRY. IF mv_is_inactive_supported = abap_true. TRY. mi_persistence->get( EXPORTING p_object_key = mv_service_binding_key p_version = 'I' p_data_selection = 'ST' CHANGING p_object_data = lo_object_data ). CATCH cx_root. mi_persistence->get( EXPORTING p_object_key = mv_service_binding_key p_version = 'A' p_data_selection = 'ST' CHANGING p_object_data = lo_object_data ). ENDTRY. ELSE. mi_persistence->get( EXPORTING p_object_key = mv_service_binding_key p_version = 'A' p_data_selection = 'ST' CHANGING p_object_data = lo_object_data ). ENDIF. rv_bool = boolc( lo_object_data IS NOT INITIAL AND lo_object_data->get_object_key( ) IS NOT INITIAL ). CATCH cx_root. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, li_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any. ASSIGN mr_service_binding->* TO . ASSERT sy-subrc = 0. TRY. li_wb_object_operator = get_wb_object_operator( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING version = 'A' data_selection = 'AL' IMPORTING eo_object_data = li_object_data_model. li_object_data_model->get_data( IMPORTING p_data = ). clear_fields( CHANGING cs_service_binding = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. io_xml->add( iv_name = 'SRVB' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_srfc IMPLEMENTATION. METHOD constructor. DATA li_srfc_persist TYPE REF TO if_wb_object_persist. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). TRY. CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). CATCH cx_root. zcx_abapgit_exception=>raise( 'Object type SRFC is not supported by this system' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: li_object_data TYPE REF TO if_wb_object_data_model, li_srfc_persist TYPE REF TO if_wb_object_persist, lr_srfc_data TYPE REF TO data, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE DATA lr_srfc_data TYPE ('UCONRFCSERV_COMPLETE'). ASSIGN lr_srfc_data->* TO . ASSERT sy-subrc = 0. CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). li_srfc_persist->get( EXPORTING p_object_key = |{ ms_item-obj_name }| p_version = 'A' CHANGING p_object_data = li_object_data ). li_object_data->get_data( IMPORTING p_data = ). ASSIGN COMPONENT 'HEADER-CHANGEDBY' OF STRUCTURE TO . IF sy-subrc = 0 AND IS NOT INITIAL. rv_user = . ELSE. rv_user = c_user_unknown. ENDIF. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: li_srfc_persist TYPE REF TO if_wb_object_persist, lx_error TYPE REF TO cx_root. TRY. CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). li_srfc_persist->delete( p_object_key = |{ ms_item-obj_name }| p_version = 'A' ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: li_srfc_persist TYPE REF TO if_wb_object_persist, li_object_data TYPE REF TO if_wb_object_data_model, lr_srfc_data TYPE REF TO data, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE DATA lr_srfc_data TYPE ('UCONRFCSERV_COMPLETE'). ASSIGN lr_srfc_data->* TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'HEADER-CREATEDBY' OF STRUCTURE TO . IF sy-subrc = 0. = sy-uname. ENDIF. ASSIGN COMPONENT 'HEADER-CREATEDON' OF STRUCTURE TO . IF sy-subrc = 0. = sy-datum. ENDIF. ASSIGN COMPONENT 'HEADER-CREATEDAT' OF STRUCTURE TO . IF sy-subrc = 0. = sy-uzeit. ENDIF. io_xml->read( EXPORTING iv_name = 'SRFC' CHANGING cg_data = ). CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). CREATE OBJECT li_object_data TYPE ('CL_UCONRFC_OBJECT_DATA'). li_object_data->set_data( ). li_srfc_persist->save( li_object_data ). tadir_insert( iv_package ). corr_insert( iv_package ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: li_object_data TYPE REF TO if_wb_object_data_model, li_srfc_persist TYPE REF TO if_wb_object_persist. TRY. CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). li_srfc_persist->get( EXPORTING p_object_key = |{ ms_item-obj_name }| p_version = 'A' CHANGING p_object_data = li_object_data ). CATCH cx_root. rv_bool = abap_false. RETURN. ENDTRY. rv_bool = abap_true. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: li_object_data TYPE REF TO if_wb_object_data_model, li_srfc_persist TYPE REF TO if_wb_object_persist, lr_srfc_data TYPE REF TO data, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE DATA lr_srfc_data TYPE ('UCONRFCSERV_COMPLETE'). ASSIGN lr_srfc_data->* TO . ASSERT sy-subrc = 0. CREATE OBJECT li_srfc_persist TYPE ('CL_UCONRFC_OBJECT_PERSIST'). li_srfc_persist->get( EXPORTING p_object_key = |{ ms_item-obj_name }| p_version = 'A' CHANGING p_object_data = li_object_data ). li_object_data->get_data( IMPORTING p_data = ). ASSIGN COMPONENT 'HEADER-CREATEDBY' OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'HEADER-CREATEDON' OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'HEADER-CREATEDAT' OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. io_xml->add( iv_name = 'SRFC' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sqsc IMPLEMENTATION. METHOD constructor. FIELD-SYMBOLS: TYPE ty_abap_name. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). TRY. CREATE OBJECT mo_proxy TYPE ('CL_DDIC_WB_DBPROC_PROXY'). ASSIGN ('MO_PROXY->IF_DDIC_WB_DBPROC_PROXY~DBPROXYNAME') TO . ASSERT sy-subrc = 0. CATCH cx_root. zcx_abapgit_exception=>raise( |SQSC not supported| ). ENDTRY. = ms_item-obj_name. ENDMETHOD. METHOD delete_interface_if_it_exists. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, lo_interface TYPE REF TO zcl_abapgit_object_intf. " The interface is managed by the proxy. If abapGit " has created it before we have to delete it. Otherwise " if_dbproc_proxy_ui~create will throw errors. ls_item-obj_name = iv_interface. ls_item-obj_type = 'INTF'. IF zcl_abapgit_objects=>exists( ls_item ) = abap_true. CREATE OBJECT lo_interface EXPORTING is_item = ls_item iv_language = mv_language io_files = mo_files io_i18n_params = mo_i18n_params. lo_interface->zif_abapgit_object~delete( iv_package = iv_package iv_transport = iv_transport ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lx_error TYPE REF TO cx_root. TRY. CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~READ_FROM_SOURCE') EXPORTING if_version = 'A' IMPORTING ef_change_user = rv_user. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_error TYPE REF TO cx_root. TRY. CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~DELETE') EXPORTING if_transport_req = iv_transport. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_proxy TYPE ty_proxy, lx_error TYPE REF TO cx_root. io_xml->read( EXPORTING iv_name = 'SQSC' CHANGING cg_data = ls_proxy ). IF zif_abapgit_object~exists( ) = abap_false. delete_interface_if_it_exists( iv_package = iv_package iv_transport = iv_transport iv_interface = ls_proxy-header-interface_pool ). CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~CREATE') EXPORTING if_interface_pool = ls_proxy-header-interface_pool if_transport_req = iv_transport if_package = iv_package if_langu = mv_language. ENDIF. TRY. CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~WRITE_TO_SOURCE') EXPORTING if_transport_req = iv_transport is_header = ls_proxy-header it_parameter = ls_proxy-parameters it_parameter_type = ls_proxy-parameter_types. CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~WRITE_DESCR') EXPORTING if_langu = mv_language if_descr = ls_proxy-description. CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~ACTIVATE'). tadir_insert( iv_package ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~EXISTS') RECEIVING ef_exists = rv_bool. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_ADT_LINK=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_proxy TYPE ty_proxy, lx_error TYPE REF TO cx_root. TRY. CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~READ_FROM_SOURCE') EXPORTING if_version = 'A' IMPORTING es_header = ls_proxy-header et_parameter = ls_proxy-parameters et_parameter_type = ls_proxy-parameter_types. CALL METHOD mo_proxy->('IF_DBPROC_PROXY_UI~READ_DESCR') EXPORTING if_langu = mv_language if_version = 'A' IMPORTING ef_descr = ls_proxy-description. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. io_xml->add( iv_name = 'SQSC' ig_data = ls_proxy ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sprx IMPLEMENTATION. METHOD check_sprx_tadir. DATA: lt_abap_keys TYPE prx_abapobjects, ls_abap_key LIKE LINE OF lt_abap_keys, lx_error TYPE REF TO cx_proxy_gen_error. ls_abap_key-object = mv_object. ls_abap_key-obj_name = mv_obj_name. APPEND ls_abap_key TO lt_abap_keys. TRY. cl_proxy_utils=>check_sprx_tadir( objects = lt_abap_keys repair = abap_true ). CATCH cx_proxy_gen_error INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). get_object_and_name( IMPORTING ev_object = mv_object ev_obj_name = mv_obj_name ). ENDMETHOD. METHOD delta_handling. DATA: lo_proxy TYPE REF TO cl_proxy, lt_delta TYPE sprx_t_delta, ls_db_data TYPE sprx_db_data. "add Delta-Handling to avoid that single objects created without the dependent objects. "Thereby the dependent objects will be deleted TRY. lo_proxy = cl_proxy_fact=>load_by_abap_name( object = mv_object obj_name = mv_obj_name ). lt_delta = lo_proxy->get_delta_all( ). ls_db_data = cl_proxy_db=>serialize( proxy = lo_proxy inactive = abap_false delta = lt_delta ). et_sproxhdr_new = ls_db_data-sproxhdr. et_sproxdat_new = ls_db_data-sproxdat. CATCH cx_proxy_gen_error. "No delta for this object -> create ii_xml->read( EXPORTING iv_name = c_proxy-header CHANGING cg_data = et_sproxhdr_new ). IF et_sproxhdr_new IS INITIAL. zcx_abapgit_exception=>raise( |SPRX - error deserialize: { ms_item-obj_name }| ). ENDIF. ii_xml->read( EXPORTING iv_name = c_proxy-data CHANGING cg_data = et_sproxdat_new ). ENDTRY. ENDMETHOD. METHOD get_object_and_name. ev_object = ms_item-obj_name(4). ev_obj_name = ms_item-obj_name+4. ENDMETHOD. METHOD load_db. * method cl_proxy_db=>load_by_abap_name does not exist in lower releases DATA: lt_packages TYPE prx_t_namespace_package, ls_package LIKE LINE OF lt_packages, ls_hdr TYPE prx_s_proxy_hdr, lv_package TYPE tadir-devclass, lt_ids TYPE prx_ids. cl_proxy_query=>get_hdr_by_abap_name( EXPORTING object = mv_object obj_name = mv_obj_name IMPORTING hdr = ls_hdr ). APPEND ls_hdr-id TO lt_ids. IF ls_hdr-gen_appl = 'WEBSERVICES'. cl_proxy_utils=>get_package( EXPORTING object = mv_object obj_name = mv_obj_name RECEIVING rval = lv_package EXCEPTIONS OTHERS = 0 ). ls_package-namespace = ls_hdr-esr_nspce. ls_package-prefix = ls_hdr-prefix. ls_package-package = lv_package. APPEND ls_package TO lt_packages. ENDIF. rs_data = cl_proxy_db=>load( inactive = abap_false ids = lt_ids generating_application = ls_hdr-gen_appl packages = lt_packages ). ENDMETHOD. METHOD save. DATA: lt_sproxhdr_old TYPE sprx_hdr_t, lt_sproxdat_old TYPE sprx_dat_t, lt_sproxsvar_old TYPE sprx_svar_t, lt_sproxintf_old TYPE sprx_matchintf_t, lt_sproxsvar_new TYPE sprx_svar_t, lt_sproxintf_new TYPE sprx_matchintf_t. cl_proxy_data=>db_save( sproxhdr_old = lt_sproxhdr_old sproxdat_old = lt_sproxdat_old sproxsvar_old = lt_sproxsvar_old sproxintf_old = lt_sproxintf_old sproxhdr_new = it_sproxhdr_new sproxdat_new = it_sproxdat_new sproxsvar_new = lt_sproxsvar_new sproxintf_new = lt_sproxintf_new ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lv_changed_by TYPE sproxhdr-changed_by. rv_user = c_user_unknown. SELECT SINGLE changed_by FROM sproxhdr INTO lv_changed_by WHERE object = mv_object AND obj_name = mv_obj_name AND inactive = abap_false. IF sy-subrc = 0 AND lv_changed_by IS NOT INITIAL. rv_user = lv_changed_by. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_object TYPE sproxhdr-object, lv_obj_name TYPE sproxhdr-obj_name, lv_transp_flag TYPE abap_bool, lv_return_code TYPE i, lt_log TYPE sprx_log_t. IF iv_package(1) <> '$'. lv_transp_flag = abap_true. ENDIF. get_object_and_name( IMPORTING ev_object = lv_object ev_obj_name = lv_obj_name ). TRY. CALL METHOD ('CL_PROXY_DATA')=>('DELETE_SINGLE_PROXY') EXPORTING object = lv_object obj_name = lv_obj_name i_transport = lv_transp_flag suppress_dialogs = abap_true CHANGING c_return_code = lv_return_code ct_log = lt_log. CATCH cx_root. cl_proxy_data=>delete_single_proxy( EXPORTING object = lv_object obj_name = lv_obj_name i_transport = lv_transp_flag CHANGING c_return_code = lv_return_code ct_log = lt_log ). ENDTRY. IF lv_return_code <> 0. zcx_abapgit_exception=>raise( 'SPRX: Error from DELETE_SINGLE_PROXY' ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lt_sproxhdr_new TYPE sprx_hdr_t, lt_sproxdat_new TYPE sprx_dat_t. tadir_insert( iv_package ). corr_insert( iv_package ). delta_handling( EXPORTING ii_xml = io_xml IMPORTING et_sproxhdr_new = lt_sproxhdr_new et_sproxdat_new = lt_sproxdat_new ). save( it_sproxhdr_new = lt_sproxhdr_new it_sproxdat_new = lt_sproxdat_new ). COMMIT WORK. check_sprx_tadir( ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_status TYPE prx_status, lv_status_text TYPE prx_status_t. cl_proxy_data=>db_get_status( EXPORTING object = mv_object obj_name = mv_obj_name IMPORTING status = lv_status status_text = lv_status_text ). rv_bool = boolc( lv_status = if_proxy=>c_state_active ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = abap_true. "dummy implementation ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_sprx_db_data TYPE sprx_db_data. FIELD-SYMBOLS: LIKE LINE OF ls_sprx_db_data-sproxhdr, LIKE LINE OF ls_sprx_db_data-sproxdat. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. ls_sprx_db_data = load_db( ). DELETE ls_sprx_db_data-sproxhdr WHERE object <> mv_object OR obj_name <> mv_obj_name. DELETE ls_sprx_db_data-sproxdat WHERE object <> mv_object OR obj_name <> mv_obj_name. DELETE ls_sprx_db_data-sproxsvar WHERE object <> mv_object OR obj_name <> mv_obj_name. DELETE ls_sprx_db_data-sproxpck WHERE object <> mv_object OR obj_name <> mv_obj_name. DELETE ls_sprx_db_data-sproxintf WHERE object <> mv_object OR obj_name <> mv_obj_name. IF lines( ls_sprx_db_data-sproxhdr ) <> 1. zcx_abapgit_exception=>raise( |SPRX, no header found, { mv_object }, { mv_obj_name }| ). ENDIF. LOOP AT ls_sprx_db_data-sproxhdr ASSIGNING . CLEAR: -created_by, -created_on, -changed_by, -changed_on. ENDLOOP. LOOP AT ls_sprx_db_data-sproxdat ASSIGNING . CLEAR -warnings. ENDLOOP. io_xml->add( iv_name = c_proxy-header ig_data = ls_sprx_db_data-sproxhdr ). io_xml->add( iv_name = c_proxy-data ig_data = ls_sprx_db_data-sproxdat ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sppf IMPLEMENTATION. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " not stored by SAP ENDMETHOD. METHOD zif_abapgit_object~delete. set_default_transport( iv_transport ). get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. set_default_transport( iv_transport ). get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_splo IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. SELECT SINGLE chgname1 FROM tsp1d INTO rv_user WHERE papart = ms_item-obj_name. IF sy-subrc <> 0 OR rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DELETE FROM tsp1t WHERE papart = ms_item-obj_name. "#EC CI_NOFIRST "#EC CI_SUBRC DELETE FROM tsp1d WHERE papart = ms_item-obj_name. "#EC CI_SUBRC DELETE FROM tsp0p WHERE pdpaper = ms_item-obj_name. "#EC CI_SUBRC set_default_transport( iv_transport ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_tsp1t TYPE tsp1t, ls_tsp1d TYPE tsp1d, ls_tsp0p TYPE tsp0p. io_xml->read( EXPORTING iv_name = 'TSPLT' CHANGING cg_data = ls_tsp1t ). io_xml->read( EXPORTING iv_name = 'TSPLD' CHANGING cg_data = ls_tsp1d ). io_xml->read( EXPORTING iv_name = 'TSP0P' CHANGING cg_data = ls_tsp0p ). MODIFY tsp1t FROM ls_tsp1t. "#EC CI_SUBRC MODIFY tsp1d FROM ls_tsp1d. "#EC CI_SUBRC MODIFY tsp0p FROM ls_tsp0p. "#EC CI_SUBRC set_default_transport( iv_transport ). tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_papart TYPE tsp1d-papart. SELECT SINGLE papart INTO lv_papart FROM tsp1d WHERE papart = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_tsp1t TYPE tsp1t, ls_tsp1d TYPE tsp1d, ls_tsp0p TYPE tsp0p. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. SELECT SINGLE * FROM tsp1t INTO ls_tsp1t WHERE papart = ms_item-obj_name AND spras = mv_language. "#EC CI_GENBUFF "#EC CI_SUBRC SELECT SINGLE * FROM tsp1d INTO ls_tsp1d WHERE papart = ms_item-obj_name. "#EC CI_SUBRC SELECT SINGLE * FROM tsp0p INTO ls_tsp0p WHERE pdpaper = ms_item-obj_name. "#EC CI_SUBRC CLEAR: ls_tsp1d-chgname1, ls_tsp1d-chgtstmp1, ls_tsp1d-chgsaprel1, ls_tsp1d-chgsapsys1. io_xml->add( iv_name = 'TSPLT' ig_data = ls_tsp1t ). io_xml->add( iv_name = 'TSPLD' ig_data = ls_tsp1d ). io_xml->add( iv_name = 'TSP0P' ig_data = ls_tsp0p ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sots IMPLEMENTATION. METHOD create_sots. " Reimplementation of SOTR_STRING_CREATE_CONCEPT because we can't supply " concept and it would then be generated. DATA: lv_subrc TYPE sy-subrc, lv_source_langu TYPE spras, ls_header TYPE btfr_head, lv_flag_is_string TYPE btfr_flag VALUE abap_true, lt_text_tab TYPE sotr_text_tt, lv_concept_default TYPE sotr_conc, lt_entries TYPE sotr_textl_tt, lv_concept LIKE is_sots-header-concept, lv_flag_correction_entry TYPE abap_bool VALUE abap_true. lt_entries = is_sots-entries. ls_header-paket = iv_package. ls_header-crea_lan = mv_language. ls_header-alias_name = is_sots-header-alias_name. lv_source_langu = mv_language. lv_concept = is_sots-header-concept. PERFORM btfr_create IN PROGRAM saplsotr_db_string USING iv_object lv_source_langu lv_flag_correction_entry lv_flag_is_string CHANGING lt_text_tab lt_entries ls_header lv_concept lv_concept_default lv_subrc. CASE lv_subrc. WHEN 1. zcx_abapgit_exception=>raise( |No entry found| ). WHEN 2. zcx_abapgit_exception=>raise( |OTR concept not found| ). WHEN 3. zcx_abapgit_exception=>raise( |Enter a permitted object type| ). WHEN 4. "The concept will be created in the non-original system (not an error) RETURN. WHEN 5. zcx_abapgit_exception=>raise( |Invalid alias| ). WHEN 6. zcx_abapgit_exception=>raise( |No correction entry has been created| ). WHEN 7. zcx_abapgit_exception=>raise( |Error in database operation| ). WHEN 9. zcx_abapgit_exception=>raise( |Action canceled by user| ). ENDCASE. ENDMETHOD. METHOD get_raw_text_filename. DATA lv_langu TYPE string. " Lower case language codes can cause duplicate filenames therefore add suffix to make them unique " Note: Using ISO code would be better but is not compatible with existing files lv_langu = is_entry-langu. IF lv_langu = to_lower( lv_langu ). lv_langu = lv_langu && '-'. ENDIF. rv_filename = to_lower( |{ is_entry-concept }_| && |{ lv_langu }_| && |{ is_entry-object }_| && |{ is_entry-lfd_num }| ). ENDMETHOD. METHOD read_sots. DATA: lt_sotr_head TYPE STANDARD TABLE OF sotr_headu, lt_objects TYPE sotr_objects, lv_object LIKE LINE OF lt_objects, ls_sots LIKE LINE OF rt_sots. FIELD-SYMBOLS: TYPE sotr_head, LIKE LINE OF ls_sots-entries. SELECT * FROM sotr_headu INTO TABLE lt_sotr_head WHERE paket = ms_item-obj_name ORDER BY PRIMARY KEY. LOOP AT lt_sotr_head ASSIGNING . CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' EXPORTING object_vector = -objid_vec IMPORTING objects = lt_objects EXCEPTIONS object_not_found = 1 OTHERS = 2. IF sy-subrc <> 0. CONTINUE. ENDIF. READ TABLE lt_objects INDEX 1 INTO lv_object. ASSERT sy-subrc = 0. " Handled by object serializer CHECK lv_object <> 'SICF' AND lv_object <> 'CPUB'. CLEAR: ls_sots. CALL FUNCTION 'SOTR_STRING_GET_CONCEPT' EXPORTING concept = -concept IMPORTING header = ls_sots-header entries = ls_sots-entries EXCEPTIONS no_entry_found = 1 OTHERS = 2. IF sy-subrc <> 0. CONTINUE. ENDIF. CLEAR: ls_sots-header-paket, ls_sots-header-crea_name, ls_sots-header-crea_tstut, ls_sots-header-chan_name, ls_sots-header-chan_tstut. LOOP AT ls_sots-entries ASSIGNING . CLEAR: -version, -crea_name, -crea_tstut, -chan_name, -chan_tstut. ENDLOOP. INSERT ls_sots INTO TABLE rt_sots. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE chan_name FROM sotr_headu INTO rv_user WHERE paket = ms_item-obj_name. "#EC CI_NOORDER IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lt_sots TYPE ty_sots_tt. FIELD-SYMBOLS: TYPE ty_sots. lt_sots = read_sots( ). LOOP AT lt_sots ASSIGNING . " Remove any usage to ensure deletion, see function module BTFR_CHECK DELETE FROM sotr_useu WHERE concept = -header-concept. CALL FUNCTION 'BTFR_DELETE_SINGLE_TEXT' EXPORTING concept = -header-concept flag_string = abap_true EXCEPTIONS text_not_found = 1 invalid_package = 2 text_not_changeable = 3 text_enqueued = 4 no_correction = 5 parameter_error = 6 OTHERS = 7. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lt_sots TYPE ty_sots_tt, lt_objects TYPE sotr_objects, lv_object LIKE LINE OF lt_objects. FIELD-SYMBOLS: TYPE ty_sots, LIKE LINE OF -entries. io_xml->read( EXPORTING iv_name = 'SOTS' CHANGING cg_data = lt_sots ). tadir_insert( iv_package ). LOOP AT lt_sots ASSIGNING . CLEAR: lt_objects. CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' EXPORTING object_vector = -header-objid_vec IMPORTING objects = lt_objects EXCEPTIONS object_not_found = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from SOTR_OBJECT_GET_OBJECTS' ). ENDIF. READ TABLE lt_objects INDEX 1 INTO lv_object. ASSERT sy-subrc = 0. LOOP AT -entries ASSIGNING . TRY. -text = mo_files->read_string( iv_extra = get_raw_text_filename( ) iv_ext = 'txt' ). CATCH zcx_abapgit_exception. " Most probably file not found -> ignore CONTINUE. ENDTRY. ENDLOOP. create_sots( is_sots = iv_package = iv_package iv_object = lv_object ). ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_object_type TYPE trobjtype, lv_object_name TYPE trobj_name. lv_object_type = ms_item-obj_type. lv_object_name = ms_item-obj_name. CALL FUNCTION 'SOTR_WBO_OBJECTS_CHECK' EXPORTING pgmid = 'R3TR' object = lv_object_type obj_name = lv_object_name IMPORTING object_exist = rv_bool EXCEPTIONS unknown_object = 1 OTHERS = 2. IF sy-subrc <> 0. rv_bool = abap_false. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lt_sots TYPE ty_sots_tt. FIELD-SYMBOLS: TYPE ty_sots, TYPE sotr_textl. lt_sots = read_sots( ). LOOP AT lt_sots ASSIGNING . LOOP AT -entries ASSIGNING . mo_files->add_string( iv_extra = get_raw_text_filename( ) iv_ext = 'txt' iv_string = -text ). CLEAR: -text. ENDLOOP. ENDLOOP. io_xml->add( iv_name = 'SOTS' ig_data = lt_sots ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sod2 IMPLEMENTATION. METHOD clear_content_fields. FIELD-SYMBOLS TYPE any. ASSIGN COMPONENT 'CONTENT' OF STRUCTURE cs_data TO . clear_field( EXPORTING iv_fieldname = 'CHANGE_USER' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CHANGE_TIMESTAMP' CHANGING cs_metadata = ). ENDMETHOD. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_metadata TO . IF sy-subrc = 0. CLEAR: . ENDIF. ENDMETHOD. METHOD clear_metadata_fields. FIELD-SYMBOLS TYPE any. ASSIGN COMPONENT 'METADATA' OF STRUCTURE cs_data TO . clear_field( EXPORTING iv_fieldname = 'VERSION' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CREATED_AT' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CREATED_BY' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CHANGED_AT' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CHANGED_BY' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'RESPONSIBLE' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'PACKAGE_REF' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'MASTER_SYSTEM' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'DT_UUID' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'ABAP_LANGU_VERSION' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'ABAP_LANGU_VERSION' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'LINKS' CHANGING cs_metadata = ). ENDMETHOD. METHOD constructor. DATA lo_data_model TYPE REF TO object. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). TRY. CREATE OBJECT lo_data_model TYPE (c_data_model_class_name). CATCH cx_root. zcx_abapgit_exception=>raise( |Object type { is_item-obj_type } is not supported by this system| ). ENDTRY. ENDMETHOD. METHOD create_wb_object_operator. DATA lx_error TYPE REF TO cx_root. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR_FACTORY')=>('CREATE_OBJECT_OPERATOR') EXPORTING object_type = is_object_type object_key = iv_object_key transport_request = iv_transport_request do_commits = iv_do_commits run_in_test_mode = iv_run_in_test_mode RECEIVING result = ro_wb_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD get_wb_object_operator. DATA lx_error TYPE REF TO cx_root. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR_FACTORY')=>('GET_OBJECT_OPERATOR') EXPORTING object_type = is_object_type object_key = iv_object_key transport_request = iv_transport_request RECEIVING result = ro_wb_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lo_data_model TYPE REF TO if_wb_object_data_model, lo_factory TYPE REF TO object, ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. TRY. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. lo_factory = create_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key ). CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = lo_data_model. rv_user = lo_data_model->get_changed_by( ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lo_factory TYPE REF TO object, lx_error TYPE REF TO cx_root. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. TRY. lo_factory = get_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key iv_transport_request = iv_transport ). CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~DELETE'). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_factory TYPE REF TO object, lo_data_model TYPE REF TO if_wb_object_data_model, lv_data_type_name TYPE string, ls_data TYPE REF TO data, ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lo_logger TYPE REF TO cl_wb_checklist, lx_create_error TYPE REF TO cx_root, lx_error TYPE REF TO cx_root, lt_msgs TYPE TABLE OF string, lt_error_msgs_create TYPE swbme_error_tab, ls_error_msg_create LIKE LINE OF lt_error_msgs_create, lv_error_msg TYPE string, lv_abap_language_version TYPE c LENGTH 1. " abap_language_version FIELD-SYMBOLS TYPE any. CREATE OBJECT lo_data_model TYPE (c_data_model_class_name). " if_wb_object_data_selection_co=>c_all_data CALL METHOD lo_data_model->('GET_DATATYPE_NAME') EXPORTING p_data_selection = 'AL' RECEIVING result = lv_data_type_name. CREATE DATA ls_data TYPE (lv_data_type_name). ASSIGN ls_data->* TO . io_xml->read( EXPORTING iv_name = c_xml_transformation_name CHANGING cg_data = ). CALL METHOD lo_data_model->('SET_SELECTED_DATA') EXPORTING p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data p_data = . TRY. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. lo_factory = get_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key ). IF zif_abapgit_object~exists( ) = abap_true. CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_data_model version = 'A' transport_request = iv_transport. ELSE. TRY. CALL METHOD lo_data_model->('GET_ABAP_LANGUAGE_VERSION') RECEIVING result = lv_abap_language_version. CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = lo_data_model version = 'A' package = iv_package abap_language_version = lv_abap_language_version transport_request = iv_transport IMPORTING logger = lo_logger. CATCH cx_root INTO lx_create_error. " Check for error messages from Workbench API to provide more error infos to user lo_logger->get_error_messages( IMPORTING p_error_tab = lt_error_msgs_create ). IF lt_error_msgs_create IS NOT INITIAL. LOOP AT lt_error_msgs_create INTO ls_error_msg_create. APPEND LINES OF ls_error_msg_create-mtext TO lt_msgs. ENDLOOP. CONCATENATE LINES OF lt_msgs INTO lv_error_msg SEPARATED BY '; '. zcx_abapgit_exception=>raise( iv_text = lv_error_msg ix_previous = lx_create_error ). ELSE. zcx_abapgit_exception=>raise_with_text( lx_create_error ). ENDIF. ENDTRY. ENDIF. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lo_factory TYPE REF TO object, ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. TRY. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. lo_factory = get_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key ). CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~CHECK_EXISTENCE') RECEIVING r_result = rv_bool. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }*| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_data_model TYPE REF TO if_wb_object_data_model, lv_data_type_name TYPE string, lo_factory TYPE REF TO object, ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. DATA ls_data TYPE REF TO data. FIELD-SYMBOLS TYPE any. TRY. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. lo_factory = create_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key ). CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = lo_data_model. " if_wb_object_data_selection_co=>c_all_data CALL METHOD lo_data_model->('GET_DATATYPE_NAME') EXPORTING p_data_selection = 'AL' RECEIVING result = lv_data_type_name. CREATE DATA ls_data TYPE (lv_data_type_name). ASSIGN ls_data->* TO . CALL METHOD lo_data_model->('GET_SELECTED_DATA') EXPORTING p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data IMPORTING p_data = . clear_metadata_fields( CHANGING cs_data = ). clear_content_fields( CHANGING cs_data = ). clear_field( EXPORTING iv_fieldname = 'PLUGIN_CONFIG' CHANGING cs_metadata = ). io_xml->add( iv_name = c_xml_transformation_name ig_data = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sod1 IMPLEMENTATION. METHOD clear_content_fields. FIELD-SYMBOLS TYPE any. ASSIGN COMPONENT 'CONTENT' OF STRUCTURE cs_data TO . clear_field( EXPORTING iv_fieldname = 'CHANGE_USER' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CHANGE_TIMESTAMP' CHANGING cs_metadata = ). ENDMETHOD. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_metadata TO . IF sy-subrc = 0. CLEAR: . ENDIF. ENDMETHOD. METHOD clear_metadata_fields. FIELD-SYMBOLS TYPE any. ASSIGN COMPONENT 'METADATA' OF STRUCTURE cs_data TO . clear_field( EXPORTING iv_fieldname = 'VERSION' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CREATED_AT' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CREATED_BY' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CHANGED_AT' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'CHANGED_BY' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'RESPONSIBLE' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'PACKAGE_REF' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'MASTER_SYSTEM' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'DT_UUID' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'ABAP_LANGU_VERSION' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'ABAP_LANGU_VERSION' CHANGING cs_metadata = ). clear_field( EXPORTING iv_fieldname = 'LINKS' CHANGING cs_metadata = ). ENDMETHOD. METHOD constructor. DATA lo_data_model TYPE REF TO object. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). TRY. CREATE OBJECT lo_data_model TYPE (c_data_model_class_name). CATCH cx_root. zcx_abapgit_exception=>raise( |Object type { is_item-obj_type } is not supported by this system| ). ENDTRY. ENDMETHOD. METHOD create_wb_object_operator. DATA lx_error TYPE REF TO cx_root. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR_FACTORY')=>('CREATE_OBJECT_OPERATOR') EXPORTING object_type = is_object_type object_key = iv_object_key transport_request = iv_transport_request do_commits = iv_do_commits run_in_test_mode = iv_run_in_test_mode RECEIVING result = ro_wb_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD get_wb_object_operator. DATA lx_error TYPE REF TO cx_root. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR_FACTORY')=>('GET_OBJECT_OPERATOR') EXPORTING object_type = is_object_type object_key = iv_object_key transport_request = iv_transport_request RECEIVING result = ro_wb_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lo_data_model TYPE REF TO if_wb_object_data_model, lo_factory TYPE REF TO object, ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. TRY. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. lo_factory = create_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key ). CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = lo_data_model. rv_user = lo_data_model->get_changed_by( ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lo_factory TYPE REF TO object, lx_error TYPE REF TO cx_root. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. TRY. lo_factory = get_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key iv_transport_request = iv_transport ). CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~DELETE'). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_factory TYPE REF TO object, lo_data_model TYPE REF TO if_wb_object_data_model, lv_data_type_name TYPE string, ls_data TYPE REF TO data, ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lo_logger TYPE REF TO cl_wb_checklist, lx_create_error TYPE REF TO cx_root, lx_error TYPE REF TO cx_root, lt_msgs TYPE TABLE OF string, lt_error_msgs_create TYPE swbme_error_tab, ls_error_msg_create LIKE LINE OF lt_error_msgs_create, lv_error_msg TYPE string, lv_abap_language_version TYPE c LENGTH 1. " abap_language_version FIELD-SYMBOLS TYPE any. CREATE OBJECT lo_data_model TYPE (c_data_model_class_name). " if_wb_object_data_selection_co=>c_all_data CALL METHOD lo_data_model->('GET_DATATYPE_NAME') EXPORTING p_data_selection = 'AL' RECEIVING result = lv_data_type_name. CREATE DATA ls_data TYPE (lv_data_type_name). ASSIGN ls_data->* TO . io_xml->read( EXPORTING iv_name = c_xml_transformation_name CHANGING cg_data = ). CALL METHOD lo_data_model->('SET_SELECTED_DATA') EXPORTING p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data p_data = . TRY. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. lo_factory = get_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key ). IF zif_abapgit_object~exists( ) = abap_true. CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_data_model version = 'A' transport_request = iv_transport. ELSE. TRY. CALL METHOD lo_data_model->('GET_ABAP_LANGUAGE_VERSION') RECEIVING result = lv_abap_language_version. CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = lo_data_model version = 'A' package = iv_package abap_language_version = lv_abap_language_version transport_request = iv_transport IMPORTING logger = lo_logger. CATCH cx_root INTO lx_create_error. " Check for error messages from Workbench API to provide more error infos to user lo_logger->get_error_messages( IMPORTING p_error_tab = lt_error_msgs_create ). IF lt_error_msgs_create IS NOT INITIAL. LOOP AT lt_error_msgs_create INTO ls_error_msg_create. APPEND LINES OF ls_error_msg_create-mtext TO lt_msgs. ENDLOOP. CONCATENATE LINES OF lt_msgs INTO lv_error_msg SEPARATED BY '; '. zcx_abapgit_exception=>raise( iv_text = lv_error_msg ix_previous = lx_create_error ). ELSE. zcx_abapgit_exception=>raise_with_text( lx_create_error ). ENDIF. ENDTRY. ENDIF. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lo_factory TYPE REF TO object, ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. TRY. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. lo_factory = get_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key ). CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~CHECK_EXISTENCE') RECEIVING r_result = rv_bool. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }*| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_data_model TYPE REF TO if_wb_object_data_model, lv_data_type_name TYPE string, lo_factory TYPE REF TO object, ls_object_type TYPE wbobjtype, lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. DATA ls_data TYPE REF TO data. FIELD-SYMBOLS TYPE any. TRY. ls_object_type-objtype_tr = ms_item-obj_type. lv_object_key = ms_item-obj_name. lo_factory = create_wb_object_operator( is_object_type = ls_object_type iv_object_key = lv_object_key ). CALL METHOD lo_factory->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = lo_data_model. " if_wb_object_data_selection_co=>c_all_data CALL METHOD lo_data_model->('GET_DATATYPE_NAME') EXPORTING p_data_selection = 'AL' RECEIVING result = lv_data_type_name. CREATE DATA ls_data TYPE (lv_data_type_name). ASSIGN ls_data->* TO . CALL METHOD lo_data_model->('GET_SELECTED_DATA') EXPORTING p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data IMPORTING p_data = . clear_metadata_fields( CHANGING cs_data = ). clear_content_fields( CHANGING cs_data = ). clear_field( EXPORTING iv_fieldname = 'PLUGIN_CONFIG' CHANGING cs_metadata = ). io_xml->add( iv_name = c_xml_transformation_name ig_data = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sobj IMPLEMENTATION. METHOD get_field_rules. ri_rules = zcl_abapgit_field_rules=>create( ). ri_rules->add( iv_table = 'TOJTB' iv_field = 'CREA_USER' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = 'TOJTB' iv_field = 'CREA_DATE' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date )->add( iv_table = 'TOJTB' iv_field = 'CREA_TIME' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time )->add( iv_table = 'TOJTB' iv_field = 'CHAN_USER' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = 'TOJTB' iv_field = 'CHAN_DATE' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date )->add( iv_table = 'TOJTB' iv_field = 'CHAN_TIME' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time )->add( iv_table = 'TOJTB' iv_field = 'ACTV_USER' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = 'TOJTB' iv_field = 'ACTV_DATE' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date )->add( iv_table = 'TOJTB' iv_field = 'ACTV_TIME' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time )->add( iv_table = 'TOJTB' iv_field = 'REL_USER' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = 'TOJTB' iv_field = 'REL_DATE' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date )->add( iv_table = 'TOJTB' iv_field = 'REL_TIME' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-time ). ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD get_program. SELECT SINGLE progname INTO rv_program FROM tojtb WHERE name = ms_item-obj_name. ENDMETHOD. METHOD is_locked. rv_is_locked = boolc( is_objtype_locked( ) = abap_true OR is_program_locked( ) = abap_true ). ENDMETHOD. METHOD is_objtype_locked. CONSTANTS lc_tabname TYPE tabname VALUE 'SWOTBASDAT'. DATA lv_varkey TYPE vim_enqkey. rv_is_locked = abap_false. lv_varkey = ms_item-obj_name. CALL FUNCTION 'ENQUEUE_E_TABLE' EXPORTING tabname = lc_tabname varkey = lv_varkey EXCEPTIONS foreign_lock = 1 OTHERS = 999. IF sy-subrc IS NOT INITIAL. rv_is_locked = abap_true. ELSE. CALL FUNCTION 'DEQUEUE_E_TABLE' EXPORTING tabname = lc_tabname varkey = lv_varkey. ENDIF. ENDMETHOD. METHOD is_program_locked. CONSTANTS lc_enqueue_exclusive TYPE enqmode VALUE 'X'. DATA lv_progname TYPE progname. rv_is_locked = abap_false. lv_progname = get_program( ). IF lv_progname IS NOT INITIAL. CALL FUNCTION 'ENQUEUE_ESRDIRE' EXPORTING mode_trdir = lc_enqueue_exclusive name = lv_progname EXCEPTIONS foreign_lock = 1 OTHERS = 999. IF sy-subrc IS NOT INITIAL. rv_is_locked = abap_true. ELSE. CALL FUNCTION 'DEQUEUE_ESRDIRE' EXPORTING mode_trdir = lc_enqueue_exclusive name = lv_progname. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: BEGIN OF ls_userinfo, crea_user TYPE tojtb-crea_user, chan_user TYPE tojtb-chan_user, END OF ls_userinfo. SELECT SINGLE crea_user chan_user INTO (ls_userinfo-crea_user, ls_userinfo-chan_user) FROM tojtb WHERE name = ms_item-obj_name. IF ls_userinfo-chan_user IS INITIAL. ls_userinfo-chan_user = ls_userinfo-crea_user. ENDIF. rv_user = ls_userinfo-chan_user. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = is_locked( ). ENDMETHOD. METHOD zif_abapgit_object~jump. "No need as GENERIC class already handles it ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_smtg IMPLEMENTATION. METHOD add_component. DATA: ls_component LIKE LINE OF ct_components, lo_typedescr TYPE REF TO cl_abap_typedescr. cl_abap_structdescr=>describe_by_name( EXPORTING p_name = iv_structure_name RECEIVING p_descr_ref = lo_typedescr EXCEPTIONS type_not_found = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |SMTG not supported| ). ENDIF. ls_component-name = iv_fielname. ls_component-type ?= lo_typedescr. INSERT ls_component INTO TABLE ct_components. ENDMETHOD. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cg_header TO . ASSERT sy-subrc = 0. CLEAR: . ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_template_id = ms_item-obj_name. mo_structdescr = get_structure( ). ENDMETHOD. METHOD get_structure. DATA: lt_components TYPE abap_component_tab. add_component( EXPORTING iv_fielname = `HEADER` iv_structure_name = `IF_SMTG_EMAIL_TEMPLATE=>TY_GS_TMPL_HDR` CHANGING ct_components = lt_components ). add_component( EXPORTING iv_fielname = `HEADER_T` iv_structure_name = `IF_SMTG_EMAIL_TEMPLATE=>TY_GT_TMPL_HDR_T` CHANGING ct_components = lt_components ). add_component( EXPORTING iv_fielname = `CONTENT` iv_structure_name = `IF_SMTG_EMAIL_TEMPLATE=>TY_GT_TMPL_CONT` CHANGING ct_components = lt_components ). ro_structdescr = cl_abap_structdescr=>create( lt_components ). ENDMETHOD. METHOD get_template. DATA: lr_template TYPE REF TO data, lx_error TYPE REF TO cx_root, lo_template TYPE REF TO object. FIELD-SYMBOLS: TYPE data, TYPE data, TYPE INDEX TABLE, TYPE INDEX TABLE. CREATE DATA lr_template TYPE HANDLE mo_structdescr. ASSIGN lr_template->* TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'HEADER' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'HEADER_T' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'CONTENT' OF STRUCTURE TO . ASSERT sy-subrc = 0. TRY. CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>get EXPORTING iv_id = mv_template_id RECEIVING ro_instance = lo_template. CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~GET_TMPL_HDR') RECEIVING rs_tmpl_hdr = . CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~GET_TMPL_HDR_T_ALL') RECEIVING rt_tmpl_hdr_t = . CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~GET_TMPL_CONT_ALL') RECEIVING rt_tmpl_cont = . CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. es_template = . ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lr_template TYPE REF TO data. FIELD-SYMBOLS: TYPE data, TYPE data. CREATE DATA lr_template TYPE HANDLE mo_structdescr. ASSIGN lr_template->* TO . ASSERT sy-subrc = 0. get_template( IMPORTING es_template = ). ASSIGN COMPONENT 'HEADER-LST_CH_USER_ACCT' OF STRUCTURE TO . ASSERT sy-subrc = 0. rv_user = . ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_error TYPE REF TO cx_root. TRY. CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>delete EXPORTING iv_id = mv_template_id. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lr_template TYPE REF TO data, lx_error TYPE REF TO cx_root, lo_template TYPE REF TO object. FIELD-SYMBOLS: TYPE data, TYPE data, TYPE INDEX TABLE, TYPE INDEX TABLE, TYPE data, TYPE data, TYPE data. CREATE DATA lr_template TYPE HANDLE mo_structdescr. ASSIGN lr_template->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'SMTG' CHANGING cg_data = ). ASSIGN COMPONENT 'HEADER' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'HEADER_T' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'CONTENT' OF STRUCTURE TO . ASSERT sy-subrc = 0. TRY. IF zif_abapgit_object~exists( ) = abap_true. CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>get EXPORTING iv_id = mv_template_id RECEIVING ro_instance = lo_template. ELSE. CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>create EXPORTING is_tmpl_hdr = RECEIVING ro_email_template = lo_template. ENDIF. CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~SET_TMPL_CONT_ALL') EXPORTING it_tmpl_cont = . READ TABLE ASSIGNING INDEX 1. IF sy-subrc = 0. ASSIGN COMPONENT 'NAME' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'DESCRIPTION' OF STRUCTURE TO . ASSERT sy-subrc = 0. CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~SET_TEXT') EXPORTING iv_name = iv_description = . ENDIF. tadir_insert( iv_package ). corr_insert( iv_package ). CALL METHOD lo_template->('IF_SMTG_EMAIL_TEMPLATE~SAVE') EXPORTING iv_lock = abap_true iv_commit = abap_true iv_wait = abap_true. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. CALL METHOD ('CL_SMTG_EMAIL_TEMPLATE')=>get EXPORTING iv_id = mv_template_id. rv_bool = abap_true. CATCH cx_root. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_SMTG' iv_argument = |{ mv_template_id }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lr_template TYPE REF TO data, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE data, TYPE data. CREATE DATA lr_template TYPE HANDLE mo_structdescr. ASSIGN lr_template->* TO . ASSERT sy-subrc = 0. get_template( IMPORTING es_template = ). ASSIGN COMPONENT 'HEADER' OF STRUCTURE TO . ASSERT sy-subrc = 0. TRY. clear_field( EXPORTING iv_fieldname = 'CREA_DATE_TIME' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'CREA_USER_ACCT' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'LST_CH_DATE_TIME' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'LST_CH_USER_ACCT' CHANGING cg_header = ). io_xml->add( iv_name = 'SMTG' ig_data = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_smim IMPLEMENTATION. METHOD build_filename. CONCATENATE ms_item-obj_name ms_item-obj_type iv_filename INTO rv_filename SEPARATED BY '.'. TRANSLATE rv_filename TO LOWER CASE. ENDMETHOD. METHOD find_content. DATA: lv_filename TYPE string, lt_files TYPE zif_abapgit_git_definitions=>ty_files_tt. FIELD-SYMBOLS: LIKE LINE OF lt_files. lv_filename = get_filename( iv_url ). lv_filename = build_filename( lv_filename ). lt_files = mo_files->get_files( ). READ TABLE lt_files ASSIGNING WITH KEY file COMPONENTS filename = lv_filename. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'SMIM, file not found' ). ENDIF. rv_content = -data. ENDMETHOD. METHOD get_filename. DATA: lv_lines TYPE i, lt_strings TYPE TABLE OF string. SPLIT iv_url AT '/' INTO TABLE lt_strings. lv_lines = lines( lt_strings ). ASSERT lv_lines > 0. READ TABLE lt_strings INDEX lv_lines INTO rv_filename. ASSERT sy-subrc = 0. ENDMETHOD. METHOD get_url_for_io. DATA: ls_io TYPE skwf_io, lv_url TYPE skwf_url, ls_smimloio TYPE smimloio, lv_loio TYPE sdok_docid. lv_loio = ms_item-obj_name. CLEAR ev_url. CLEAR ev_is_folder. SELECT SINGLE * FROM smimloio INTO ls_smimloio WHERE loio_id = lv_loio. "#EC CI_GENBUFF IF sy-subrc <> 0. RAISE EXCEPTION TYPE zcx_abapgit_not_found. ENDIF. IF ls_smimloio-lo_class = wbmr_c_skwf_folder_class. ev_is_folder = abap_true. ls_io-objtype = skwfc_obtype_folder. ELSE. ls_io-objtype = skwfc_obtype_loio. ENDIF. ls_io-class = ls_smimloio-lo_class. ls_io-objid = ls_smimloio-loio_id. CALL FUNCTION 'SKWF_NMSPC_IO_ADDRESS_GET' EXPORTING io = ls_io IMPORTING url = lv_url. ev_url = lv_url. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_loio TYPE sdok_docid. lv_loio = ms_item-obj_name. SELECT SINGLE chng_user FROM smimloio INTO rv_user WHERE loio_id = lv_loio. "#EC CI_GENBUFF IF sy-subrc <> 0 OR rv_user IS INITIAL. SELECT SINGLE chng_user FROM smimphio INTO rv_user WHERE loio_id = lv_loio. "#EC CI_GENBUFF IF sy-subrc <> 0 OR rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: li_api TYPE REF TO if_mr_api, lv_url TYPE string. TRY. get_url_for_io( IMPORTING ev_url = lv_url ). CATCH zcx_abapgit_not_found. " Deleted already (maybe by "folder with children") but record deletion in transport corr_insert( iv_package ). RETURN. ENDTRY. li_api = cl_mime_repository_api=>if_mr_api~get_api( ). li_api->delete( EXPORTING i_url = lv_url i_delete_children = abap_true EXCEPTIONS parameter_missing = 1 error_occured = 2 cancelled = 3 permission_failure = 4 not_found = 5 OTHERS = 6 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_url TYPE string, lv_folder TYPE abap_bool, lv_content TYPE xstring, lv_filename TYPE skwf_filnm, lv_io TYPE sdok_docid, lv_class TYPE smimloio-lo_class, ls_skwf_io TYPE skwf_io, li_api TYPE REF TO if_mr_api. li_api = cl_mime_repository_api=>if_mr_api~get_api( ). lv_io = ms_item-obj_name. io_xml->read( EXPORTING iv_name = 'URL' CHANGING cg_data = lv_url ). io_xml->read( EXPORTING iv_name = 'FOLDER' CHANGING cg_data = lv_folder ). io_xml->read( EXPORTING iv_name = 'CLASS' CHANGING cg_data = lv_class ). ls_skwf_io-objid = lv_io. IF lv_folder = abap_true. li_api->create_folder( EXPORTING i_url = lv_url i_language = mv_language i_dev_package = iv_package i_folder_loio = ls_skwf_io EXCEPTIONS parameter_missing = 1 error_occured = 2 cancelled = 3 permission_failure = 4 folder_exists = 5 OTHERS = 6 ). IF sy-subrc <> 5 AND sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ELSE. lv_filename = get_filename( lv_url ). ls_skwf_io-class = lv_class. IF ls_skwf_io-class IS INITIAL. cl_wb_mime_repository=>determine_io_class( EXPORTING filename = lv_filename IMPORTING io_class = ls_skwf_io-class ). CONCATENATE ls_skwf_io-class '_L' INTO ls_skwf_io-class. ENDIF. lv_content = find_content( lv_url ). li_api->put( EXPORTING i_url = lv_url i_content = lv_content i_dev_package = iv_package i_new_loio = ls_skwf_io EXCEPTIONS parameter_missing = 1 error_occured = 2 cancelled = 3 permission_failure = 4 data_inconsistency = 5 new_loio_already_exists = 6 is_folder = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_loio TYPE sdok_docid. lv_loio = ms_item-obj_name. SELECT SINGLE loio_id FROM smimloio INTO lv_loio WHERE loio_id = lv_loio. "#EC CI_GENBUFF rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_url TYPE string, lv_folder TYPE abap_bool, lv_filename TYPE string, lv_class TYPE smimloio-lo_class, ls_file TYPE zif_abapgit_git_definitions=>ty_file, lv_content TYPE xstring, li_api TYPE REF TO if_mr_api, lv_loio TYPE sdok_docid. lv_loio = ms_item-obj_name. TRY. get_url_for_io( IMPORTING ev_url = lv_url ev_is_folder = lv_folder ). CATCH zcx_abapgit_not_found. RETURN. ENDTRY. IF lv_folder = abap_false. li_api = cl_mime_repository_api=>if_mr_api~get_api( ). li_api->get( EXPORTING i_url = lv_url IMPORTING e_content = lv_content EXCEPTIONS parameter_missing = 1 error_occured = 2 not_found = 3 permission_failure = 4 OTHERS = 5 ). IF sy-subrc <> 0 AND sy-subrc <> 2 AND sy-subrc <> 3. zcx_abapgit_exception=>raise_t100( ). ENDIF. lv_filename = get_filename( lv_url ). CLEAR ls_file. ls_file-filename = build_filename( lv_filename ). ls_file-path = '/'. ls_file-data = lv_content. mo_files->add( ls_file ). SELECT SINGLE lo_class FROM smimloio INTO lv_class WHERE loio_id = lv_loio. "#EC CI_GENBUFF ENDIF. io_xml->add( iv_name = 'URL' ig_data = lv_url ). io_xml->add( iv_name = 'FOLDER' ig_data = lv_folder ). io_xml->add( iv_name = 'CLASS' ig_data = lv_class ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sktd IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_data TO . ASSERT sy-subrc = 0. CLEAR . ENDMETHOD. METHOD clear_fields. clear_field( EXPORTING iv_fieldname = 'METADATA-NAME' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-TYPE' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-MASTER_SYSTEM' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-VERSION' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'REF_OBJECT-URI' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'REF_OBJECT-DESCRIPTION' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_AT' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_BY' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_AT' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_BY' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-MASTER_LANGUAGE' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-RESPONSIBLE' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-PACKAGE_REF' CHANGING cs_data = cs_data ). clear_field( EXPORTING iv_fieldname = 'METADATA-LINKS' CHANGING cs_data = cs_data ). ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_object_key = ms_item-obj_name. TRY. CREATE DATA mr_data TYPE ('CL_KTD_OBJECT_DATA=>TY_KTD_DATA'). CREATE OBJECT mi_persistence TYPE ('CL_KTD_OBJECT_PERSIST'). CATCH cx_sy_create_error. zcx_abapgit_exception=>raise( |SKTD not supported by your NW release| ). ENDTRY. ENDMETHOD. METHOD get_wb_object_operator. DATA: ls_object_type TYPE wbobjtype, lx_error TYPE REF TO cx_root. IF mi_wb_object_operator IS BOUND. ri_wb_object_operator = mi_wb_object_operator. ENDIF. ls_object_type-objtype_tr = 'SKTD'. ls_object_type-subtype_wb = 'TYP'. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') EXPORTING object_type = ls_object_type object_key = mv_object_key RECEIVING result = mi_wb_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ri_wb_object_operator = mi_wb_object_operator. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: li_wb_object_operator TYPE REF TO object, li_object_data_model TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root. TRY. li_wb_object_operator = get_wb_object_operator( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = li_object_data_model. rv_user = li_object_data_model->get_changed_by( ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_error TYPE REF TO cx_root, li_wb_object_operator TYPE REF TO object. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') EXPORTING transport_request = iv_transport. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA li_wb_object_operator TYPE REF TO object. DATA li_object_data_model TYPE REF TO if_wb_object_data_model. FIELD-SYMBOLS TYPE any. ASSIGN mr_data->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'SKTD' CHANGING cg_data = ). li_wb_object_operator = get_wb_object_operator( ). CREATE OBJECT li_object_data_model TYPE ('CL_KTD_OBJECT_DATA'). li_object_data_model->set_data( ). tadir_insert( iv_package ). IF zif_abapgit_object~exists( ) = abap_true. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = li_object_data_model transport_request = iv_transport. ELSE. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = li_object_data_model data_selection = 'P' " if_wb_object_data_selection_co=>c_properties package = iv_package transport_request = iv_transport. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = li_object_data_model data_selection = 'D' " if_wb_object_data_selection_co=>c_data_content transport_request = iv_transport. ENDIF. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~ACTIVATE'). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. mi_persistence->get( p_object_key = mv_object_key p_version = 'A' p_existence_check_only = abap_true ). rv_bool = abap_true. CATCH cx_swb_exception. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'WBS_ENQUEUE_STRU' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: li_wb_object_operator TYPE REF TO object, li_object_data_model TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS TYPE any. ASSIGN mr_data->* TO . ASSERT sy-subrc = 0. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING version = 'A' IMPORTING data = eo_object_data = li_object_data_model. clear_fields( CHANGING cs_data = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. io_xml->add( iv_name = 'SKTD' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sicf IMPLEMENTATION. METHOD change_sicf. DATA: lt_icfhndlist TYPE icfhndlist, lt_existing TYPE TABLE OF icfhandler, ls_icfserdesc TYPE icfserdesc. FIELD-SYMBOLS: LIKE LINE OF lt_existing. lt_icfhndlist = to_icfhndlist( it_icfhandler ). " Do not add handlers if they already exist, it will make the below " call to SAP standard code raise an exception SELECT * FROM icfhandler INTO TABLE lt_existing WHERE icf_name = is_icfservice-icf_name ORDER BY PRIMARY KEY. LOOP AT lt_existing ASSIGNING . DELETE TABLE lt_icfhndlist FROM -icfhandler. ENDLOOP. MOVE-CORRESPONDING is_icfservice TO ls_icfserdesc. cl_icf_tree=>if_icf_tree~change_node( EXPORTING icf_name = is_icfservice-orig_name icfaltnme = get_icfaltname( is_icfservice ) icfparguid = iv_parent icfdocu = is_icfdocu doculang = mv_language icfhandlst = lt_icfhndlist package = iv_package application = space icfserdesc = ls_icfserdesc icfactive = abap_true EXCEPTIONS empty_icf_name = 1 no_new_virtual_host = 2 special_service_error = 3 parent_not_existing = 4 enqueue_error = 5 node_already_existing = 6 empty_docu = 7 doculang_not_installed = 8 security_info_error = 9 user_password_error = 10 password_encryption_error = 11 invalid_url = 12 invalid_otr_concept = 13 formflg401_error = 14 handler_error = 15 transport_error = 16 tadir_error = 17 package_not_found = 18 wrong_application = 19 not_allow_application = 20 no_application = 21 invalid_icfparguid = 22 alt_name_invalid = 23 alternate_name_exist = 24 wrong_icf_name = 25 no_authority = 26 OTHERS = 27 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD deserialize_otr. DATA: lt_sots TYPE zcl_abapgit_sots_handler=>ty_sots_tt, lt_sots_use TYPE zcl_abapgit_sots_handler=>ty_sots_use_tt. FIELD-SYMBOLS: LIKE LINE OF lt_sots_use. io_xml->read( EXPORTING iv_name = 'SOTS' CHANGING cg_data = lt_sots ). io_xml->read( EXPORTING iv_name = 'SOTS_USE' CHANGING cg_data = lt_sots_use ). LOOP AT lt_sots_use ASSIGNING . -obj_name = ms_item-obj_name. ENDLOOP. zcl_abapgit_sots_handler=>create_sots_from_data( iv_package = iv_package it_sots = lt_sots it_sots_use = lt_sots_use ). ENDMETHOD. METHOD find_parent. cl_icf_tree=>if_icf_tree~service_from_url( EXPORTING url = iv_url hostnumber = 0 IMPORTING icfnodguid = rv_parent EXCEPTIONS wrong_application = 1 no_application = 2 not_allow_application = 3 wrong_url = 4 no_authority = 5 OTHERS = 6 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD get_hash_from_object. DATA: lv_icfnodguid TYPE icfservice-icfnodguid, lv_url TYPE icfurlbuf, lv_ext_url TYPE string. SELECT SINGLE icfnodguid FROM icfservice INTO lv_icfnodguid WHERE icf_name = iv_obj_name(15) AND icfparguid = iv_obj_name+15. IF sy-subrc = 0. CALL FUNCTION 'HTTP_GET_URL_FROM_NODGUID' EXPORTING nodguid = lv_icfnodguid IMPORTING url = lv_url extended_url = lv_ext_url EXCEPTIONS icf_inconst = 1 OTHERS = 2. IF sy-subrc = 0. " It's possible that the URL contains the system id, for example for WD applications with names " longer than 15 characters. In that case, use the extended URL to generate the hash (#5064) IF lv_ext_url <> lv_url. rv_hash = zcl_abapgit_hash=>sha1_raw( zcl_abapgit_convert=>string_to_xstring_utf8( |{ lv_ext_url }| ) ). ELSE. rv_hash = zcl_abapgit_hash=>sha1_raw( zcl_abapgit_convert=>string_to_xstring_utf8( |{ lv_url }| ) ). ENDIF. ENDIF. ELSE. rv_hash = to_lower( iv_obj_name+15 ). ENDIF. ENDMETHOD. METHOD get_icfaltname. rv_icfaltnme = is_icfservice-icfaltnme. " If the original name is different (lower vs upper case), it needs to be deserialized IF is_icfservice-icfaltnme <> is_icfservice-icfaltnme_orig. rv_icfaltnme = is_icfservice-icfaltnme_orig. ENDIF. ENDMETHOD. METHOD insert_sicf. DATA: lt_icfhndlist TYPE icfhndlist, ls_icfserdesc TYPE icfserdesc, ls_icfdocu TYPE icfdocu, lv_icfnodguid TYPE icfnodguid, lv_parent TYPE icfparguid. lt_icfhndlist = to_icfhndlist( it_icfhandler ). lv_parent = find_parent( iv_url ). " Nice, it seems that the structure should be mistreated ls_icfdocu = is_icfdocu-icf_docu. MOVE-CORRESPONDING is_icfservice TO ls_icfserdesc. cl_icf_tree=>if_icf_tree~insert_node( EXPORTING icf_name = is_icfservice-orig_name icfparguid = lv_parent icfdocu = ls_icfdocu doculang = mv_language icfhandlst = lt_icfhndlist package = iv_package application = space icfserdesc = ls_icfserdesc icfactive = abap_true icfaltnme = get_icfaltname( is_icfservice ) IMPORTING icfnodguid = lv_icfnodguid EXCEPTIONS empty_icf_name = 1 no_new_virtual_host = 2 special_service_error = 3 parent_not_existing = 4 enqueue_error = 5 node_already_existing = 6 empty_docu = 7 doculang_not_installed = 8 security_info_error = 9 user_password_error = 10 password_encryption_error = 11 invalid_url = 12 invalid_otr_concept = 13 formflg401_error = 14 handler_error = 15 transport_error = 16 tadir_error = 17 package_not_found = 18 wrong_application = 19 not_allow_application = 20 no_application = 21 invalid_icfparguid = 22 alt_name_invalid = 23 alternate_name_exist = 24 wrong_icf_name = 25 no_authority = 26 OTHERS = 27 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. " Update item with name assigned by system SELECT SINGLE icfparguid INTO ms_item-obj_name+15 FROM icfservice WHERE icfnodguid = lv_icfnodguid. ENDMETHOD. METHOD read. DATA: lt_serv_info TYPE icfservtbl, ls_serv_info LIKE LINE OF lt_serv_info, ls_key TYPE ty_sicf_key. FIELD-SYMBOLS: LIKE LINE OF et_icfhandler. CLEAR es_icfservice. CLEAR es_icfdocu. CLEAR et_icfhandler. CLEAR ev_url. ls_key-icf_name = ms_item-obj_name(15). ls_key-icfparguid = ms_item-obj_name+15. cl_icf_tree=>if_icf_tree~get_info_from_serv( EXPORTING icf_name = ls_key-icf_name icfparguid = ls_key-icfparguid icf_langu = mv_language IMPORTING serv_info = lt_serv_info icfdocu = es_icfdocu url = ev_url EXCEPTIONS wrong_name = 1 wrong_parguid = 2 incorrect_service = 3 no_authority = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ASSERT lines( lt_serv_info ) = 1. READ TABLE lt_serv_info INDEX 1 INTO ls_serv_info. ASSERT sy-subrc = 0. MOVE-CORRESPONDING ls_serv_info-service TO es_icfservice. IF iv_clear = abap_true. CLEAR es_icfservice-icf_cuser. CLEAR es_icfservice-icf_cdate. CLEAR es_icfservice-icf_muser. CLEAR es_icfservice-icf_mdate. ENDIF. CLEAR es_icfdocu-icfparguid. APPEND LINES OF ls_serv_info-handlertbl TO et_icfhandler. LOOP AT et_icfhandler ASSIGNING . CLEAR -icfparguid. ENDLOOP. ENDMETHOD. METHOD serialize_otr. DATA: lt_sots TYPE zcl_abapgit_sots_handler=>ty_sots_tt, lt_sots_use TYPE zcl_abapgit_sots_handler=>ty_sots_use_tt. FIELD-SYMBOLS: LIKE LINE OF lt_sots_use. zcl_abapgit_sots_handler=>read_sots( EXPORTING iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params IMPORTING et_sots = lt_sots et_sots_use = lt_sots_use ). LOOP AT lt_sots_use ASSIGNING . CLEAR -obj_name. ENDLOOP. io_xml->add( iv_name = 'SOTS' ig_data = lt_sots ). io_xml->add( iv_name = 'SOTS_USE' ig_data = lt_sots_use ). ENDMETHOD. METHOD to_icfhndlist. FIELD-SYMBOLS: LIKE LINE OF it_list. " Convert to sorted table LOOP AT it_list ASSIGNING . INSERT -icfhandler INTO TABLE rt_list. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: ls_icfservice TYPE icfservice. read( EXPORTING iv_clear = abap_false IMPORTING es_icfservice = ls_icfservice ). rv_user = ls_icfservice-icf_muser. IF rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA ls_icfservice TYPE icfservice. read( IMPORTING es_icfservice = ls_icfservice ). IF ls_icfservice IS INITIAL. " It seems that the ICF service doesn't exist anymore. " But that's ok, because some objects like SAPC manage " the lifecycle of its ICF service by itself and already " deleted the service. RETURN. ENDIF. IF ls_icfservice-icfparguid CO '0'. " not supported by the SAP standard API zcx_abapgit_exception=>raise( 'SICF - cannot delete root node, delete node manually' ). ENDIF. " OTR long texts zcl_abapgit_sots_handler=>delete_sots( iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name ). " Delete Application Customizing Data the hard way, as it isn't done by the API. " If we wouldn't we would get errors from the API if entries exist. " Transaction SICF does the same. DELETE FROM icfapplcust WHERE icf_name = ls_icfservice-icf_name AND icfparguid = ls_icfservice-icfparguid. cl_icf_tree=>if_icf_tree~delete_node( EXPORTING icfparguid = ls_icfservice-icfparguid CHANGING icf_name = ls_icfservice-icf_name EXCEPTIONS no_virtual_host_delete = 1 special_service_error = 2 enqueue_error = 3 node_not_existing = 4 node_has_childs = 5 node_is_aliased = 6 node_not_in_original_system = 7 transport_error = 8 tadir_error = 9 db_error = 10 no_authority = 11 OTHERS = 12 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_icfservice TYPE icfservice, ls_read TYPE icfservice, ls_icfdocu TYPE icfdocu, lv_url TYPE string, lv_exists TYPE abap_bool, lt_icfhandler TYPE TABLE OF icfhandler. io_xml->read( EXPORTING iv_name = 'URL' CHANGING cg_data = lv_url ). io_xml->read( EXPORTING iv_name = 'ICFSERVICE' CHANGING cg_data = ls_icfservice ). io_xml->read( EXPORTING iv_name = 'ICFDOCU' CHANGING cg_data = ls_icfdocu ). io_xml->read( EXPORTING iv_name = 'ICFHANDLER_TABLE' CHANGING cg_data = lt_icfhandler ). lv_exists = zif_abapgit_object~exists( ). IF lv_exists = abap_false. insert_sicf( is_icfservice = ls_icfservice is_icfdocu = ls_icfdocu it_icfhandler = lt_icfhandler iv_package = iv_package iv_url = lv_url ). ELSE. read( IMPORTING es_icfservice = ls_read ). change_sicf( is_icfservice = ls_icfservice is_icfdocu = ls_icfdocu it_icfhandler = lt_icfhandler iv_package = iv_package iv_parent = ls_read-icfparguid ). ENDIF. " OTR long texts deserialize_otr( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA ls_key TYPE ty_sicf_key. SELECT SINGLE icfaltnme FROM icfservice INTO ls_key-icf_name WHERE icf_name = ms_item-obj_name(15) AND icfparguid = ms_item-obj_name+15. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_argument TYPE seqg3-garg. lv_argument = ms_item-obj_name(15). lv_argument+15(1) = '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESICFSER' iv_argument = lv_argument ). ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_bcdata TYPE bdcdata, lt_bcdata TYPE STANDARD TABLE OF bdcdata. ls_bcdata-program = 'RSICFTREE'. ls_bcdata-dynpro = '1000'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. ls_bcdata-dynpro = space. ls_bcdata-dynbegin = space. ls_bcdata-fnam = 'ICF_SERV'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=ONLI'. APPEND ls_bcdata TO lt_bcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SICF' it_bdcdata = lt_bcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, lv_hash TYPE ty_hash, lv_obj_name TYPE tadir-obj_name. FIELD-SYMBOLS LIKE LINE OF lt_tadir. lv_obj_name = to_upper( iv_filename(15) ) && '%'. lv_hash = iv_filename+15(25). SELECT * FROM tadir INTO CORRESPONDING FIELDS OF TABLE lt_tadir WHERE pgmid = 'R3TR' AND object = 'SICF' AND obj_name LIKE lv_obj_name ORDER BY PRIMARY KEY ##TOO_MANY_ITAB_FIELDS. "#EC CI_GENBUFF LOOP AT lt_tadir ASSIGNING . IF get_hash_from_object( -obj_name ) = lv_hash. cs_item-obj_name = -obj_name. RETURN. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. DATA: lv_rest TYPE string, lv_old_name TYPE string. SPLIT cv_filename AT '.' INTO lv_old_name lv_rest. cv_filename = |{ cv_filename(15) }{ get_hash_from_object( is_item-obj_name ) }.{ lv_rest }|. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_icfservice TYPE icfservice, ls_icfdocu TYPE icfdocu, lv_url TYPE string, lt_icfhandler TYPE TABLE OF icfhandler. read( IMPORTING es_icfservice = ls_icfservice es_icfdocu = ls_icfdocu et_icfhandler = lt_icfhandler ev_url = lv_url ). IF ls_icfservice IS INITIAL. RETURN. ENDIF. CLEAR ls_icfservice-icf_mandt. CLEAR ls_icfservice-icfnodguid. CLEAR ls_icfservice-icfparguid. CLEAR ls_icfservice-icfchildno. CLEAR ls_icfservice-icfaliasno. CLEAR ls_icfservice-icf_user. CLEAR ls_icfservice-icf_cclnt. CLEAR ls_icfservice-icf_mclnt. " If the original name is different (lower vs upper case), it needs to be serialized IF ls_icfservice-icfaltnme = ls_icfservice-icfaltnme_orig. CLEAR ls_icfservice-icfaltnme_orig. ENDIF. CLEAR ls_icfservice-icfbitmap. io_xml->add( iv_name = 'URL' ig_data = lv_url ). io_xml->add( iv_name = 'ICFSERVICE' ig_data = ls_icfservice ). io_xml->add( iv_name = 'ICFDOCU' ig_data = ls_icfdocu ). io_xml->add( iv_name = 'ICFHANDLER_TABLE' ig_data = lt_icfhandler ). " OTR long texts serialize_otr( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_shma IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. SELECT SINGLE chg_user FROM shma_attributes INTO rv_user WHERE area_name = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. " We can't use FM SHMA_DELETE_AREA because it depends " on the corresponding class, but in abapGit it has its own " lifecycle. Therefore we have to reimplement most of the " FMs logic CONSTANTS: lc_request_delete TYPE i VALUE 4. DATA: lv_request TYPE i, lv_area_name TYPE shm_area_name, lv_order TYPE e070-trkorr, lv_task TYPE e070-trkorr, lv_append TYPE abap_bool, ls_tdevc TYPE tdevc, lo_cts_if TYPE REF TO object. lv_area_name = ms_item-obj_name. TRY. CALL FUNCTION 'ENQUEUE_E_SHM_AREA' EXPORTING mode_shma_attributes = 'E' area_name = lv_area_name x_area_name = ' ' _scope = '2' _wait = ' ' _collect = ' ' EXCEPTIONS foreign_lock = 1 system_failure = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL METHOD ('\PROGRAM=SAPMSHM_MONITOR\CLASS=LCL_SHMM')=>('FREE_AREA_BY_NAME') EXPORTING area_name = lv_area_name affect_server = cl_shm_area=>affect_all_servers. CREATE OBJECT lo_cts_if TYPE ('\FUNCTION-POOL=SHMA\CLASS=LCL_CTS_INTERFACE') EXPORTING area = lv_area_name. CALL METHOD lo_cts_if->('CHECK_AREA') EXPORTING request = lc_request_delete IMPORTING access_mode = lv_request appendable = lv_append. IF lv_request <> lc_request_delete. zcx_abapgit_exception=>raise( |Error deleting SHMA { ms_item-obj_name }| ). ENDIF. CALL METHOD lo_cts_if->('INSERT_AREA') EXPORTING request = lc_request_delete IMPORTING order = lv_order task = lv_task. DELETE FROM shma_attributes WHERE area_name = lv_area_name. DELETE FROM shma_start WHERE area_name = lv_area_name. CALL FUNCTION 'TR_DEVCLASS_GET' EXPORTING iv_devclass = iv_package IMPORTING es_tdevc = ls_tdevc EXCEPTIONS OTHERS = 1. IF sy-subrc = 0 AND ls_tdevc-korrflag IS INITIAL. " TADIR entries for local objects must be deleted 'by hand' tadir_delete( ). ENDIF. CALL METHOD ('\PROGRAM=SAPLSHMA\CLASS=LCL_SHMA_HELPER')=>('DELETE_RUNTIME_SETTINGS') EXPORTING area_name = lv_area_name. CALL FUNCTION 'DEQUEUE_E_SHM_AREA' EXPORTING mode_shma_attributes = 'E' area_name = lv_area_name x_area_name = ' ' _scope = '3' _synchron = ' ' _collect = ' '. CATCH cx_root. zcx_abapgit_exception=>raise( |Error deleting SHMA { ms_item-obj_name }| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_area_name TYPE shm_area_name, ls_area_attributes TYPE shma_attributes. lv_area_name = ms_item-obj_name. io_xml->read( EXPORTING iv_name = 'AREA_ATTRIBUTES' CHANGING cg_data = ls_area_attributes ). tadir_insert( iv_package ). TRY. CALL METHOD ('\PROGRAM=SAPLSHMA\CLASS=LCL_SHMA_HELPER')=>('INSERT_AREA') EXPORTING area_name = lv_area_name attributes = ls_area_attributes force_overwrite = abap_true no_class_generation = abap_false silent_mode = abap_true. CATCH cx_root. zcx_abapgit_exception=>raise( |Error serializing SHMA { ms_item-obj_name }| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_area_name TYPE shm_area_name. SELECT SINGLE area_name FROM shma_attributes INTO lv_area_name WHERE area_name = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_bcdata TYPE bdcdata, lt_bcdata TYPE STANDARD TABLE OF bdcdata. ls_bcdata-program = 'SAPLSHMA'. ls_bcdata-dynpro = '0100'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'SHMA_ATTRIBUTES-AREA_NAME'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=SHOW'. APPEND ls_bcdata TO lt_bcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SHMA' it_bdcdata = lt_bcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_area_name TYPE shm_area_name, ls_area_attributes TYPE shma_attributes. lv_area_name = ms_item-obj_name. TRY. CALL METHOD ('\PROGRAM=SAPLSHMA\CLASS=LCL_SHMA_HELPER')=>('READ_AREA_ATTRIBUTES_ALL') EXPORTING area_name = lv_area_name IMPORTING area_attributes = ls_area_attributes. CLEAR: ls_area_attributes-chg_user, ls_area_attributes-chg_date, ls_area_attributes-chg_time, ls_area_attributes-cls_gen_user, ls_area_attributes-cls_gen_date, ls_area_attributes-cls_gen_time. io_xml->add( iv_name = 'AREA_ATTRIBUTES' ig_data = ls_area_attributes ). CATCH cx_root. zcx_abapgit_exception=>raise( |Error serializing SHMA { ms_item-obj_name }| ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_shlp IMPLEMENTATION. METHOD adjust_exit. CONSTANTS lc_standard_exit TYPE dd30v-selmexit VALUE 'RS_DD_SELMEXIT'. IF cv_exit IS NOT INITIAL AND zcl_abapgit_factory=>get_function_module( )->function_exists( cv_exit ) = abap_false. " If exit function does not exist, replace it with standard SAP function " which exists in 7.02 and higher cv_exit = lc_standard_exit. ENDIF. ENDMETHOD. METHOD check_exit. DATA lv_exit TYPE dd30v-selmexit. rv_done = abap_true. IF iv_exit IS NOT INITIAL. " Check if exit function is set correctly SELECT SINGLE selmexit FROM dd30v INTO lv_exit WHERE shlpname = ms_item-obj_name. IF sy-subrc = 0 AND lv_exit <> iv_exit. rv_done = abap_false. ENDIF. ENDIF. ENDMETHOD. METHOD handle_dependencies. " For search helps with dependency on exit function, we use two phases: " 1) DDIC phase: " - If function does not exit, replace it with a standard SAP function " 2) LATE phase " - If function was replaced, change it to the correct exit function CASE iv_step. WHEN zif_abapgit_object=>gc_step_id-ddic. adjust_exit( CHANGING cv_exit = cv_exit ). WHEN zif_abapgit_object=>gc_step_id-late. cv_done = check_exit( cv_exit ). WHEN OTHERS. ASSERT 0 = 1. ENDCASE. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE as4user FROM dd30l INTO rv_user WHERE shlpname = ms_item-obj_name AND as4local = 'A'. "#EC CI_GENBUFF IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. delete_ddic( 'H' ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_name TYPE ddobjname, lv_done TYPE abap_bool, ls_dd30v TYPE dd30v, lt_dd31v TYPE TABLE OF dd31v, lt_dd32p TYPE TABLE OF dd32p, lt_dd33v TYPE TABLE OF dd33v. io_xml->read( EXPORTING iv_name = 'DD30V' CHANGING cg_data = ls_dd30v ). handle_dependencies( EXPORTING iv_step = iv_step CHANGING cv_exit = ls_dd30v-selmexit cv_done = lv_done ). IF lv_done = abap_true. RETURN. ENDIF. io_xml->read( EXPORTING iv_name = 'DD31V_TABLE' CHANGING cg_data = lt_dd31v ). io_xml->read( EXPORTING iv_name = 'DD32P_TABLE' CHANGING cg_data = lt_dd32p ). io_xml->read( EXPORTING iv_name = 'DD33V_TABLE' CHANGING cg_data = lt_dd33v ). corr_insert( iv_package = iv_package ig_object_class = 'DICT' ). lv_name = ms_item-obj_name. CALL FUNCTION 'DDIF_SHLP_PUT' EXPORTING name = lv_name dd30v_wa = ls_dd30v TABLES dd31v_tab = lt_dd31v dd32p_tab = lt_dd32p dd33v_tab = lt_dd33v EXCEPTIONS shlp_not_found = 1 name_inconsistent = 2 shlp_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_shlpname TYPE dd30l-shlpname. SELECT SINGLE shlpname FROM dd30l INTO lv_shlpname WHERE shlpname = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECT=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_name TYPE ddobjname, lv_state TYPE ddgotstate, ls_dd30v TYPE dd30v, lt_dd31v TYPE TABLE OF dd31v, lt_dd32p TYPE TABLE OF dd32p, lt_dd33v TYPE TABLE OF dd33v. FIELD-SYMBOLS: LIKE LINE OF lt_dd32p. lv_name = ms_item-obj_name. CALL FUNCTION 'DDIF_SHLP_GET' EXPORTING name = lv_name state = 'A' langu = mv_language IMPORTING gotstate = lv_state dd30v_wa = ls_dd30v TABLES dd31v_tab = lt_dd31v dd32p_tab = lt_dd32p dd33v_tab = lt_dd33v EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF ls_dd30v IS INITIAL OR lv_state <> 'A'. RETURN. ENDIF. CLEAR: ls_dd30v-as4user, ls_dd30v-as4date, ls_dd30v-as4time. LOOP AT lt_dd32p ASSIGNING . * clear information inherited from domain CLEAR: -domname, -headlen, -scrlen1, -scrlen2, -datatype, -leng, -outputlen, -decimals, -lowercase, -signflag, -convexit. ENDLOOP. io_xml->add( iv_name = 'DD30V' ig_data = ls_dd30v ). io_xml->add( ig_data = lt_dd31v iv_name = 'DD31V_TABLE' ). io_xml->add( ig_data = lt_dd32p iv_name = 'DD32P_TABLE' ). io_xml->add( ig_data = lt_dd33v iv_name = 'DD33V_TABLE' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_shi8 IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_assignment_id = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " not stored by SAP ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_deleted TYPE abap_bool, ls_message TYPE hier_mess. CALL FUNCTION 'STREE_SFW_ASSIGNMENT_DELETE' EXPORTING assignment_id = mv_assignment_id IMPORTING id_deleted = lv_deleted message = ls_message. IF lv_deleted = abap_false. zcx_abapgit_exception=>raise( |{ ls_message-msgtxt }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_assignment_data TYPE ttree_sfw_nodes, ls_node_data TYPE hier_iface, lv_saved TYPE abap_bool, ls_message TYPE hier_mess. io_xml->read( EXPORTING iv_name = 'SHI8' CHANGING cg_data = ls_assignment_data ). ls_node_data-tree_id = ls_assignment_data-tree_id. ls_node_data-node_id = ls_assignment_data-node_id. CALL FUNCTION 'STREE_SFW_ASSIGNMENT_SAVE' EXPORTING assignment_id = ls_assignment_data-sfw_ass_id switch_id = ls_assignment_data-switch_id reaction = ls_assignment_data-reaction node_data = ls_node_data IMPORTING data_saved = lv_saved message = ls_message. IF lv_saved = abap_false. zcx_abapgit_exception=>raise( |{ ls_message-msgtxt }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. CALL FUNCTION 'STREE_SFW_ASSIGNMENT_ID_EXISTS' EXPORTING assignment_id = mv_assignment_id IMPORTING exists = rv_bool. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lt_assignments TYPE STANDARD TABLE OF hier_sfw_assignment_id, ls_assignment LIKE LINE OF lt_assignments, lt_assignment_data TYPE STANDARD TABLE OF ttree_sfw_nodes, ls_assignment_data LIKE LINE OF lt_assignment_data. ls_assignment-sfw_ass_id = mv_assignment_id. INSERT ls_assignment INTO TABLE lt_assignments. CALL FUNCTION 'STREE_SFW_ASSIGNMENT_READ' TABLES it_assignments = lt_assignments et_assignment_data = lt_assignment_data. READ TABLE lt_assignment_data INTO ls_assignment_data INDEX 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error serializing { ms_item-obj_type } { ms_item-obj_name }| ). ENDIF. io_xml->add( iv_name = 'SHI8' ig_data = ls_assignment_data ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_shi5 IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_extension = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " not stored by SAP ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_msg TYPE hier_mess, lv_found_users TYPE hier_yesno, ls_check_extensions TYPE treenamesp, lt_check_extensions TYPE TABLE OF treenamesp, lv_obj_name TYPE ko200-obj_name. " STREE_EXTENSION_DELETE shows a popup so do the same here ls_check_extensions-extension = mv_extension. INSERT ls_check_extensions INTO TABLE lt_check_extensions. CALL FUNCTION 'STREE_CHECK_EXTENSION' IMPORTING message = ls_msg TABLES check_extension = lt_check_extensions. READ TABLE lt_check_extensions INTO ls_check_extensions INDEX 1. IF ls_check_extensions-original = abap_false. zcx_abapgit_exception=>raise( 'Delete enhancement ID in your source system' ). ENDIF. lv_obj_name = mv_extension. CALL FUNCTION 'STREE_TRANSPORT_CHECK' EXPORTING object = 'SHI5' obj_name = lv_obj_name IMPORTING message = ls_msg. IF ls_msg-msgty = 'E'. MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'STREE_EXTENSION_USAGE' EXPORTING extension = mv_extension no_display = abap_true IMPORTING message = ls_msg extension_is_used = lv_found_users. IF ls_msg-msgty = 'E'. MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF lv_found_users = abap_true. zcx_abapgit_exception=>raise( 'Enhancement ID is still used' ). ENDIF. CALL FUNCTION 'STREE_TRANSPORT_INSERT' EXPORTING object = 'SHI5' obj_name = lv_obj_name IMPORTING message = ls_msg. IF ls_msg-msgty = 'E'. MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. DELETE FROM ttree_ext WHERE extension = mv_extension. DELETE FROM ttree_extt WHERE extension = mv_extension. IF ls_check_extensions-transport = abap_false. " no transportable Devclass -> delete TADIR tadir_delete( ). ENDIF. " reset some internal tables CALL FUNCTION 'STREE_RESET_FUGR_SHI5_TABLES'. ENDMETHOD. METHOD zif_abapgit_object~deserialize. " We cannot use STREE_EXTENSION_NAME_CREATE " the create logic is directly tied to the UI " " Do it like here LSHI20F01 -> SAVE_DATA DATA: ls_extension TYPE ty_extension. io_xml->read( EXPORTING iv_name = 'SHI5' CHANGING cg_data = ls_extension ). INSERT ttree_ext FROM ls_extension-header. DELETE FROM ttrees WHERE extension = ls_extension-header-extension. MODIFY ttrees FROM TABLE ls_extension-sequences. DELETE FROM ttree_extt WHERE extension = ls_extension-header-extension. MODIFY ttree_extt FROM TABLE ls_extension-texts. corr_insert( iv_package ). tadir_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_extension_header TYPE ttree_ext. CALL FUNCTION 'STREE_EXTENSION_EXISTS' EXPORTING extension = mv_extension IMPORTING extension_header = ls_extension_header. rv_bool = boolc( ls_extension_header IS NOT INITIAL ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lt_extension TYPE STANDARD TABLE OF ttree_ext. FIELD-SYMBOLS: LIKE LINE OF lt_extension. INSERT INITIAL LINE INTO TABLE lt_extension ASSIGNING . -extension = mv_extension. CALL FUNCTION 'STREE_EXTENSION_NAME_F4' EXPORTING originals_only = abap_true TABLES show_only_extensions = lt_extension. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_extension TYPE ty_extension. CALL FUNCTION 'STREE_EXTENSION_EXISTS' EXPORTING extension = mv_extension IMPORTING extension_header = ls_extension-header. SELECT * FROM ttree_extt INTO TABLE ls_extension-texts WHERE extension = mv_extension ORDER BY PRIMARY KEY. SELECT * FROM ttrees INTO TABLE ls_extension-sequences WHERE extension = mv_extension ORDER BY PRIMARY KEY. io_xml->add( iv_name = 'SHI5' ig_data = ls_extension ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_shi3 IMPLEMENTATION. METHOD clear_fields. FIELD-SYMBOLS LIKE LINE OF ct_nodes. CLEAR: cs_head-luser, cs_head-ldate, cs_head-ltime. CLEAR: cs_head-fuser, cs_head-fdate, cs_head-ftime. CLEAR: cs_head-frelease, cs_head-lrelease. CLEAR: cs_head-responsibl. LOOP AT ct_nodes ASSIGNING . CLEAR: -luser, -ldate, -ltime. CLEAR: -fuser, -fdate, -ftime. CLEAR: -frelease, -lrelease. ENDLOOP. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_tree_id = ms_item-obj_name. ENDMETHOD. METHOD delete_tree_structure. CALL FUNCTION 'STREE_EXTERNAL_DELETE' EXPORTING structure_id = iv_structure_id no_confirmation_popup = abap_true. ENDMETHOD. METHOD has_authorization. AUTHORITY-CHECK OBJECT 'S_DEVELOP' ID 'DEVCLASS' FIELD iv_devclass ID 'OBJTYPE' FIELD 'MENU' ID 'OBJNAME' FIELD iv_structure_id ID 'P_GROUP' DUMMY ID 'ACTVT' FIELD iv_activity. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( iv_msgid = 'S#' iv_msgno = '203' ). ENDIF. ENDMETHOD. METHOD insert_transport. DATA: ls_msg TYPE hier_mess, ls_object TYPE e071, lt_objects TYPE TABLE OF e071, lt_keys TYPE TABLE OF e071k, ls_ko200 TYPE ko200, lt_ko200 TYPE TABLE OF ko200. " This function shows a popup so get objects and keys and insert " them into transport below CALL FUNCTION 'STREE_INSERT_ALL_IN_TRANSPORT' EXPORTING structure_id = mv_tree_id iv_return_objects_and_keys = abap_true IMPORTING message = ls_msg TABLES et_objects = lt_objects et_keys = lt_keys. IF ls_msg-msgty = 'E'. MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. LOOP AT lt_objects INTO ls_object. MOVE-CORRESPONDING ls_object TO ls_ko200. INSERT ls_ko200 INTO TABLE lt_ko200. ENDLOOP. CALL FUNCTION 'TR_RECORD_OBJ_CHANGE_TO_REQ' EXPORTING iv_request = iv_transport it_objects = lt_ko200 it_keys = lt_keys EXCEPTIONS cancel = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD is_used. DATA: lt_used_in_structures TYPE STANDARD TABLE OF ttree WITH DEFAULT KEY. CALL FUNCTION 'STREE_GET_STRUCTURE_USAGE' EXPORTING structure_id = iv_structure_id TABLES used_in_structures = lt_used_in_structures. IF lt_used_in_structures IS NOT INITIAL. zcx_abapgit_exception=>raise( |IMG structure ID { iv_structure_id } is still used| ). ENDIF. ENDMETHOD. METHOD jump_sbach04. DATA: ls_message TYPE hier_mess, lv_structure_id TYPE hier_treeg. lv_structure_id = ms_item-obj_name. CALL FUNCTION 'STREE_EXTERNAL_EDIT' EXPORTING structure_id = lv_structure_id language = mv_language edit_structure = abap_false no_commit_work = abap_false activity = 'D' IMPORTING message = ls_message. IF ls_message IS NOT INITIAL. zcx_abapgit_exception=>raise_t100( iv_msgid = ls_message-msgid iv_msgno = ls_message-msgno iv_msgv1 = ls_message-msgv1 iv_msgv2 = ls_message-msgv2 iv_msgv3 = ls_message-msgv3 iv_msgv4 = ls_message-msgv4 ). ENDIF. ENDMETHOD. METHOD jump_se43. DATA: lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPLBMEN'. -dynpro = '0200'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=SHOW'. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BMENUNAME-ID'. -fval = ms_item-obj_name. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SE43' it_bdcdata = lt_bdcdata ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: ls_head TYPE ttree. CALL FUNCTION 'STREE_STRUCTURE_READ' EXPORTING structure_id = mv_tree_id IMPORTING structure_header = ls_head. rv_user = ls_head-luser. ENDMETHOD. METHOD zif_abapgit_object~delete. CONSTANTS lc_activity_delete_06 TYPE activ_auth VALUE '06'. TRY. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. CATCH zcx_abapgit_exception. RETURN. ENDTRY. has_authorization( iv_structure_id = mv_tree_id iv_devclass = ms_item-devclass iv_activity = lc_activity_delete_06 ). is_used( mv_tree_id ). delete_tree_structure( mv_tree_id ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_msg TYPE hier_mess, ls_head TYPE ttree, ls_ttree TYPE ttree, lt_titles TYPE TABLE OF ttreet, lt_nodes TYPE TABLE OF hier_iface, lt_texts TYPE TABLE OF hier_texts, lt_refs TYPE TABLE OF hier_ref. io_xml->read( EXPORTING iv_name = 'TREE_HEAD' CHANGING cg_data = ls_head ). io_xml->read( EXPORTING iv_name = 'TREE_TITLES' CHANGING cg_data = lt_titles ). io_xml->read( EXPORTING iv_name = 'TREE_NODES' CHANGING cg_data = lt_nodes ). io_xml->read( EXPORTING iv_name = 'TREE_REFS' CHANGING cg_data = lt_refs ). io_xml->read( EXPORTING iv_name = 'TREE_TEXTS' CHANGING cg_data = lt_texts ). mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'SPRAS' iv_keep_master_lang = abap_true CHANGING ct_tab = lt_titles ). mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'SPRAS' iv_keep_master_lang = abap_true CHANGING ct_tab = lt_texts ). IF zif_abapgit_object~exists( ) = abap_true. delete_tree_structure( mv_tree_id ). ENDIF. CALL FUNCTION 'STREE_HIERARCHY_SAVE' EXPORTING structure_id = mv_tree_id structure_type = ls_head-type structure_description = space structure_masterlanguage = mv_language structure_responsible = sy-uname structure_buffermode = ls_head-buffermode development_class = iv_package IMPORTING message = ls_msg TABLES list_of_nodes = lt_nodes list_of_references = lt_refs list_of_texts = lt_texts structure_descriptions = lt_titles EXCEPTIONS no_nodes_given = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ELSEIF ls_msg-msgty = 'E'. MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. " Set buffer mode for menus (see function BMENU_CREATE_TREE) SELECT SINGLE * FROM ttree INTO ls_ttree WHERE type = 'BMENU' AND id = mv_tree_id. IF sy-subrc = 0. ls_ttree-buffermode = ls_head-buffermode. ls_ttree-buffervar = ls_head-buffervar. MODIFY ttree FROM ls_ttree. ENDIF. IF zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ) = abap_true. " Add necessary SHI6, SHI7, and TABU entries to transport (SAP Note 455542) insert_transport( iv_transport ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_msg TYPE hier_mess, ls_header TYPE ttree, ls_tadir TYPE tadir. " Ignore buffer and get state from DB CALL FUNCTION 'STREE_STRUCTURE_EXIST' EXPORTING structure_id = mv_tree_id read_from_database = abap_true do_not_read_devclass = abap_false IMPORTING message = ls_msg structure_header = ls_header structure_tadir = ls_tadir. rv_bool = boolc( ls_header-id IS NOT INITIAL ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_head TYPE ttree. CALL FUNCTION 'STREE_STRUCTURE_READ' EXPORTING structure_id = mv_tree_id IMPORTING structure_header = ls_head. CASE ls_head-type. WHEN 'BMENU'. jump_se43( ). rv_exit = abap_true. WHEN 'GHIER'. jump_sbach04( ). rv_exit = abap_true. ENDCASE. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_msg TYPE hier_mess, ls_head TYPE ttree, lt_titles TYPE TABLE OF ttreet, lt_nodes TYPE TABLE OF hier_iface, lt_texts TYPE TABLE OF hier_texts, lt_refs TYPE TABLE OF hier_ref, lv_all_languages TYPE abap_bool. CALL FUNCTION 'STREE_STRUCTURE_READ' EXPORTING structure_id = mv_tree_id IMPORTING message = ls_msg structure_header = ls_head TABLES description = lt_titles. IF mo_i18n_params->ms_params-main_language_only = abap_true OR mo_i18n_params->is_lxe_applicable( ) = abap_true. lv_all_languages = abap_false. DELETE lt_titles WHERE spras <> mv_language. ELSE. lv_all_languages = abap_true. mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'SPRAS' iv_keep_master_lang = abap_true CHANGING ct_tab = lt_titles ). ENDIF. CALL FUNCTION 'STREE_HIERARCHY_READ' EXPORTING structure_id = mv_tree_id read_also_texts = abap_true all_languages = lv_all_languages language = mv_language IMPORTING message = ls_msg TABLES list_of_nodes = lt_nodes list_of_references = lt_refs list_of_texts = lt_texts. clear_fields( CHANGING cs_head = ls_head ct_nodes = lt_nodes ). SORT lt_titles BY id. DELETE ADJACENT DUPLICATES FROM lt_titles COMPARING spras id. SORT lt_texts BY spras. DELETE ADJACENT DUPLICATES FROM lt_texts COMPARING spras node_id. mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'SPRAS' iv_keep_master_lang = abap_true CHANGING ct_tab = lt_texts ). io_xml->add( iv_name = 'TREE_HEAD' ig_data = ls_head ). io_xml->add( iv_name = 'TREE_TITLES' ig_data = lt_titles ). io_xml->add( iv_name = 'TREE_NODES' ig_data = lt_nodes ). io_xml->add( iv_name = 'TREE_REFS' ig_data = lt_refs ). io_xml->add( iv_name = 'TREE_TEXTS' ig_data = lt_texts ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sfsw IMPLEMENTATION. METHOD activate. DATA: lt_switches TYPE sfw_switchtab, lt_msgtab TYPE sprot_u_tab. IF zif_abapgit_object~is_active( ) = abap_true. RETURN. ENDIF. APPEND mv_switch TO lt_switches. cl_sfw_activate=>activate_sfsw( EXPORTING p_switches = lt_switches p_version = 'I' IMPORTING p_msgtab = lt_msgtab ). READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. IF sy-subrc = 0. zcx_abapgit_exception=>raise( 'Error activating SFBS' ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_switch = is_item-obj_name. ENDMETHOD. METHOD create. TRY. " make sure to clear cache ro_switch = cl_sfw_sw=>create_switch( mv_switch ). ro_switch->free( ). ro_switch = cl_sfw_sw=>create_switch( mv_switch ). CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. zcx_abapgit_exception=>raise( 'Error from CL_SFW_SW=>CREATE_SWITCH' ). ENDTRY. ENDMETHOD. METHOD get. TRY. " make sure to clear cache ro_switch = cl_sfw_sw=>get_switch( mv_switch ). ro_switch->free( ). ro_switch = cl_sfw_sw=>get_switch( mv_switch ). CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. zcx_abapgit_exception=>raise( 'Error from CL_SFW_SW=>GET_SWITCH' ). ENDTRY. ENDMETHOD. METHOD unlock. CALL FUNCTION 'DEQUEUE_EEUDB' EXPORTING relid = 'SW' name = ms_item-obj_name _synchron = 'X' _scope = '1' mode_eudb = abap_true. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: ls_data TYPE sfw_switch. ls_data = get( )->get_header_data( ). rv_user = ls_data-changedby. IF rv_user IS INITIAL. rv_user = ls_data-author. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lt_delete TYPE sfw_switchtab, lt_msgtab TYPE sprot_u_tab. APPEND mv_switch TO lt_delete. cl_sfw_activate=>delete_sfsw( EXPORTING p_switches = lt_delete IMPORTING p_msgtab = lt_msgtab ). READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. IF sy-subrc = 0. zcx_abapgit_exception=>raise( 'Error deleting SFSW' ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_switch TYPE REF TO cl_sfw_sw, ls_header TYPE sfw_switch, lv_name_32 TYPE sfw_name32, lv_name_80 TYPE sfw_name80, lt_parent_bf TYPE sfw_bf_sw_outtab, lt_conflicts TYPE sfw_confl_outtab. IF iv_step = zif_abapgit_object=>gc_step_id-late. activate( ). RETURN. ENDIF. io_xml->read( EXPORTING iv_name = 'HEADER' CHANGING cg_data = ls_header ). io_xml->read( EXPORTING iv_name = 'NAME32' CHANGING cg_data = lv_name_32 ). io_xml->read( EXPORTING iv_name = 'NAME80' CHANGING cg_data = lv_name_80 ). io_xml->read( EXPORTING iv_name = 'PARENT_BF' CHANGING cg_data = lt_parent_bf ). io_xml->read( EXPORTING iv_name = 'CONFLICTS' CHANGING cg_data = lt_conflicts ). TRY. IF zif_abapgit_object~exists( ) = abap_true. lo_switch = get( ). ELSE. lo_switch = create( ). ENDIF. CATCH cx_pak_not_authorized cx_pak_invalid_state cx_pak_invalid_data. zcx_abapgit_exception=>raise( 'error in CL_SFW_SW=>CREATE_SWITCH' ). ENDTRY. ls_header-author = sy-uname. ls_header-createdon = sy-datum. lo_switch->set_header_data( ls_header ). lo_switch->set_texts( p_32 = lv_name_32 p_80 = lv_name_80 ). lo_switch->set_parent_bf( lt_parent_bf ). lo_switch->set_conflicts( lt_conflicts ). set_default_package( iv_package ). tadir_insert( iv_package ). lo_switch->save_all( EXCEPTIONS not_saved = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error in CL_SFW_SW->SAVE_ALL' ). ENDIF. unlock( ). deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_sfsw ). zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA ls_tadir TYPE tadir. IF cl_sfw_sw=>check_existence( mv_switch ) = abap_false. RETURN. ENDIF. SELECT SINGLE * FROM tadir INTO ls_tadir WHERE pgmid = 'R3TR' AND object = ms_item-obj_type AND obj_name = ms_item-obj_name. IF ls_tadir IS INITIAL. RETURN. ENDIF. rv_bool = abap_true. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' iv_argument = ms_item-obj_name iv_prefix = 'SW' ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_switch TYPE REF TO cl_sfw_sw, ls_header TYPE sfw_switch, lv_name_32 TYPE sfw_name32, lv_name_80 TYPE sfw_name80, lt_parent_bf TYPE sfw_bf_sw_outtab, lt_conflicts TYPE sfw_confl_outtab. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. lo_switch = get( ). ls_header = lo_switch->get_header_data( ). CLEAR: ls_header-author, ls_header-version, ls_header-createdon, ls_header-changedby, ls_header-changedon, ls_header-timestamp. lo_switch->get_texts( IMPORTING p_32 = lv_name_32 p_80 = lv_name_80 ). lt_parent_bf = lo_switch->get_parent_bf( ). lt_conflicts = lo_switch->get_conflicts( ). io_xml->add( ig_data = ls_header iv_name = 'HEADER' ). io_xml->add( ig_data = lv_name_32 iv_name = 'NAME32' ). io_xml->add( ig_data = lv_name_80 iv_name = 'NAME80' ). io_xml->add( ig_data = lt_parent_bf iv_name = 'PARENT_BF' ). io_xml->add( ig_data = lt_conflicts iv_name = 'CONFLICTS' ). serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_sfsw ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sfpi IMPLEMENTATION. METHOD interface_to_xstring. DATA: li_fp_interface TYPE REF TO if_fp_interface, li_wb_interface TYPE REF TO if_fp_wb_interface. TRY. li_wb_interface = load( ). li_fp_interface ?= li_wb_interface->get_object( ). rv_xstr = cl_fp_helper=>convert_interface_to_xstring( li_fp_interface ). CATCH cx_fp_api. zcx_abapgit_exception=>raise( 'SFPI error, interface_to_xstring' ). ENDTRY. ENDMETHOD. METHOD load. DATA: lv_name TYPE fpname. lv_name = ms_item-obj_name. TRY. ri_wb_interface = cl_fp_wb_interface=>load( lv_name ). CATCH cx_fp_api. zcx_abapgit_exception=>raise( 'SFPI error, load' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE lastuser FROM fpinterface INTO rv_user WHERE name = ms_item-obj_name AND state = 'A'. IF rv_user IS INITIAL. SELECT SINGLE firstuser FROM fpinterface INTO rv_user WHERE name = ms_item-obj_name AND state = 'A'. ENDIF. IF rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_name TYPE fpname, lo_wb_interface TYPE REF TO cl_fp_wb_interface. lo_wb_interface ?= load( ). lv_name = ms_item-obj_name. TRY. lo_wb_interface->delete( lv_name ). CATCH cx_fp_api. zcx_abapgit_exception=>raise( 'SFPI error, delete' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_xstr TYPE xstring, lv_name TYPE fpname, li_wb_object TYPE REF TO if_fp_wb_interface, li_interface TYPE REF TO if_fp_interface. lv_name = ms_item-obj_name. lv_xstr = cl_ixml_80_20=>render_to_xstring( io_xml->get_raw( ) ). IF zif_abapgit_object~exists( ) = abap_true. zif_abapgit_object~delete( iv_package = iv_package iv_transport = iv_transport ). ENDIF. TRY. li_interface = cl_fp_helper=>convert_xstring_to_interface( lv_xstr ). tadir_insert( iv_package ). li_wb_object = cl_fp_wb_interface=>create( i_name = lv_name i_interface = li_interface ). li_wb_object->save( ). li_wb_object->free( ). CATCH cx_fp_api. zcx_abapgit_exception=>raise( 'SFPI error, deserialize' ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_name TYPE fpinterface-name. SELECT SINGLE name FROM fpinterface INTO lv_name WHERE name = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_object TYPE seqg3-garg. lv_object = |{ ms_item-obj_name }|. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EFPINTERFACE' iv_argument = lv_object ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_xstr TYPE xstring, li_document TYPE REF TO if_ixml_document. lv_xstr = interface_to_xstring( ). li_document = cl_ixml_80_20=>parse_to_document( stream_xstring = lv_xstr ). zcl_abapgit_object_sfpf=>fix_oref( li_document ). io_xml->set_raw( li_document->get_root_element( ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sfpf IMPLEMENTATION. METHOD fix_oref. * During serialization of a SFPF / SFPI object the interface hierarchy * is represented by attributes "id" and "href", where the id looks * like "o" and href like "#o". Every run of * serialization generates a new in these attributes, that * leads to differences even by comparing of untouched forms. * The purpose of this method is to renumber the id's consequentially * and therefore to avoid fictive differences. * NB: As the method iterator->get_next() works quite slowly, * it is better to collect all attributes in a cache table * instead of implementing of a nested loop using get_next(). DATA: li_iterator TYPE REF TO if_ixml_node_iterator, li_elem TYPE REF TO if_ixml_element, lv_new TYPE string, lv_old TYPE string, lv_count TYPE i, BEGIN OF ls_attr_href, val TYPE string, attr TYPE REF TO if_ixml_attribute, END OF ls_attr_href, lt_attr_href LIKE SORTED TABLE OF ls_attr_href WITH NON-UNIQUE KEY val. FIELD-SYMBOLS LIKE LINE OF lt_attr_href. * Collect all attributes href='#o...' in the cache table li_iterator = ii_document->create_iterator_filtered( ii_document->create_filter_and( filter1 = ii_document->create_filter_node_type( if_ixml_node=>co_node_element ) filter2 = ii_document->create_filter_attribute( 'href' ) ) ). li_elem ?= li_iterator->get_next( ). WHILE li_elem IS NOT INITIAL. ls_attr_href-attr = li_elem->get_attribute_node( 'href' ). ls_attr_href-val = ls_attr_href-attr->get_value( ). IF ls_attr_href-val CP '##o*'. INSERT ls_attr_href INTO TABLE lt_attr_href. ENDIF. li_elem ?= li_iterator->get_next( ). ENDWHILE. * Renumber id='o...' attributes li_iterator = ii_document->create_iterator_filtered( ii_document->create_filter_and( filter1 = ii_document->create_filter_node_type( if_ixml_node=>co_node_element ) filter2 = ii_document->create_filter_attribute( 'id' ) ) ). li_elem ?= li_iterator->get_next( ). WHILE li_elem IS NOT INITIAL. lv_old = li_elem->get_attribute( 'id' ). IF lv_old CP 'o*'. lv_count = lv_count + 1. lv_new = |o{ lv_count }|. * Rewrite id IF li_elem->set_attribute( name = 'id' value = lv_new ) IS NOT INITIAL. zcx_abapgit_exception=>raise( 'SFPF error, FIX_OREF' ). ENDIF. * Update references LOOP AT lt_attr_href ASSIGNING WHERE val = '#' && lv_old. IF -attr->set_value( '#' && lv_new ) IS NOT INITIAL. zcx_abapgit_exception=>raise( 'SFPF error, FIX_OREF' ). ENDIF. ENDLOOP. ENDIF. li_elem ?= li_iterator->get_next( ). ENDWHILE. ENDMETHOD. METHOD form_to_xstring. CONSTANTS: lc_empty_data TYPE xstring VALUE ''. DATA: li_fp_form TYPE REF TO if_fp_form, li_wb_form TYPE REF TO if_fp_wb_form, li_fp_layout TYPE REF TO if_fp_layout, lx_fp_err TYPE REF TO cx_fp_api, lx_fp_conv_err TYPE REF TO cx_fp_api, lv_layout_data TYPE xstring. li_wb_form = load( ). li_fp_form ?= li_wb_form->get_object( ). li_fp_layout = li_fp_form->get_layout( ). lv_layout_data = li_fp_layout->get_layout_data( ). mo_files->add_raw( iv_ext = c_layout_file_ext iv_data = lv_layout_data ). TRY. li_fp_layout->set_layout_data( i_layout_data = lc_empty_data i_set_xliff_ids = abap_false ). CATCH cx_fp_api INTO lx_fp_err. zcx_abapgit_exception=>raise( |SFPF remove layout: { lx_fp_err->get_text( ) }| ). ENDTRY. TRY. rv_xstr = cl_fp_helper=>convert_form_to_xstring( li_fp_form ). CATCH cx_fp_api INTO lx_fp_conv_err. " Pass - the exception is handled below! ENDTRY. TRY. li_fp_layout->set_layout_data( i_layout_data = lv_layout_data i_set_xliff_ids = abap_false ). CATCH cx_fp_api INTO lx_fp_err. " Be aware that there might be another exception " raised by cl_fp_helper=>convert_form_to_xstring( ) zcx_abapgit_exception=>raise( |SFPF recover layout: { lx_fp_err->get_text( ) }| ). ENDTRY. IF lx_fp_conv_err IS BOUND. " This statement handles the exception raised from cl_fp_helper=>convert_form_to_xstring( ) zcx_abapgit_exception=>raise( |SFPF convert_form_to_xstring: { lx_fp_conv_err->get_text( ) }| ). ENDIF. ENDMETHOD. METHOD load. DATA: lv_name TYPE fpname. lv_name = ms_item-obj_name. TRY. ri_wb_form = cl_fp_wb_form=>load( lv_name ). CATCH cx_fp_api. zcx_abapgit_exception=>raise( 'SFPF error, load' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE lastuser FROM fplayout INTO rv_user WHERE name = ms_item-obj_name AND state = 'A'. IF rv_user IS INITIAL. SELECT SINGLE firstuser FROM fplayout INTO rv_user WHERE name = ms_item-obj_name AND state = 'A'. ENDIF. IF rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_name TYPE fpname. lv_name = ms_item-obj_name. TRY. TRY. CALL METHOD cl_fp_wb_form=>('DELETE') EXPORTING i_name = lv_name i_ordernum = iv_transport i_dark = abap_true. " > 740 CATCH cx_sy_dyn_call_error. cl_fp_wb_form=>delete( i_name = lv_name i_ordernum = iv_transport ). ENDTRY. CATCH cx_fp_api. zcx_abapgit_exception=>raise( 'SFPI error, delete' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_xstr TYPE xstring, lv_layout TYPE xstring, lv_name TYPE fpname, li_wb_object TYPE REF TO if_fp_wb_form, li_form TYPE REF TO if_fp_form, lx_fp_err TYPE REF TO cx_fp_api. lv_name = ms_item-obj_name. lv_xstr = cl_ixml_80_20=>render_to_xstring( io_xml->get_raw( ) ). TRY. li_form = cl_fp_helper=>convert_xstring_to_form( lv_xstr ). IF mo_files->contains_file( c_layout_file_ext ) = abap_true. lv_layout = mo_files->read_raw( c_layout_file_ext ). li_form->get_layout( )->set_layout_data( lv_layout ). ENDIF. IF zif_abapgit_object~exists( ) = abap_true. TRY. CALL METHOD cl_fp_wb_form=>('DELETE') EXPORTING i_name = lv_name i_ordernum = iv_transport i_dark = abap_true. " > 740 CATCH cx_sy_dyn_call_error. cl_fp_wb_form=>delete( i_name = lv_name i_ordernum = iv_transport ). ENDTRY. ENDIF. tadir_insert( iv_package ). TRY. CALL METHOD cl_fp_wb_form=>('CREATE') EXPORTING i_name = lv_name i_form = li_form i_ordernum = iv_transport i_dark = abap_true " > 740 RECEIVING r_wb_form = li_wb_object. CATCH cx_sy_dyn_call_error. li_wb_object = cl_fp_wb_form=>create( i_name = lv_name i_form = li_form i_ordernum = iv_transport ). ENDTRY. li_wb_object->save( ). li_wb_object->free( ). CATCH cx_fp_api INTO lx_fp_err. zcx_abapgit_exception=>raise( |SFPF deserialization error: { lx_fp_err->get_text( ) }| ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_name TYPE fpname. SELECT SINGLE name FROM fplayout INTO lv_name WHERE name = ms_item-obj_name AND state = 'A'. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_object TYPE seqg3-garg. lv_object = |{ ms_item-obj_name }|. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EFPFORM' iv_argument = lv_object ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_xstr TYPE xstring, li_document TYPE REF TO if_ixml_document, li_node_collection TYPE REF TO if_ixml_node_collection, li_node_iter TYPE REF TO if_ixml_node_iterator, li_node TYPE REF TO if_ixml_node, li_node_new TYPE REF TO if_ixml_node, li_node_parent TYPE REF TO if_ixml_node. lv_xstr = form_to_xstring( ). li_document = cl_ixml_80_20=>parse_to_document( stream_xstring = lv_xstr ). * Clear CACHE_INFO li_node_collection = li_document->get_elements_by_tag_name_ns( 'CACHE_INFO' ). IF li_node_collection IS NOT INITIAL. li_node_iter = li_node_collection->create_iterator( ). DO. li_node = li_node_iter->get_next( ). IF li_node IS INITIAL. EXIT. ENDIF. li_node_new = li_document->create_element_ns( 'CACHE_INFO' ). li_node_parent = li_node->get_parent( ). li_node_parent->replace_child( new_child = li_node_new old_child = li_node ). ENDDO. ENDIF. fix_oref( li_document ). io_xml->set_raw( li_document->get_root_element( ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sfbs IMPLEMENTATION. METHOD activate. DATA: lt_bfsets TYPE sfw_bstab, lt_msgtab TYPE sprot_u_tab. IF zif_abapgit_object~is_active( ) = abap_true. RETURN. ENDIF. APPEND mv_bfset TO lt_bfsets. cl_sfw_activate=>activate_sfbs( EXPORTING p_bsets = lt_bfsets p_version = 'I' IMPORTING p_msgtab = lt_msgtab ). READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. IF sy-subrc = 0. zcx_abapgit_exception=>raise( 'Error activating SFBS' ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_bfset = is_item-obj_name. ENDMETHOD. METHOD create. TRY. " make sure to clear cache ro_bfs = cl_sfw_bfs=>create_bfs( mv_bfset ). ro_bfs->free( ). ro_bfs = cl_sfw_bfs=>create_bfs( mv_bfset ). CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. zcx_abapgit_exception=>raise( 'Error from CL_SFW_BFS=>CREATE_BFS' ). ENDTRY. ENDMETHOD. METHOD get. TRY. " make sure to clear cache ro_bfs = cl_sfw_bfs=>get_bfs( mv_bfset ). ro_bfs->free( ). ro_bfs = cl_sfw_bfs=>get_bfs( mv_bfset ). CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. zcx_abapgit_exception=>raise( 'Error from CL_SFW_BFS=>GET_BFS' ). ENDTRY. ENDMETHOD. METHOD unlock. CALL FUNCTION 'DEQUEUE_EEUDB' EXPORTING relid = 'SS' name = ms_item-obj_name _synchron = 'X' _scope = '1' mode_eudb = abap_true. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: ls_data TYPE sfw_bs. ls_data = get( )->get_header_data( ). rv_user = ls_data-changedby. IF rv_user IS INITIAL. rv_user = ls_data-author. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lt_delete TYPE sfw_bstab, lt_msgtab TYPE sprot_u_tab. APPEND mv_bfset TO lt_delete. cl_sfw_activate=>delete_sfbs( EXPORTING p_bsets = lt_delete IMPORTING p_msgtab = lt_msgtab ). READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. IF sy-subrc = 0. zcx_abapgit_exception=>raise( 'Error deleting SFBS' ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_bfs TYPE REF TO cl_sfw_bfs, ls_header TYPE sfw_bs, lv_name_32 TYPE sfw_name32, lv_name_80 TYPE sfw_name80, lt_assigned_bf TYPE sfw_bfbs_outtab, lt_nested_bfs TYPE sfw_bsbs_outtab, lt_parent_bfs TYPE sfw_bs_bs_parent_outtab. IF iv_step = zif_abapgit_object=>gc_step_id-late. activate( ). RETURN. ENDIF. io_xml->read( EXPORTING iv_name = 'HEADER' CHANGING cg_data = ls_header ). io_xml->read( EXPORTING iv_name = 'NAME32' CHANGING cg_data = lv_name_32 ). io_xml->read( EXPORTING iv_name = 'NAME80' CHANGING cg_data = lv_name_80 ). io_xml->read( EXPORTING iv_name = 'ASSIGNED_BF' CHANGING cg_data = lt_assigned_bf ). io_xml->read( EXPORTING iv_name = 'NESTED_BFS' CHANGING cg_data = lt_nested_bfs ). io_xml->read( EXPORTING iv_name = 'PARENT_BFS' CHANGING cg_data = lt_parent_bfs ). TRY. IF zif_abapgit_object~exists( ) = abap_true. lo_bfs = get( ). ELSE. lo_bfs = create( ). ENDIF. CATCH cx_pak_not_authorized cx_pak_invalid_state cx_pak_invalid_data. zcx_abapgit_exception=>raise( 'error in CL_SFW_BFS=>CREATE_BFS' ). ENDTRY. ls_header-author = sy-uname. ls_header-createdon = sy-datum. lo_bfs->set_header_data( ls_header ). lo_bfs->set_texts( p_32 = lv_name_32 p_80 = lv_name_80 ). lo_bfs->set_assigned_bf( lt_assigned_bf ). lo_bfs->set_assigned_bfs( lt_nested_bfs ). lo_bfs->set_nested_parent( lt_parent_bfs ). set_default_package( iv_package ). tadir_insert( iv_package ). lo_bfs->save_all( ). unlock( ). deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_sfbs ). zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA ls_tadir TYPE tadir. IF cl_sfw_bfs=>check_existence( mv_bfset ) = abap_false. RETURN. ENDIF. SELECT SINGLE * FROM tadir INTO ls_tadir WHERE pgmid = 'R3TR' AND object = ms_item-obj_type AND obj_name = ms_item-obj_name. IF ls_tadir IS INITIAL. RETURN. ENDIF. rv_bool = abap_true. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' iv_argument = ms_item-obj_name iv_prefix = 'SS' ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_bfs TYPE REF TO cl_sfw_bfs, ls_header TYPE sfw_bs, lv_name_32 TYPE sfw_name32, lv_name_80 TYPE sfw_name80, lt_assigned_bf TYPE sfw_bfbs_outtab, lt_nested_bfs TYPE sfw_bsbs_outtab, lt_parent_bfs TYPE sfw_bs_bs_parent_outtab. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. lo_bfs = get( ). ls_header = lo_bfs->get_header_data( ). CLEAR: ls_header-author, ls_header-version, ls_header-createdon, ls_header-changedby, ls_header-changedon, ls_header-timestamp. lo_bfs->get_texts( IMPORTING p_32 = lv_name_32 p_80 = lv_name_80 ). lt_assigned_bf = lo_bfs->get_assigned_bf( ). lt_nested_bfs = lo_bfs->get_nested_bfs( ). lt_parent_bfs = lo_bfs->get_nested_parent( ). io_xml->add( ig_data = ls_header iv_name = 'HEADER' ). io_xml->add( ig_data = lv_name_32 iv_name = 'NAME32' ). io_xml->add( ig_data = lv_name_80 iv_name = 'NAME80' ). io_xml->add( ig_data = lt_assigned_bf iv_name = 'ASSIGNED_BF' ). io_xml->add( ig_data = lt_nested_bfs iv_name = 'NESTED_BFS' ). io_xml->add( ig_data = lt_parent_bfs iv_name = 'PARENT_BFS' ). serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_sfbs ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sfbf IMPLEMENTATION. METHOD activate. DATA: lt_bfuncts TYPE sfw_bftab, lt_msgtab TYPE sprot_u_tab. IF zif_abapgit_object~is_active( ) = abap_true. RETURN. ENDIF. APPEND mv_bf TO lt_bfuncts. cl_sfw_activate=>activate_sfbf( EXPORTING p_bfuncts = lt_bfuncts p_version = 'I' IMPORTING p_msgtab = lt_msgtab ). READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. IF sy-subrc = 0. zcx_abapgit_exception=>raise( 'Error activating SFBF' ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_bf = is_item-obj_name. ENDMETHOD. METHOD create. TRY. " make sure to clear cache ro_bf = cl_sfw_bf=>create_bf( mv_bf ). ro_bf->free( ). ro_bf = cl_sfw_bf=>create_bf( mv_bf ). CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. zcx_abapgit_exception=>raise( 'Error from CL_SFW_BF=>CREATE_BF' ). ENDTRY. ENDMETHOD. METHOD get. TRY. " make sure to clear cache, method GET_BF_FROM_DB does not exist in 702 ro_bf = cl_sfw_bf=>get_bf( mv_bf ). ro_bf->free( ). ro_bf = cl_sfw_bf=>get_bf( mv_bf ). CATCH cx_pak_invalid_data cx_pak_invalid_state cx_pak_not_authorized. zcx_abapgit_exception=>raise( 'Error from CL_SFW_BF=>GET_BF' ). ENDTRY. ENDMETHOD. METHOD unlock. CALL FUNCTION 'DEQUEUE_EEUDB' EXPORTING relid = 'SF' name = ms_item-obj_name _synchron = 'X' _scope = '1' mode_eudb = abap_true. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: ls_data TYPE sfw_bf. ls_data = get( )->get_header_data( ). rv_user = ls_data-changedby. IF rv_user IS INITIAL. rv_user = ls_data-author. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lt_delete TYPE sfw_bftab, lt_msgtab TYPE sprot_u_tab. APPEND mv_bf TO lt_delete. cl_sfw_activate=>delete_sfbf( EXPORTING p_bfuncts = lt_delete IMPORTING p_msgtab = lt_msgtab ). READ TABLE lt_msgtab WITH KEY severity = 'E' TRANSPORTING NO FIELDS. IF sy-subrc = 0. zcx_abapgit_exception=>raise( 'Error deleting SFBF' ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_bf TYPE REF TO cl_sfw_bf, ls_header TYPE sfw_bf, lv_name_32 TYPE sfw_name32, lv_name_80 TYPE sfw_name80, lt_assigned_switches TYPE sfw_swbf_outtab, lt_dependancies TYPE sfw_depend_outtab, ls_sfw_bfc_kw TYPE sfw_bfc_kw, ls_sfw_bfc_tc TYPE sfw_bfc_tc, ls_sfw_bfc_rn TYPE sfw_bfc_rn, lt_parent_bfs TYPE sfw_bs_bf_outtab. IF iv_step = zif_abapgit_object=>gc_step_id-late. activate( ). RETURN. ENDIF. io_xml->read( EXPORTING iv_name = 'HEADER' CHANGING cg_data = ls_header ). io_xml->read( EXPORTING iv_name = 'NAME32' CHANGING cg_data = lv_name_32 ). io_xml->read( EXPORTING iv_name = 'NAME80' CHANGING cg_data = lv_name_80 ). io_xml->read( EXPORTING iv_name = 'ASSIGNED_SWITCHES' CHANGING cg_data = lt_assigned_switches ). io_xml->read( EXPORTING iv_name = 'DEPENDANCIES' CHANGING cg_data = lt_dependancies ). io_xml->read( EXPORTING iv_name = 'CONTENT_KW' CHANGING cg_data = ls_sfw_bfc_kw ). io_xml->read( EXPORTING iv_name = 'CONTENT_TC' CHANGING cg_data = ls_sfw_bfc_tc ). io_xml->read( EXPORTING iv_name = 'CONTENT_RN' CHANGING cg_data = ls_sfw_bfc_rn ). io_xml->read( EXPORTING iv_name = 'PARENT_BFS' CHANGING cg_data = lt_parent_bfs ). TRY. IF zif_abapgit_object~exists( ) = abap_true. lo_bf = get( ). ELSE. lo_bf = create( ). ENDIF. CATCH cx_pak_not_authorized cx_pak_invalid_state cx_pak_invalid_data. zcx_abapgit_exception=>raise( 'error in CL_SFW_BF=>CREATE_BF' ). ENDTRY. ls_header-author = sy-uname. ls_header-createdon = sy-datum. " Get component from package SELECT SINGLE dlvunit FROM tdevc INTO ls_header-component WHERE devclass = iv_package. lo_bf->set_header_data( ls_header ). lo_bf->set_texts( p_32 = lv_name_32 p_80 = lv_name_80 ). lo_bf->set_assigned_switches( lt_assigned_switches ). lo_bf->set_excluded_bf( lt_dependancies ). lo_bf->set_content_data( im_sfw_bfc_kw = ls_sfw_bfc_kw im_sfw_bfc_rn = ls_sfw_bfc_rn im_sfw_bfc_tc = ls_sfw_bfc_tc ). lo_bf->set_parent_bfs( lt_parent_bfs ). set_default_package( iv_package ). tadir_insert( iv_package ). lo_bf->save_all( ). unlock( ). deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_sfbf ). zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_tadir TYPE tadir, lv_bf TYPE sfw_bfunction. lv_bf = ms_item-obj_name. IF cl_sfw_bf=>check_existence( lv_bf ) = abap_false. RETURN. ENDIF. SELECT SINGLE * FROM tadir INTO ls_tadir WHERE pgmid = 'R3TR' AND object = ms_item-obj_type AND obj_name = ms_item-obj_name. IF ls_tadir IS INITIAL. RETURN. ENDIF. rv_bool = abap_true. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' iv_argument = ms_item-obj_name iv_prefix = 'SF' ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_bf TYPE REF TO cl_sfw_bf, ls_header TYPE sfw_bf, lv_name_32 TYPE sfw_name32, lv_name_80 TYPE sfw_name80, lt_assigned_switches TYPE sfw_swbf_outtab, lt_dependancies TYPE sfw_depend_outtab, ls_sfw_bfc_kw TYPE sfw_bfc_kw, ls_sfw_bfc_tc TYPE sfw_bfc_tc, ls_sfw_bfc_rn TYPE sfw_bfc_rn, lt_parent_bfs TYPE sfw_bs_bf_outtab. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. lo_bf = get( ). ls_header = lo_bf->get_header_data( ). CLEAR: ls_header-author, ls_header-version, ls_header-component, ls_header-createdon, ls_header-changedby, ls_header-changedon, ls_header-timestamp. lo_bf->get_texts( IMPORTING p_32 = lv_name_32 p_80 = lv_name_80 ). lt_assigned_switches = lo_bf->get_assigned_switches( ). lt_dependancies = lo_bf->get_excluded_bf( ). lo_bf->get_content_data( IMPORTING ex_sfw_bfc_kw = ls_sfw_bfc_kw ex_sfw_bfc_tc = ls_sfw_bfc_tc ex_sfw_bfc_rn = ls_sfw_bfc_rn ). lt_parent_bfs = lo_bf->get_parent_bfs( ). io_xml->add( ig_data = ls_header iv_name = 'HEADER' ). io_xml->add( ig_data = lv_name_32 iv_name = 'NAME32' ). io_xml->add( ig_data = lv_name_80 iv_name = 'NAME80' ). io_xml->add( ig_data = lt_assigned_switches iv_name = 'ASSIGNED_SWITCHES' ). io_xml->add( ig_data = lt_dependancies iv_name = 'DEPENDANCIES' ). io_xml->add( ig_data = ls_sfw_bfc_kw iv_name = 'CONTENT_KW' ). io_xml->add( ig_data = ls_sfw_bfc_tc iv_name = 'CONTENT_TC' ). io_xml->add( ig_data = ls_sfw_bfc_rn iv_name = 'CONTENT_RN' ). io_xml->add( ig_data = lt_parent_bfs iv_name = 'PARENT_BFS' ). serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_sfbf ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_scvi IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lv_screen_variant TYPE scvariant. lv_screen_variant = ms_item-obj_name. SELECT SINGLE chuser FROM shdsvci INTO rv_user WHERE scvariant = lv_screen_variant. IF sy-subrc <> 0 OR rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_screen_variant TYPE scvariant. lv_screen_variant = ms_item-obj_name. CALL FUNCTION 'RS_HDSYS_DELETE_SC_VARIANT' EXPORTING scvariant = lv_screen_variant EXCEPTIONS variant_enqueued = 1 no_correction = 2 scvariant_used = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_screen_variant TYPE ty_screen_variant. io_xml->read( EXPORTING iv_name = 'SCVI' CHANGING cg_data = ls_screen_variant ). CALL FUNCTION 'ENQUEUE_ESSCVARCIU' EXPORTING scvariant = ls_screen_variant-shdsvci-scvariant EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. MESSAGE e413(ms) WITH ls_screen_variant-shdsvci-scvariant INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. corr_insert( iv_package ). * Populate user details ls_screen_variant-shdsvci-crdate = sy-datum. ls_screen_variant-shdsvci-cruser = sy-uname. ls_screen_variant-shdsvci-chdate = sy-datum. ls_screen_variant-shdsvci-chuser = sy-uname. MODIFY shdsvci FROM ls_screen_variant-shdsvci. MODIFY shdsvtxci FROM TABLE ls_screen_variant-shdsvtxci[]. MODIFY shdsvfvci FROM TABLE ls_screen_variant-shdsvfvci[]. MODIFY shdguixt FROM TABLE ls_screen_variant-shdguixt[]. MODIFY shdgxtcode FROM TABLE ls_screen_variant-shdgxtcode[]. CALL FUNCTION 'DEQUEUE_ESSCVARCIU' EXPORTING scvariant = ls_screen_variant-shdsvci-scvariant. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_screen_variant TYPE scvariant. lv_screen_variant = ms_item-obj_name. CALL FUNCTION 'RS_HDSYS_READ_SC_VARIANT_DB' EXPORTING scvariant = lv_screen_variant EXCEPTIONS no_variant = 1 OTHERS = 2. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_screen_variant TYPE ty_screen_variant. ls_screen_variant-shdsvci-scvariant = ms_item-obj_name. CALL FUNCTION 'RS_HDSYS_READ_SC_VARIANT_DB' EXPORTING scvariant = ls_screen_variant-shdsvci-scvariant IMPORTING header_scvariant = ls_screen_variant-shdsvci TABLES values_scvariant = ls_screen_variant-shdsvfvci[] guixt_scripts = ls_screen_variant-shdguixt[] EXCEPTIONS no_variant = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. * Clear all user details CLEAR: ls_screen_variant-shdsvci-crdate, ls_screen_variant-shdsvci-cruser, ls_screen_variant-shdsvci-chdate, ls_screen_variant-shdsvci-chuser. SELECT * FROM shdsvtxci INTO TABLE ls_screen_variant-shdsvtxci[] WHERE scvariant = ls_screen_variant-shdsvci-scvariant ORDER BY PRIMARY KEY. SELECT * FROM shdgxtcode INTO TABLE ls_screen_variant-shdgxtcode[] WHERE scvariant = ls_screen_variant-shdsvci-scvariant ORDER BY PRIMARY KEY. io_xml->add( iv_name = 'SCVI' ig_data = ls_screen_variant ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_scp1 IMPLEMENTATION. METHOD adjust_inbound. FIELD-SYMBOLS: TYPE scprvals, TYPE scprreca, TYPE scprvall. * back to internal format LOOP AT cs_scp1-scprvals ASSIGNING . SHIFT -recnumber RIGHT DELETING TRAILING space. ENDLOOP. LOOP AT cs_scp1-scprreca ASSIGNING . SHIFT -recnumber RIGHT DELETING TRAILING space. ENDLOOP. LOOP AT cs_scp1-scprvall ASSIGNING . SHIFT -recnumber RIGHT DELETING TRAILING space. ENDLOOP. ENDMETHOD. METHOD adjust_outbound. FIELD-SYMBOLS: TYPE scprvals, TYPE scprreca, TYPE scprvall. * normalize the XML LOOP AT cs_scp1-scprvals ASSIGNING . CONDENSE -recnumber. ENDLOOP. LOOP AT cs_scp1-scprreca ASSIGNING . CONDENSE -recnumber. ENDLOOP. LOOP AT cs_scp1-scprvall ASSIGNING . CONDENSE -recnumber. ENDLOOP. ENDMETHOD. METHOD call_delete_fms. CONSTANTS: lc_version_new TYPE c VALUE 'N', "Include SCPRINTCONST version_new lc_operation_delete TYPE c VALUE 'D'. DATA: lv_profile_type TYPE scprattr-type, lt_fatherprofiles TYPE STANDARD TABLE OF scproprof WITH DEFAULT KEY, ls_fatherprofile TYPE scproprof. CALL FUNCTION 'SCPR_DB_ATTR_GET_DETAIL' EXPORTING profid = iv_profile_id version = lc_version_new IMPORTING proftype = lv_profile_type EXCEPTIONS OTHERS = 0. CALL FUNCTION 'SCPR_PRSET_DB_USED_IN' EXPORTING profid = iv_profile_id version = lc_version_new TABLES profiles = lt_fatherprofiles. ls_fatherprofile-id = iv_profile_id. APPEND ls_fatherprofile TO lt_fatherprofiles. CALL FUNCTION 'SCPR_CT_TRANSPORT_ENTRIES' TABLES profids = lt_fatherprofiles EXCEPTIONS error_in_transport_layer = 1 user_abort = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error while deleting SCP1 - TRANSPORT, { sy-subrc }| ). ENDIF. CALL FUNCTION 'SCPR_PRSET_DB_DELETE_ALL' EXPORTING profid = iv_profile_id proftype = lv_profile_type TABLES fatherprofs = lt_fatherprofiles EXCEPTIONS user_abort = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error while deleting SCP1 - DB_DELETE, { sy-subrc }| ). ENDIF. CALL FUNCTION 'SCPR_MEM_SCPR_ACTIONS_ADD' EXPORTING bcset_id = iv_profile_id operation = lc_operation_delete. ENDMETHOD. METHOD dequeue. DATA: lv_id TYPE scpr_id. lv_id = ms_item-obj_name. CALL FUNCTION 'SCPR_SV_DEQUEUE_BCSET' EXPORTING bcset_id = lv_id. ENDMETHOD. METHOD enqueue. DATA: lv_id TYPE scpr_id. lv_id = ms_item-obj_name. CALL FUNCTION 'SCPR_SV_ENQUEUE_BCSET' EXPORTING bcset_id = lv_id EXCEPTIONS is_already_locked = 1 system_failure = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD load. CALL FUNCTION 'SCPR_TEMPL_DB_VALS_GET_DETAIL' EXPORTING profid = cs_scp1-scprattr-id category = cs_scp1-scprattr-category TABLES values = cs_scp1-scprvals valuesl = cs_scp1-scprvall recattr = cs_scp1-scprreca. CALL FUNCTION 'SCPR_TEMPL_DB_FLDTXTVAR_GET' EXPORTING bcset_id = cs_scp1-scprattr-id category = cs_scp1-scprattr-category TABLES it_fldv = cs_scp1-scprfldv. ENDMETHOD. METHOD load_hier. CALL FUNCTION 'SCPR_PRSET_DB_SUBP_GET_DETAIL' EXPORTING profid = cs_scp1-scprattr-id category = cs_scp1-scprattr-category TABLES subprofs = cs_scp1-subprofs. ENDMETHOD. METHOD save. DATA: ls_scp1 TYPE ty_scp1, ls_text TYPE scprtext. * copy everything to local, the function module changes the values ls_scp1 = is_scp1. READ TABLE ls_scp1-scprtext INTO ls_text WITH KEY langu = mv_language. "#EC CI_SUBRC CALL FUNCTION 'SCPR_TEMPL_MN_TEMPLATE_SAVE' EXPORTING profid = ls_scp1-scprattr-id proftext = ls_text-text category = ls_scp1-scprattr-category cli_dep = ls_scp1-scprattr-cli_dep cli_cas = ls_scp1-scprattr-cli_cas reftype = ls_scp1-scprattr-reftype refname = ls_scp1-scprattr-refname orgid = ls_scp1-scprattr-orgid component = ls_scp1-scprattr-component minrelease = ls_scp1-scprattr-minrelease maxrelease = ls_scp1-scprattr-maxrelease act_info = ls_scp1-scprattr-act_info bcset_type = ls_scp1-scprattr-type fldtxtvar_supplied = 'YES' with_transp_insert = abap_false with_progress_indicator = abap_false remove_denied_data = abap_true ask_for_cont_after_remove = abap_true TABLES values = ls_scp1-scprvals valuesl = ls_scp1-scprvall recattr = ls_scp1-scprreca it_fldv = ls_scp1-scprfldv texts = ls_scp1-scprtext EXCEPTIONS user_abort = 1 error_in_transport_layer = 2 inconsistent_data = 3 database_error = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD save_hier. DATA: ls_scp1 TYPE ty_scp1, ls_profs LIKE LINE OF ls_scp1-subprofs, lt_sub TYPE STANDARD TABLE OF scproprof WITH DEFAULT KEY, ls_sub LIKE LINE OF lt_sub, ls_text TYPE scprtext. * copy everything to local, the function module changes the values ls_scp1 = is_scp1. READ TABLE ls_scp1-scprtext INTO ls_text WITH KEY langu = mv_language. "#EC CI_SUBRC * see fm SCPR_PRSET_DB_STORE, only this field and sequence is used LOOP AT ls_scp1-subprofs INTO ls_profs. ls_sub-id = ls_profs-subprofile. APPEND ls_sub TO lt_sub. ENDLOOP. CALL FUNCTION 'SCPR_PRSET_MN_BCSET_SAVE' EXPORTING profid = ls_scp1-scprattr-id proftext = ls_text-text category = ls_scp1-scprattr-category cli_dep = ls_scp1-scprattr-cli_dep cli_cas = ls_scp1-scprattr-cli_cas reftype = ls_scp1-scprattr-reftype refname = ls_scp1-scprattr-refname orgid = ls_scp1-scprattr-orgid component = ls_scp1-scprattr-component minrelease = ls_scp1-scprattr-minrelease maxrelease = ls_scp1-scprattr-maxrelease act_info = ls_scp1-scprattr-act_info with_transp_insert = abap_false with_progress_indicator = abap_false TABLES subprofs = lt_sub texts = ls_scp1-scprtext EXCEPTIONS user_abort = 1 error_in_transport_layer = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE modifier INTO rv_user FROM scprattr WHERE id = ms_item-obj_name AND version = 'N'. IF sy-subrc <> 0 OR rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_profile_id TYPE scpr_id. lv_profile_id = ms_item-obj_name. enqueue( ). call_delete_fms( lv_profile_id ). dequeue( ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_scp1 TYPE ty_scp1. io_xml->read( EXPORTING iv_name = 'SCP1' CHANGING cg_data = ls_scp1 ). adjust_inbound( CHANGING cs_scp1 = ls_scp1 ). IF ls_scp1-scprattr-type = 'TMP'. save_hier( ls_scp1 ). ELSE. save( ls_scp1 ). ENDIF. dequeue( ). tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_rc TYPE sy-subrc, lv_profid TYPE scprattr-id. lv_profid = ms_item-obj_name. CALL FUNCTION 'SCPR_BCSET_EXISTS' EXPORTING profid = lv_profid IMPORTING rc = lv_rc. rv_bool = boolc( lv_rc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lv_display_only TYPE scpr_txt20, lv_bcset_id TYPE scpr_id. lv_display_only = abap_false. lv_bcset_id = ms_item-obj_name. EXPORT scpr3_display_only = lv_display_only scpr3_bcset_id = lv_bcset_id TO MEMORY ID 'SCPR3_PARAMETER'. SUBMIT scpr3 AND RETURN. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_scp1 TYPE ty_scp1. ls_scp1-scprattr-id = ms_item-obj_name. CALL FUNCTION 'SCPR_DB_ATTR_GET_DETAIL' EXPORTING profid = ls_scp1-scprattr-id IMPORTING proftype = ls_scp1-scprattr-type cli_dep = ls_scp1-scprattr-cli_dep cli_cas = ls_scp1-scprattr-cli_cas reftype = ls_scp1-scprattr-reftype refname = ls_scp1-scprattr-refname component = ls_scp1-scprattr-component minrelease = ls_scp1-scprattr-minrelease maxrelease = ls_scp1-scprattr-maxrelease orgid = ls_scp1-scprattr-orgid act_info = ls_scp1-scprattr-act_info. CALL FUNCTION 'SCPR_TEXT_GET' EXPORTING profid = ls_scp1-scprattr-id category = ls_scp1-scprattr-category TABLES texts = ls_scp1-scprtext EXCEPTIONS no_text_found = 1. IF ls_scp1-scprattr-type = 'TMP'. load_hier( CHANGING cs_scp1 = ls_scp1 ). ELSE. load( CHANGING cs_scp1 = ls_scp1 ). ENDIF. adjust_outbound( CHANGING cs_scp1 = ls_scp1 ). io_xml->add( iv_name = 'SCP1' ig_data = ls_scp1 ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_saxx_super IMPLEMENTATION. METHOD create_channel_objects. get_names( ). TRY. IF mi_appl_obj_data IS NOT BOUND. CREATE OBJECT mi_appl_obj_data TYPE (mv_appl_obj_cls_name). ENDIF. IF mi_persistence IS NOT BOUND. CREATE OBJECT mi_persistence TYPE (mv_persistence_cls_name). ENDIF. CATCH cx_root. zcx_abapgit_exception=>raise( |{ ms_item-obj_type } not supported| ). ENDTRY. ENDMETHOD. METHOD get_data. DATA: lv_object_key TYPE seu_objkey. lv_object_key = ms_item-obj_name. TRY. mi_persistence->get( EXPORTING p_object_key = lv_object_key p_version = 'A' CHANGING p_object_data = mi_appl_obj_data ). CATCH cx_root. zcx_abapgit_exception=>raise( |{ ms_item-obj_type } not supported| ). ENDTRY. mi_appl_obj_data->get_data( IMPORTING p_data = eg_data ). ENDMETHOD. METHOD get_names. IF mv_data_structure_name IS INITIAL. mv_data_structure_name = get_data_structure_name( ). ENDIF. IF mv_appl_obj_cls_name IS INITIAL. mv_appl_obj_cls_name = get_data_class_name( ). ENDIF. IF mv_persistence_cls_name IS INITIAL. mv_persistence_cls_name = get_persistence_class_name( ). ENDIF. ENDMETHOD. METHOD lock. DATA: lv_objname TYPE trobj_name, lv_object_key TYPE seu_objkey, lv_objtype TYPE trobjtype. lv_objname = ms_item-obj_name. lv_object_key = ms_item-obj_name. lv_objtype = ms_item-obj_type. mi_persistence->lock( EXPORTING p_objname_tr = lv_objname p_object_key = lv_object_key p_objtype_tr = lv_objtype EXCEPTIONS foreign_lock = 1 error_occurred = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error occurred while locking { ms_item-obj_type } { lv_objname }| ). ENDIF. ENDMETHOD. METHOD unlock. DATA: lv_objname TYPE trobj_name, lv_object_key TYPE seu_objkey, lv_objtype TYPE trobjtype. lv_objname = ms_item-obj_name. lv_object_key = ms_item-obj_name. lv_objtype = ms_item-obj_type. mi_persistence->unlock( p_objname_tr = lv_objname p_object_key = lv_object_key p_objtype_tr = lv_objtype ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lr_data TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any. create_channel_objects( ). TRY. CREATE DATA lr_data TYPE (mv_data_structure_name). ASSIGN lr_data->* TO . CATCH cx_root. zcx_abapgit_exception=>raise( |{ ms_item-obj_name } not supported| ). ENDTRY. get_data( IMPORTING eg_data = ). ASSIGN COMPONENT 'HEADER' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. IF IS NOT INITIAL. rv_user = . ELSE. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_object_key TYPE seu_objkey. create_channel_objects( ). lv_object_key = ms_item-obj_name. TRY. lock( ). mi_persistence->delete( lv_object_key ). unlock( ). CATCH cx_swb_exception. zcx_abapgit_exception=>raise( |Error occurred while deleting { ms_item-obj_type }| ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lr_data TYPE REF TO data. FIELD-SYMBOLS: TYPE any. create_channel_objects( ). TRY. CREATE DATA lr_data TYPE (mv_data_structure_name). ASSIGN lr_data->* TO . CATCH cx_root. zcx_abapgit_exception=>raise( |{ ms_item-obj_type } not supported| ). ENDTRY. io_xml->read( EXPORTING iv_name = ms_item-obj_type CHANGING cg_data = ). IF zif_abapgit_object~exists( ) = abap_true. zif_abapgit_object~delete( iv_package = iv_package iv_transport = iv_transport ). ENDIF. TRY. lock( ). corr_insert( iv_package ). mi_appl_obj_data->set_data( ). mi_persistence->save( mi_appl_obj_data ). unlock( ). CATCH cx_swb_exception. zcx_abapgit_exception=>raise( |Error occurred while creating { ms_item-obj_type }| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_object_key TYPE seu_objkey. create_channel_objects( ). lv_object_key = ms_item-obj_name. TRY. mi_persistence->get( p_object_key = lv_object_key p_version = 'A' p_existence_check_only = abap_true ). CATCH cx_swb_object_does_not_exist cx_swb_exception. rv_bool = abap_false. RETURN. ENDTRY. rv_bool = abap_true. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lr_data TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any. create_channel_objects( ). TRY. CREATE DATA lr_data TYPE (mv_data_structure_name). ASSIGN lr_data->* TO . CATCH cx_root. zcx_abapgit_exception=>raise( |{ ms_item-obj_type } not supported| ). ENDTRY. get_data( IMPORTING eg_data = ). ASSIGN COMPONENT 'HEADER' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'CHANGED_ON' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'CHANGED_AT' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'CHANGED_CLNT' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'CREATED_ON' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'CREATED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'CREATED_AT' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'CREATED_CLNT' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . io_xml->add( iv_name = ms_item-obj_type ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_sapc IMPLEMENTATION. METHOD get_data_class_name. rv_data_class_name = 'CL_APC_APPLICATION_OBJ_DATA'. ENDMETHOD. METHOD get_data_structure_name. rv_data_structure_name = 'APC_APPLICATION_COMPLETE'. ENDMETHOD. METHOD get_persistence_class_name. rv_persistence_class_name = 'CL_APC_APPLICATION_OBJ_PERS'. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_samc IMPLEMENTATION. METHOD get_data_class_name. rv_data_class_name = 'CL_AMC_APPLICATION_OBJ_DATA'. ENDMETHOD. METHOD get_data_structure_name. rv_data_structure_name = 'AMC_APPLICATION_COMPLETE'. ENDMETHOD. METHOD get_persistence_class_name. rv_persistence_class_name = 'CL_AMC_APPLICATION_OBJ_PERS'. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_prog IMPLEMENTATION. METHOD deserialize_texts. DATA: lt_tpool_i18n TYPE ty_tpools_i18n, lt_tpool TYPE textpool_table. FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. ii_xml->read( EXPORTING iv_name = 'I18N_TPOOL' CHANGING cg_data = lt_tpool_i18n ). LOOP AT lt_tpool_i18n ASSIGNING . lt_tpool = read_tpool( -textpool ). deserialize_textpool( iv_program = ms_item-obj_name iv_language = -language it_tpool = lt_tpool ). ENDLOOP. ENDMETHOD. METHOD deserialize_with_ext. " Special treatment for extensions " If the program name exceeds 30 characters it is not a usual ABAP program but might be " some extension, which requires the internal addition EXTENSION TYPE " https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.htm?file=abapinsert_report_internal.htm " This e.g. occurs in case of transportable Code Inspector variants (ending with ===VC) zcl_abapgit_factory=>get_sap_report( )->insert_report( iv_name = is_progdir-name iv_package = iv_package it_source = it_source iv_state = 'I' iv_version = is_progdir-uccheck iv_program_type = is_progdir-subc iv_extension_type = is_progdir-name+30 ). zcl_abapgit_factory=>get_sap_report( )->update_progdir( is_progdir = is_progdir iv_state = 'I' iv_package = iv_package ). zcl_abapgit_objects_activation=>add( iv_type = 'REPS' iv_name = is_progdir-name ). ENDMETHOD. METHOD is_program_locked. rv_is_program_locked = exists_a_lock_entry_for( iv_lock_object = 'ESRDIRE' iv_argument = |{ ms_item-obj_name }| ). ENDMETHOD. METHOD serialize_texts. DATA: lt_tpool_i18n TYPE ty_tpools_i18n, lt_tpool TYPE textpool_table, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. " Table d010tinf stores info. on languages in which program is maintained " Select all active translations of program texts " Skip main language - it was already serialized lt_language_filter = mo_i18n_params->build_language_filter( ). SELECT DISTINCT language INTO CORRESPONDING FIELDS OF TABLE lt_tpool_i18n FROM d010tinf WHERE r3state = 'A' AND prog = ms_item-obj_name AND language <> mv_language AND language IN lt_language_filter ORDER BY language ##TOO_MANY_ITAB_FIELDS. SORT lt_tpool_i18n BY language ASCENDING. LOOP AT lt_tpool_i18n ASSIGNING . READ TEXTPOOL ms_item-obj_name LANGUAGE -language INTO lt_tpool. -textpool = add_tpool( lt_tpool ). ENDLOOP. IF lines( lt_tpool_i18n ) > 0. ii_xml->add( iv_name = 'I18N_TPOOL' ig_data = lt_tpool_i18n ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE unam FROM reposrc INTO rv_user WHERE progname = ms_item-obj_name AND r3state = 'A'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_program LIKE sy-repid, lv_obj_name TYPE e071-obj_name. lv_program = ms_item-obj_name. CALL FUNCTION 'RS_DELETE_PROGRAM' EXPORTING corrnumber = iv_transport program = lv_program suppress_popup = abap_true mass_delete_call = abap_true tadir_devclass = iv_package force_delete_used_includes = abap_true EXCEPTIONS enqueue_lock = 1 object_not_found = 2 permission_failure = 3 reject_deletion = 4 OTHERS = 5. IF sy-subrc = 2. " Drop also any inactive code that is left in REPOSRC zcl_abapgit_factory=>get_sap_report( )->delete_report( lv_program ). " Remove inactive objects from work area lv_obj_name = lv_program. CALL FUNCTION 'RS_DELETE_FROM_WORKING_AREA' EXPORTING object = 'REPS' obj_name = lv_obj_name immediate = 'X' actualize_working_area = 'X'. CALL FUNCTION 'RS_DELETE_FROM_WORKING_AREA' EXPORTING object = 'REPT' obj_name = lv_obj_name immediate = 'X' actualize_working_area = 'X'. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. delete_longtexts( c_longtext_id_prog ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_program_name TYPE syrepid, ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, lt_tpool TYPE textpool_table, lt_dynpros TYPE ty_dynpro_tt, lt_tpool_ext TYPE zif_abapgit_definitions=>ty_tpool_tt, ls_cua TYPE ty_cua, lt_source TYPE abaptxt255_tab. " Add R3TR PROG to transport first, otherwise we get several LIMUs corr_insert( iv_package ). lv_program_name = ms_item-obj_name. lt_source = mo_files->read_abap( ). io_xml->read( EXPORTING iv_name = 'TPOOL' CHANGING cg_data = lt_tpool_ext ). lt_tpool = read_tpool( lt_tpool_ext ). io_xml->read( EXPORTING iv_name = 'PROGDIR' CHANGING cg_data = ls_progdir ). set_abap_language_version( CHANGING cv_abap_language_version = ls_progdir-uccheck ). IF strlen( lv_program_name ) > 30. " Objects with extension for example transportable Code Inspector variants (ending with ===VC) deserialize_with_ext( is_progdir = ls_progdir iv_package = iv_package it_source = lt_source ). ELSE. deserialize_program( is_progdir = ls_progdir it_source = lt_source it_tpool = lt_tpool iv_package = iv_package ). io_xml->read( EXPORTING iv_name = 'DYNPROS' CHANGING cg_data = lt_dynpros ). deserialize_dynpros( lt_dynpros ). io_xml->read( EXPORTING iv_name = 'CUA' CHANGING cg_data = ls_cua ). deserialize_cua( iv_program_name = lv_program_name is_cua = ls_cua ). " Texts deserializing (English) deserialize_textpool( iv_program = lv_program_name it_tpool = lt_tpool ). " Texts deserializing (translations) IF mo_i18n_params->is_lxe_applicable( ) = abap_false. deserialize_texts( io_xml ). ENDIF. deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_prog ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_progname TYPE reposrc-progname. SELECT SINGLE progname FROM reposrc INTO lv_progname WHERE progname = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. IF is_program_locked( ) = abap_true OR is_any_dynpro_locked( ms_item-obj_name ) = abap_true OR is_cua_locked( ms_item-obj_name ) = abap_true OR is_text_locked( ms_item-obj_name ) = abap_true. rv_is_locked = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. * see SAP note 1025291, run report DELETE_TADIR_FOR_EIMP_INCLUDE to clean bad TADIR entries ASSERT NOT ms_item-obj_name CP '*=E'. serialize_program( io_xml = io_xml is_item = ms_item io_files = mo_files ). " Texts serializing (translations) IF mo_i18n_params->is_lxe_applicable( ) = abap_false. serialize_texts( io_xml ). ENDIF. serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_prog ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_prag IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " not stored by SAP ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_pragma TYPE REF TO cl_abap_pragma, lx_error TYPE REF TO cx_root. TRY. lo_pragma = cl_abap_pragma=>get_ref( ms_item-obj_name ). lo_pragma->delete( ). lo_pragma->leave_change( ). "unlock CATCH cx_root INTO lx_error. IF lo_pragma IS BOUND. lo_pragma->leave_change( ). ENDIF. zcx_abapgit_exception=>raise( lx_error->get_text( ) ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_pragma TYPE ty_pragma, lo_pragma TYPE REF TO cl_abap_pragma, lx_error TYPE REF TO cx_root. tadir_insert( iv_package ). TRY. io_xml->read( EXPORTING iv_name = 'PRAG' CHANGING cg_data = ls_pragma ). lo_pragma = cl_abap_pragma=>create( p_pragma = ms_item-obj_name p_package = iv_package ). lo_pragma->set_info( p_description = ls_pragma-description p_signature = ls_pragma-signature p_extension = ls_pragma-extension ). lo_pragma->save( ). lo_pragma->leave_change( ). "unlock CATCH cx_root INTO lx_error. IF lo_pragma IS BOUND. lo_pragma->leave_change( ). ENDIF. zcx_abapgit_exception=>raise( lx_error->get_text( ) ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. cl_abap_pragma=>get_ref( ms_item-obj_name ). CATCH cx_abap_pragma_not_exists. rv_bool = abap_false. RETURN. ENDTRY. rv_bool = abap_true. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_pragma TYPE REF TO cl_abap_pragma, ls_pragma TYPE ty_pragma. TRY. lo_pragma = cl_abap_pragma=>get_ref( ms_item-obj_name ). ls_pragma-pragma = lo_pragma->pragma. ls_pragma-extension = lo_pragma->extension. ls_pragma-signature = lo_pragma->signature. ls_pragma-description = lo_pragma->description. io_xml->add( iv_name = 'PRAG' ig_data = ls_pragma ). CATCH cx_abap_pragma_not_exists. zcx_abapgit_exception=>raise( |Pragma { ms_item-obj_name } doesn't exist| ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS kHGwlqJyKbsVHldwKaGddDbbHeNaet IMPLEMENTATION. METHOD constructor. mi_interface = ii_interface. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~get_elements. mi_interface->get_elements( IMPORTING e_elements = rt_elements EXCEPTIONS object_invalid = 1 intern_err = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~set_elements_changeable. mi_interface->set_elements_changeable( EXPORTING i_changeable = iv_changeable EXCEPTIONS object_already_changeable = 1 object_already_unlocked = 2 object_locked_by_other_user = 3 object_modified = 4 object_just_created = 5 object_deleted = 6 permission_failure = 7 object_invalid = 8 unexpected_error = 9 OTHERS = 10 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~save_elements. mi_interface->save_elements( EXCEPTIONS object_not_changeable = 1 object_invalid = 2 cancelled_in_corr = 3 permission_failure = 4 unexpected_error = 5 intern_err = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~get_all_attributes. mi_interface->get_all_attributes( IMPORTING e_package_interface_data = rs_package_interface_data EXCEPTIONS object_invalid = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~set_changeable. mi_interface->set_changeable( EXPORTING i_changeable = iv_changeable EXCEPTIONS object_locked_by_other_user = 1 permission_failure = 2 object_already_changeable = 3 object_already_unlocked = 4 object_just_created = 5 object_deleted = 6 object_modified = 7 object_not_existing = 8 object_invalid = 9 unexpected_error = 10 OTHERS = 11 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~delete. mi_interface->delete( EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 intern_err = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~save. mi_interface->save( EXCEPTIONS short_text_missing = 1 object_not_changeable = 2 object_invalid = 3 cancelled_in_corr = 4 permission_failure = 5 unexpected_error = 6 intern_err = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~remove_elements. mi_interface->remove_elements( EXPORTING i_elements = it_elements EXCEPTIONS object_deleted = 1 object_invalid = 2 object_not_changeable = 3 element_not_contained = 4 intern_err = 5 OTHERS = 6 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~add_elements. DATA: lt_mismatched TYPE scomeldata, ls_mismatched LIKE LINE OF lt_mismatched. mi_interface->add_elements( EXPORTING i_elements_data = it_elements_data IMPORTING e_mismatched_elem_data = lt_mismatched EXCEPTIONS object_invalid = 1 intern_err = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. LOOP AT lt_mismatched INTO ls_mismatched. zcx_abapgit_exception=>raise( |Object { ls_mismatched-elem_type } { ls_mismatched-elem_key } | && |from different package { ls_mismatched-elem_pack }| ). ENDLOOP. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~set_all_attributes. mi_interface->set_all_attributes( EXPORTING i_package_interface_data = is_package_interface_data i_data_sign = is_data_sign EXCEPTIONS object_deleted = 1 object_not_changeable = 2 interface_not_empty = 3 acl_not_empty = 4 author_not_existing = 5 object_type_mismatch = 6 object_invalid = 7 OTHERS = 8 ). * Downport: exception "logical_package_types_differ" * does not exist in lower versions IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD iUFTsqJyKbsVHldwKaGdXoRoiJNIwT~get_changeable. mi_interface->get_changeable( IMPORTING e_changeable = rv_changeable EXCEPTIONS object_invalid = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_pinf IMPLEMENTATION. METHOD create_facade. CREATE OBJECT ri_facade TYPE kHGwlqJyKbsVHldwKaGddDbbHeNaet EXPORTING ii_interface = ii_interface. ENDMETHOD. METHOD create_or_load. DATA: li_interface TYPE REF TO if_package_interface, lv_pkg_interface_data TYPE scompidtln. lv_pkg_interface_data-default_if = is_pinf-attributes-default_if. lv_pkg_interface_data-tadir_devc = iv_package. "Important if the package name comes from another package IF is_pinf-attributes-pack_name IS INITIAL. lv_pkg_interface_data-pack_name = iv_package. ELSE. lv_pkg_interface_data-pack_name = is_pinf-attributes-pack_name. ENDIF. IF zif_abapgit_object~exists( ) = abap_false. cl_package_interface=>create_new_package_interface( EXPORTING i_pkg_interface_name = is_pinf-attributes-intf_name i_publisher_pkg_name = lv_pkg_interface_data-pack_name i_pkg_interface_data = lv_pkg_interface_data IMPORTING e_package_interface = li_interface EXCEPTIONS object_already_existing = 1 object_just_created = 2 interface_name_invalid = 3 unexpected_error = 4 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error creating new package interface' ). ENDIF. ri_interface = create_facade( li_interface ). ELSE. ri_interface = load( is_pinf-attributes-intf_name ). ENDIF. ENDMETHOD. METHOD delete_elements. DATA: lt_elements TYPE ty_elements. FIELD-SYMBOLS: LIKE LINE OF lt_elements. ii_interface->set_elements_changeable( abap_true ). lt_elements = ii_interface->get_elements( ). LOOP AT lt_elements ASSIGNING . ->delete( ). ENDLOOP. ii_interface->save_elements( ). ENDMETHOD. METHOD load. DATA: li_interface TYPE REF TO if_package_interface. cl_package_interface=>load_package_interface( EXPORTING i_package_interface_name = iv_name i_force_reload = abap_true IMPORTING e_package_interface = li_interface ). ri_interface = create_facade( li_interface ). ENDMETHOD. METHOD update_attributes. DATA: ls_sign TYPE scompisign, lv_changeable TYPE abap_bool. lv_changeable = ii_interface->get_changeable( ). IF lv_changeable = abap_false. * at creation the object is already in change mode ii_interface->set_changeable( abap_true ). ENDIF. ls_sign-descript = abap_true. ls_sign-pinftype = abap_true. ls_sign-restricted = abap_true. ls_sign-default_if = abap_true. ls_sign-def_sever = abap_true. ls_sign-acl_flag = abap_true. ls_sign-pifstablty = abap_true. ls_sign-release_status = abap_true. ii_interface->set_all_attributes( is_package_interface_data = is_pinf-attributes is_data_sign = ls_sign ). set_default_package( iv_package ). * looks like setting "i_suppress_dialog = abap_true" will make * it fail for local($) packages ii_interface->save( ). ii_interface->set_changeable( abap_false ). ENDMETHOD. METHOD update_elements. DATA: lt_existing TYPE ty_elements, ls_element LIKE LINE OF is_pinf-elements, lt_add TYPE scomeldata, lv_index TYPE i, lv_found TYPE abap_bool, ls_attr TYPE scomeldtln. FIELD-SYMBOLS LIKE LINE OF lt_existing. ii_interface->set_elements_changeable( abap_true ). lt_existing = ii_interface->get_elements( ). LOOP AT is_pinf-elements INTO ls_element. lv_found = abap_false. LOOP AT lt_existing ASSIGNING . lv_index = sy-tabix. ->get_all_attributes( IMPORTING e_element_data = ls_attr ). IF ls_element-elem_type = ls_attr-elem_type AND ls_element-elem_key = ls_attr-elem_key. DELETE lt_existing INDEX lv_index. CONTINUE. " current loop ENDIF. ENDLOOP. IF lv_found = abap_false. ls_element-elem_pack = iv_package. APPEND ls_element TO lt_add. ENDIF. ENDLOOP. ii_interface->remove_elements( lt_existing ). ii_interface->add_elements( lt_add ). ii_interface->save_elements( ). ii_interface->set_elements_changeable( abap_false ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changed_by FROM intf INTO rv_user WHERE intf_name = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: li_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. corr_insert( iv_package ). li_interface = load( |{ ms_item-obj_name }| ). * elements must be deleted before the package interface * can be deleted delete_elements( li_interface ). li_interface->set_changeable( abap_true ). li_interface->delete( ). li_interface->save( ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: li_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT, ls_pinf TYPE ty_pinf. io_xml->read( EXPORTING iv_name = 'PINF' CHANGING cg_data = ls_pinf ). "needed for update_attributes ls_pinf-attributes-tadir_devc = iv_package. li_interface = create_or_load( is_pinf = ls_pinf iv_package = iv_package ). update_attributes( iv_package = iv_package is_pinf = ls_pinf ii_interface = li_interface ). update_elements( iv_package = iv_package is_pinf = ls_pinf ii_interface = li_interface ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_pack_name TYPE intf-pack_name, lv_main_pack TYPE tdevc-mainpack. SELECT SINGLE pack_name FROM intf INTO lv_pack_name WHERE intf_name = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). IF rv_bool = abap_true. SELECT SINGLE mainpack FROM tdevc INTO lv_main_pack WHERE devclass = lv_pack_name. "#EC CI_GENBUFF rv_bool = boolc( sy-subrc = 0 ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' iv_argument = ms_item-obj_name iv_prefix = 'PF' ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_pinf TYPE ty_pinf, lt_elements TYPE ty_elements, li_interface TYPE REF TO iUFTsqJyKbsVHldwKaGdXoRoiJNIwT. FIELD-SYMBOLS: TYPE any, LIKE LINE OF lt_elements, LIKE LINE OF ls_pinf-elements. li_interface = load( |{ ms_item-obj_name }| ). ls_pinf-attributes = li_interface->get_all_attributes( ). "Delete the package name if it comes from the same package IF ls_pinf-attributes-tadir_devc = ls_pinf-attributes-pack_name OR ms_item-devclass = ls_pinf-attributes-pack_name. CLEAR ls_pinf-attributes-pack_name. ENDIF. CLEAR: ls_pinf-attributes-author, ls_pinf-attributes-created_by, ls_pinf-attributes-created_on, ls_pinf-attributes-changed_by, ls_pinf-attributes-changed_on, ls_pinf-attributes-tadir_devc. * fields does not exist in older SAP versions ASSIGN COMPONENT 'SW_COMP_LOGICAL_PACKAGE' OF STRUCTURE ls_pinf-attributes TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'SW_COMP_TADIR_PACKAGE' OF STRUCTURE ls_pinf-attributes TO . IF sy-subrc = 0. CLEAR . ENDIF. lt_elements = li_interface->get_elements( ). LOOP AT lt_elements ASSIGNING . APPEND INITIAL LINE TO ls_pinf-elements ASSIGNING . ->get_all_attributes( IMPORTING e_element_data = ). CLEAR -elem_pack. ENDLOOP. io_xml->add( ig_data = ls_pinf iv_name = 'PINF' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_pers IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_pers_key = ms_item-obj_name. ENDMETHOD. METHOD get_personalization_object. CREATE OBJECT ro_personalization_object EXPORTING p_create = iv_create p_pers_key = mv_pers_key p_view_only = iv_view_only EXCEPTIONS pers_key_already_exists = 1 pers_key_does_not_exist = 2 transport_view_only = 3 transport_canceled = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE author FROM spers_reg INTO rv_user WHERE pers_key = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_personalization_object TYPE REF TO cl_pers_reg. lo_personalization_object = get_personalization_object( ). lo_personalization_object->delete( EXPORTING p_no_confirm = abap_true EXCEPTIONS deletion_canceled = 1 deletion_failed = 2 transport_canceled = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_personalization_object TYPE ty_personalization_object, lo_personalization_object TYPE REF TO cl_pers_reg. io_xml->read( EXPORTING iv_name = 'PERS' CHANGING cg_data = ls_personalization_object ). tadir_insert( iv_package ). lo_personalization_object = get_personalization_object( iv_create = abap_true ). lo_personalization_object->set_reg_data( p_pers_reg = ls_personalization_object-pers_reg p_pers_reg_text = ls_personalization_object-pers_reg_text ). lo_personalization_object->save( EXPORTING no_check = abap_true EXCEPTIONS data_not_saved = 1 transport_canceled = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. cl_pers_reg=>exists( EXPORTING p_pers_key = mv_pers_key EXCEPTIONS pers_key_does_not_exist = 1 OTHERS = 2 ). rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. " There's no object specific locking. Just a global one. rv_is_locked = exists_a_lock_entry_for( 'E_SPERSREG' ). ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_bcdata TYPE bdcdata, lt_bcdata TYPE STANDARD TABLE OF bdcdata. ls_bcdata-program = 'SAPLSPERS_REG_DIALOG'. ls_bcdata-dynpro = '0100'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'SPERS_REG-PERS_KEY'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=PERSDISPLAY'. APPEND ls_bcdata TO lt_bcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'PERSREG' it_bdcdata = lt_bcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_personalization_object TYPE REF TO cl_pers_reg, ls_personalization_object TYPE ty_personalization_object. lo_personalization_object = get_personalization_object( iv_view_only = abap_true ). lo_personalization_object->get_reg_data( IMPORTING p_pers_reg = ls_personalization_object-pers_reg p_pers_reg_text = ls_personalization_object-pers_reg_text ). CLEAR: ls_personalization_object-pers_reg-author, ls_personalization_object-pers_reg-fdate, ls_personalization_object-pers_reg-ftime. io_xml->add( iv_name = 'PERS' ig_data = ls_personalization_object ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_pdxx_super IMPLEMENTATION. METHOD check_subrc_for. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( iv_call && ' returned ' && sy-subrc ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). ms_objkey-otype = is_item-obj_type+2(2). ms_objkey-objid = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE uname INTO rv_user FROM hrs1201 WHERE otype = ms_item-obj_type AND objid = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. CALL FUNCTION 'RH_HRSOBJECT_DELETE' EXPORTING act_otype = ms_objkey-otype act_objid = ms_objkey-objid no_confirmation_msg = abap_true EXCEPTIONS enqueue_failed = 1 object_not_deleted = 2 object_not_found = 3 OTHERS = 4. "#EC SUBRC_OK check_subrc_for( `RH_HRSOBJECT_DELETE` ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. ASSERT 1 = 2. "Must be redefined ENDMETHOD. METHOD zif_abapgit_object~exists. CALL FUNCTION 'RH_READ_OBJECT' EXPORTING plvar = '01' otype = ms_objkey-otype objid = ms_objkey-objid istat = '1' begda = sy-datum endda = '99991231' ointerval = 'X' read_db = 'X' EXCEPTIONS not_found = 1 OTHERS = 2. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = abap_true. ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'HRSOBJECT' iv_argument = ms_objkey-otype && ms_objkey-objid ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. ASSERT 1 = 2. "Must be redefined ENDMETHOD. ENDCLASS. CLASS kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ DEFINITION DEFERRED. CLASS kHGwlvrpxwdUTiJUSNzxpMacLYgbxq DEFINITION DEFERRED. * renamed: zcl_abapgit_object_pdts :: lcl_attribute_setter CLASS kHGwlvrpxwdUTiJUSNzxpMacLYgbxq DEFINITION INHERITING FROM cl_workflow_general_task_def CREATE PUBLIC FINAL. PUBLIC SECTION. CLASS-METHODS set_objid IMPORTING iv_objid TYPE hrobject-objid io_task TYPE REF TO cl_workflow_general_task_def. CLASS-METHODS set_container_id IMPORTING iv_id TYPE guid_32 io_task TYPE REF TO cl_workflow_general_task_def. "#EC NEEDED ENDCLASS. CLASS kHGwlvrpxwdUTiJUSNzxpMacLYgbxq IMPLEMENTATION. METHOD set_container_id. FIELD-SYMBOLS TYPE REF TO if_swf_cnt_container. ASSIGN ('IO_TASK->CONTAINER') TO . ASSERT sy-subrc = 0. CALL METHOD ->('SET_GUID') EXPORTING guid_32 = iv_id. ENDMETHOD. METHOD set_objid. io_task->objid = iv_objid. ENDMETHOD. ENDCLASS. * renamed: zcl_abapgit_object_pdts :: lcl_task_definition CLASS kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ DEFINITION CREATE PUBLIC FINAL. PUBLIC SECTION. INTERFACES iUFTsvrpxwdUTiJUSNzxoTkdegmNBa. CLASS-METHODS load IMPORTING iv_objid TYPE hrobject-objid RETURNING VALUE(ri_result) TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa RAISING zcx_abapgit_exception. CLASS-METHODS create IMPORTING iv_objid TYPE hrobject-objid is_task_data TYPE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa=>ty_task_data RETURNING VALUE(ri_result) TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa RAISING zcx_abapgit_exception. PRIVATE SECTION. CONSTANTS c_subty_task_description TYPE hr_s_subty VALUE '0120'. DATA mo_taskdef TYPE REF TO cl_workflow_task_ts. DATA ms_task TYPE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa=>ty_task_data. DATA: mv_objid TYPE hrobjid. METHODS supply_instance RAISING zcx_abapgit_exception. METHODS check_subrc_for IMPORTING iv_call TYPE clike OPTIONAL RAISING zcx_abapgit_exception. ENDCLASS. CLASS kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ IMPLEMENTATION. METHOD load. DATA lo_taskdef TYPE REF TO kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ. CREATE OBJECT lo_taskdef. lo_taskdef->mv_objid = iv_objid. lo_taskdef->supply_instance( ). ri_result = lo_taskdef. ENDMETHOD. METHOD check_subrc_for. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( iv_call && ' returned ' && sy-subrc ). ENDIF. ENDMETHOD. METHOD supply_instance. cl_workflow_factory=>create_ts( EXPORTING objid = mv_objid RECEIVING ts_inst = mo_taskdef EXCEPTIONS standard_task_does_not_exist = 1 object_could_not_be_locked = 2 objid_not_given = 3 OTHERS = 4 ) ##SUBRC_OK. check_subrc_for( 'CREATE_TS' ). ms_task-wi_text = mo_taskdef->wi_text. ms_task-short_text = mo_taskdef->short_text. ms_task-plvar = mo_taskdef->plvar. ms_task-method = mo_taskdef->method. ms_task-method_binding = mo_taskdef->method_binding. ms_task-starting_events = mo_taskdef->starting_events. ms_task-starting_events_binding = mo_taskdef->starting_events_binding. ms_task-terminating_events = mo_taskdef->terminating_events. ms_task-terminating_events_binding = mo_taskdef->terminating_events_binding. ms_task-descriptions = mo_taskdef->descriptions. ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~clear_origin_data. FIELD-SYMBOLS: TYPE hrs1002, TYPE hrs1214, TYPE hrs1212, TYPE hrs1212. CLEAR: ms_task-method-aedtm, ms_task-method-uname. LOOP AT ms_task-method_binding ASSIGNING . CLEAR: -aedtm, -uname. ENDLOOP. LOOP AT ms_task-starting_events_binding ASSIGNING . CLEAR: -aedtm, -uname. ENDLOOP. LOOP AT ms_task-descriptions ASSIGNING . CLEAR: -aedtm, -uname. ENDLOOP. LOOP AT ms_task-terminating_events_binding ASSIGNING . CLEAR: -aedtm, -uname. ENDLOOP. ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~get_definition. rs_result = me->ms_task. ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~get_container. ri_result = mo_taskdef->container. ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~get_user_container. DATA: li_container TYPE REF TO if_swf_cnt_element_access_1, lt_user_elements TYPE swfdnamtab, lt_system_elements TYPE swfdnamtab, lv_element TYPE swfdname. li_container = mo_taskdef->container. lt_user_elements = li_container->all_elements_list( ). lt_system_elements = li_container->all_elements_list( list_system = abap_true ). LOOP AT lt_system_elements INTO lv_element. READ TABLE lt_user_elements WITH KEY table_line = lv_element TRANSPORTING NO FIELDS. IF sy-subrc <> 0. TRY. li_container->element_remove( name = lv_element ). CATCH cx_swf_cnt_container. "Shouldn't happen, doesn't matter if it does ENDTRY. ENDIF. ENDLOOP. ri_result ?= li_container. ENDMETHOD. METHOD create. DATA lo_task TYPE REF TO kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ. CREATE OBJECT lo_task TYPE kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ. lo_task->mv_objid = iv_objid. lo_task->ms_task = is_task_data. ri_result = lo_task. ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~import_container. DATA lt_exception_list TYPE swf_cx_tab. DATA lx_exception TYPE REF TO cx_swf_ifs_exception. mo_taskdef->container->import_from_xml( EXPORTING xml_stream = iv_xml_string IMPORTING exception_list = lt_exception_list ). IF lt_exception_list IS NOT INITIAL. READ TABLE lt_exception_list INDEX 1 INTO lx_exception. zcx_abapgit_exception=>raise_with_text( lx_exception ). ENDIF. ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~create_task. cl_workflow_factory=>create_new_ts( EXPORTING short_text = |{ ms_task-short_text }| text = |{ ms_task-wi_text }| RECEIVING task_object = mo_taskdef EXCEPTIONS text_exists_already = 1 OTHERS = 2 ). "#EC SUBRC_OK check_subrc_for( `CREATE_NEW_TS` ). kHGwlvrpxwdUTiJUSNzxpMacLYgbxq=>set_objid( iv_objid = mv_objid io_task = mo_taskdef ). kHGwlvrpxwdUTiJUSNzxpMacLYgbxq=>set_container_id( iv_id = |TS{ mv_objid }| io_task = mo_taskdef ). ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_start_events. mo_taskdef->change_start_events_complete( EXPORTING starting_events = ms_task-starting_events EXCEPTIONS no_changes_allowed = 1 OTHERS = 2 ). "#EC SUBRC_OK check_subrc_for( `CHANGE_START_EVENTS_COMPLETE` ). mo_taskdef->change_start_evt_bind_complete( EXPORTING new_bindings = ms_task-starting_events_binding EXCEPTIONS no_changes_allowed = 1 OTHERS = 2 ). "#EC SUBRC_OK check_subrc_for( `CHANGE_START_EVT_BIND_COMPLETE` ). ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~save. DATA ls_hrsobject TYPE hrsobject. ls_hrsobject-otype = 'TS'. "swfco_org_standard_task - todo: linter can't resolve this ls_hrsobject-objid = mv_objid. INSERT hrsobject FROM ls_hrsobject. mo_taskdef->save_standard_task( EXPORTING development_class = iv_package iv_force_gen = abap_true EXCEPTIONS no_changes_allowed = 1 no_client_indep_maint = 2 update_error = 3 insert_error_new_ts = 4 new_ts_could_not_be_locked = 5 save_abort_by_user = 6 OTHERS = 7 ). "#EC SUBRC_OK check_subrc_for( `SAVE_STANDARD_TASK` ). ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_wi_text. mo_taskdef->change_wi_text( EXPORTING new_wi_text = ms_task-wi_text EXCEPTIONS no_changes_allowed = 1 OTHERS = 2 ). "#EC SUBRC_OK check_subrc_for( `CHANGE_WI_TEXT` ). ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_method. FIELD-SYMBOLS TYPE hrs1214. mo_taskdef->change_method( EXPORTING new_method = ms_task-method " New Method or Settings EXCEPTIONS no_changes_allowed = 1 problem_method_web_enabling = 2 problem_method_phon_enabling = 3 OTHERS = 4 ). "#EC SUBRC_OK check_subrc_for( `CHANGE_METHOD` ). LOOP AT ms_task-method_binding ASSIGNING . mo_taskdef->change_method_binding( EXPORTING binding = delete = abap_false insert = abap_true EXCEPTIONS no_changes_allowed = 1 desired_action_not_clear = 2 ts_cnt_element_does_not_exist = 3 binding_could_not_be_deleted = 4 OTHERS = 5 ). "#EC SUBRC_OK check_subrc_for( `CHANGE_METHOD_BINDING` ). ENDLOOP. ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_terminating_events. mo_taskdef->change_term_events_complete( EXPORTING terminating_events = ms_task-terminating_events EXCEPTIONS no_changes_allowed = 1 OTHERS = 2 ). "#EC SUBRC_OK check_subrc_for( `CHANGE_TERM_EVENTS_COMPLETE` ). mo_taskdef->change_term_evt_bind_complete( EXPORTING new_bindings = ms_task-terminating_events_binding EXCEPTIONS no_changes_allowed = 1 OTHERS = 2 ). "#EC SUBRC_OK check_subrc_for( `CHANGE_TERM_EVT_BIND_COMPLETE` ). ENDMETHOD. METHOD iUFTsvrpxwdUTiJUSNzxoTkdegmNBa~change_text. mo_taskdef->change_text( EXPORTING subty = c_subty_task_description new_text = ms_task-descriptions EXCEPTIONS no_changes_allowed = 1 OTHERS = 2 ). "#EC SUBRC_OK check_subrc_for( `CHANGE_TEXT` ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_pdts IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). ms_objkey-otype = 'TS'. ms_objkey-objid = ms_item-obj_name. mv_objid = ms_item-obj_name. "Todo: Obsolete ENDMETHOD. METHOD extract_container. DATA li_stream TYPE REF TO if_ixml_ostream. DATA li_container_element TYPE REF TO if_ixml_element. DATA li_document TYPE REF TO if_ixml_document. li_document = io_xml->get_raw( ). li_container_element = li_document->find_from_name_ns( 'CONTAINER' ). IF li_container_element IS BOUND. li_document = cl_ixml=>create( )->create_document( ). li_stream = cl_ixml=>create( )->create_stream_factory( )->create_ostream_xstring( rv_result ). li_document->append_child( li_container_element ). cl_ixml=>create( )->create_renderer( document = li_document ostream = li_stream )->render( ). ENDIF. ENDMETHOD. METHOD get_container_xml. DATA li_xml_dom TYPE REF TO if_ixml_document. DATA li_elements TYPE REF TO if_ixml_node_collection. DATA li_iterator TYPE REF TO if_ixml_node_iterator. DATA li_element TYPE REF TO if_ixml_node. DATA li_children TYPE REF TO if_ixml_node_list. DATA li_child_iterator TYPE REF TO if_ixml_node_iterator. DATA li_attributes TYPE REF TO if_ixml_named_node_map. DATA lv_name TYPE string. DATA li_container TYPE REF TO if_swf_cnt_container. "Todo: get_user_container strips out system elements, but to_xml adds them back in (hardcoded internally) " Dirty hack further down to remove them from XML until we get this to work properly li_container = ii_task->get_user_container( ). li_container->to_xml( EXPORTING include_null_values = abap_true include_initial_values = abap_true include_typenames = abap_true include_change_data = abap_true include_texts = abap_false "Todo: Get texts to work properly #4164 include_extension_elements = abap_true save_delta_handling_info = abap_true use_xslt = abap_false IMPORTING xml_dom = li_xml_dom EXCEPTIONS conversion_error = 1 OTHERS = 2 ). "#EC SUBRC_OK check_subrc_for( `TO_XML` ). ri_first_element ?= li_xml_dom->get_first_child( ). li_elements = ri_first_element->get_elements_by_tag_name( 'ELEMENTS' ). li_iterator = li_elements->create_iterator( ). DO. li_element = li_iterator->get_next( ). IF li_element IS NOT BOUND. EXIT. ENDIF. li_children = li_element->get_children( ). li_child_iterator = li_children->create_iterator( ). DO. li_element = li_child_iterator->get_next( ). IF li_element IS NOT BOUND. EXIT. ENDIF. "Remove system container elements - causing too much trouble "Todo: This is a bad hack, but obsolete if we can fix todo above li_attributes = li_element->get_attributes( ). lv_name = li_attributes->get_named_item( 'NAME' )->get_value( ). IF lv_name(1) = '_'. li_element->remove_node( ). li_child_iterator->reset( ). CONTINUE. ENDIF. li_attributes->remove_named_item( 'CHGDTA' ). ENDDO. ENDDO. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_task TYPE iUFTsvrpxwdUTiJUSNzxoTkdegmNBa=>ty_task_data, lv_xml_string TYPE xstring, li_task TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa. io_xml->read( EXPORTING iv_name = 'PDTS' CHANGING cg_data = ls_task ). li_task = kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ=>create( iv_objid = mv_objid is_task_data = ls_task ). li_task->create_task( ). li_task->change_wi_text( ). li_task->change_method( ). lv_xml_string = extract_container( io_xml ). li_task->import_container( lv_xml_string ). li_task->change_start_events( ). li_task->change_terminating_events( ). li_task->change_text( ). tadir_insert( iv_package ). li_task->save( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA li_task TYPE REF TO iUFTsvrpxwdUTiJUSNzxoTkdegmNBa. li_task = kHGwlvrpxwdUTiJUSNzxhvMTMsAVCJ=>load( mv_objid ). li_task->clear_origin_data( ). io_xml->add( iv_name = 'PDTS' ig_data = li_task->get_definition( ) ). io_xml->add_xml( iv_name = 'CONTAINER' ii_xml = get_container_xml( li_task ) ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_para IMPLEMENTATION. METHOD unlock. CALL FUNCTION 'RS_ACCESS_PERMISSION' EXPORTING mode = 'FREE' object = iv_paramid object_class = 'PARA'. ENDMETHOD. METHOD zif_abapgit_object~changed_by. * looks like "changed by user" is not stored in the database rv_user = c_user_unknown. ENDMETHOD. METHOD zif_abapgit_object~delete. " We can't use FM RS_PARAMETER_DELETE because of the popup to confirm "Therefore we have to reimplement most of the FMs logic DATA lv_paramid TYPE tpara-paramid. lv_paramid = ms_item-obj_name. CALL FUNCTION 'RS_ACCESS_PERMISSION' EXPORTING global_lock = abap_true language_upd_exit = 'RS_PARAMETER_LANGUAGE_EXIT' " Name FuBa for maintenance language change object = lv_paramid object_class = ms_item-obj_type suppress_language_check = space EXCEPTIONS canceled_in_corr = 1 enqueued_by_user = 2 enqueue_system_failure = 3 illegal_parameter_values = 4 locked_by_author = 5 no_modify_permission = 6 no_show_permission = 7 permission_failure = 8 request_language_denied = 9 OTHERS = 10. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. SELECT COUNT(*) FROM cross WHERE ( type = 'P' OR type = 'Q' ) AND name = lv_paramid. IF sy-subrc = 0. unlock( lv_paramid ). zcx_abapgit_exception=>raise( 'PARA: Parameter is still used' ). ELSE. SELECT COUNT(*) FROM dd04l BYPASSING BUFFER WHERE memoryid = lv_paramid AND as4local = 'A'. IF sy-subrc = 0. unlock( lv_paramid ). zcx_abapgit_exception=>raise( 'PARA: Parameter is still used' ). ENDIF. ENDIF. unlock( lv_paramid ). zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( iv_object = 'PARA' iv_obj_name = lv_paramid iv_package = iv_package iv_language = mv_language iv_mode = zif_abapgit_cts_api=>c_transport_mode-delete ). DELETE FROM tpara WHERE paramid = lv_paramid. DELETE FROM tparat WHERE paramid = lv_paramid. CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' EXPORTING object = lv_paramid operation = 'DELETE' type = 'CR'. ENDMETHOD. METHOD zif_abapgit_object~deserialize. * see fm RS_PARAMETER_ADD and RS_PARAMETER_EDIT DATA: lv_mode TYPE c LENGTH 1, ls_tpara TYPE tpara, ls_tparat TYPE tparat. SELECT SINGLE * FROM tpara INTO ls_tpara WHERE paramid = ms_item-obj_name. "#EC CI_GENBUFF IF sy-subrc = 0. lv_mode = 'M'. ELSE. lv_mode = 'I'. ENDIF. io_xml->read( EXPORTING iv_name = 'TPARA' CHANGING cg_data = ls_tpara ). CALL FUNCTION 'RS_CORR_INSERT' EXPORTING object = ms_item-obj_name object_class = 'PARA' mode = lv_mode global_lock = abap_true devclass = iv_package master_language = mv_language suppress_dialog = abap_true EXCEPTIONS cancelled = 1 permission_failure = 2 unknown_objectclass = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. MODIFY tpara FROM ls_tpara. "#EC CI_SUBRC ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'TPARAT' CHANGING cg_data = ls_tparat ). MODIFY tparat FROM ls_tparat. "#EC CI_SUBRC ASSERT sy-subrc = 0. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_paramid TYPE tpara-paramid. SELECT SINGLE paramid FROM tpara INTO lv_paramid WHERE paramid = ms_item-obj_name. "#EC CI_GENBUFF rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' iv_argument = ms_item-obj_name iv_prefix = 'PA' ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_tpara TYPE tpara, ls_tparat TYPE tparat. SELECT SINGLE * FROM tpara INTO ls_tpara WHERE paramid = ms_item-obj_name. "#EC CI_GENBUFF IF sy-subrc <> 0. RETURN. ENDIF. SELECT SINGLE * FROM tparat INTO ls_tparat WHERE paramid = ms_item-obj_name AND sprache = mv_language. "#EC CI_GENBUFF "#EC CI_SUBRC io_xml->add( iv_name = 'TPARA' ig_data = ls_tpara ). io_xml->add( iv_name = 'TPARAT' ig_data = ls_tparat ). " Here only the original language is serialized, " so it should be present for the moment. LXEs are just translations ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_otgr IMPLEMENTATION. METHOD instantiate_and_lock_otgr. DATA: lv_new TYPE abap_bool, lv_name TYPE cls_attribute_name, lv_state TYPE cls_type_group-activation_state. SELECT SINGLE name FROM cls_type_group INTO lv_name WHERE name = ms_item-obj_name. IF sy-subrc = 0. lv_new = abap_false. lv_state = cl_pak_wb_domains=>co_activation_state-invalid. ELSE. lv_new = abap_true. lv_state = cl_pak_wb_domains=>co_activation_state-active. ENDIF. lv_name = ms_item-obj_name. TRY. CREATE OBJECT ro_otgr EXPORTING im_name = lv_name im_new = lv_new im_activation_state = lv_state. CATCH cx_pak_invalid_data cx_pak_not_authorized cx_pak_invalid_state cx_pak_wb_object_locked. zcx_abapgit_exception=>raise( |OTGR { lv_name }: error while instantiating CL_CLS_OBJECT_TYPE_GROUP| ). ENDTRY. IF lv_new = abap_false. TRY. ro_otgr->if_pak_wb_object~lock_and_refresh( ). CATCH cx_pak_invalid_data cx_pak_not_authorized cx_pak_invalid_state cx_pak_wb_object_locked. zcx_abapgit_exception=>raise( |OTGR { lv_name }: could not acquire lock| ). ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changed_by FROM cls_type_group INTO rv_user WHERE name = ms_item-obj_name AND activation_state = cl_pak_wb_domains=>co_activation_state-active. IF rv_user IS INITIAL. SELECT SINGLE created_by FROM cls_type_group INTO rv_user WHERE name = ms_item-obj_name AND activation_state = cl_pak_wb_domains=>co_activation_state-active. ENDIF. IF rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_otgr TYPE REF TO cl_cls_object_type_group, lx_pak_error TYPE REF TO cx_root, lv_text TYPE string. lo_otgr = instantiate_and_lock_otgr( ). TRY. lo_otgr->if_pak_wb_object~delete( ). lo_otgr->if_pak_wb_object~save( ). lo_otgr->unlock( ). CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. lo_otgr->unlock( ). lv_text = lx_pak_error->get_text( ). zcx_abapgit_exception=>raise( |OTGR { ms_item-obj_name }: delete: { lv_text }| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_otgr TYPE ty_otgr, lo_otgr TYPE REF TO cl_cls_object_type_group, lx_pak_error TYPE REF TO cx_root, lv_text TYPE string, lv_main_lang TYPE sy-langu, lo_parents TYPE REF TO data. FIELD-SYMBOLS: LIKE LINE OF ls_otgr-texts, LIKE LINE OF ls_otgr-elements, TYPE any, TYPE any, TYPE ANY TABLE. io_xml->read( EXPORTING iv_name = 'OTGR' CHANGING cg_data = ls_otgr ). LOOP AT ls_otgr-texts ASSIGNING . -activation_state = cl_pak_wb_domains=>co_activation_state-inactive. " Removed in the method serialize. -name = ms_item-obj_name. ENDLOOP. " Parents (cls_tygr_parent) does not exist in lower releases TRY. CREATE DATA lo_parents TYPE TABLE OF ('CLS_TYGR_PARENT'). ASSIGN lo_parents->* TO . CATCH cx_sy_create_data_error. ENDTRY. IF IS ASSIGNED. io_xml->read( EXPORTING iv_name = 'PARENTS' CHANGING cg_data = ). LOOP AT ASSIGNING . ASSIGN COMPONENT 'ACTIVATION_STATE' OF STRUCTURE TO . IF sy-subrc = 0. = cl_pak_wb_domains=>co_activation_state-inactive. ENDIF. ASSIGN COMPONENT 'OBJ_TYPE_GROUP' OF STRUCTURE TO . IF sy-subrc = 0. " Removed in the method serialize. = ms_item-obj_name. ENDIF. ENDLOOP. ENDIF. LOOP AT ls_otgr-elements ASSIGNING . -activation_state = cl_pak_wb_domains=>co_activation_state-inactive. " Removed in the method serialize. -obj_type_group = ms_item-obj_name. ENDLOOP. tadir_insert( iv_package ). lo_otgr = instantiate_and_lock_otgr( ). TRY. lo_otgr->if_cls_object_type_group~set_proxy_filter( ls_otgr-cls_type_group-proxy_flag ). lo_otgr->if_cls_object_type_group~set_elements( ls_otgr-elements ). IF IS ASSIGNED. CALL METHOD lo_otgr->('IF_CLS_OBJECT_TYPE_GROUP~SET_PARENT_GROUPS') EXPORTING im_parent_groups = . ENDIF. lv_main_lang = lo_otgr->if_pak_wb_object~get_master_language( ). READ TABLE ls_otgr-texts WITH KEY langu = lv_main_lang ASSIGNING . IF sy-subrc = 0. lo_otgr->set_description( -text ). " ELSE. " Do we want to clear the main language description if not present in the XML content? " Main language is non-deterministic - it depends on sy-langu, so rather don't touch " description if the main language is not present " Perhaps, we can display some sort of a message but how? ENDIF. set_default_package( iv_package ). lo_otgr->if_pak_wb_object~save( ). lo_otgr->if_pak_wb_object~activate( ). lo_otgr->unlock( ). CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. lo_otgr->unlock( ). lv_text = lx_pak_error->get_text( ). zcx_abapgit_exception=>raise( |OTGR { ms_item-obj_name }: deserialize: { lv_text }| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = cl_cls_object_type_group=>exists_object_type_group( ms_item-obj_name ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ECLS_ATTRIBUTE' iv_argument = |{ ms_item-obj_name }*| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_text TYPE string, lv_name TYPE ty_otgr-cls_type_group, ls_otgr TYPE ty_otgr, lo_otgr TYPE REF TO cl_cls_object_type_group, lx_pak_error TYPE REF TO cx_root, lo_parents TYPE REF TO data. FIELD-SYMBOLS: LIKE LINE OF ls_otgr-texts, LIKE LINE OF ls_otgr-elements, TYPE any, TYPE any, TYPE ANY TABLE. lo_otgr = instantiate_and_lock_otgr( ). * Description part 1: * Dealing with Description of OTGR objects is problematic. * The API supports setting of main language only and * if we want to save also translations we would have to implement * our own logic for merging and activation. To keep it simple stupid * the current version focuses on the main language only. * If anybody ever runs into the need to version also translation, * ask the maintainers of CL_CLS_OBJECT_TYPE_GROUP to add a method for it. * * However, the XML content will pretend we support also translations, * so if someone adds support for them in future, there will be no format change. APPEND INITIAL LINE TO ls_otgr-texts ASSIGNING . " Parents (cls_tygr_parent) does not exist in lower releases TRY. CREATE DATA lo_parents TYPE TABLE OF ('CLS_TYGR_PARENT'). ASSIGN lo_parents->* TO . CATCH cx_sy_create_data_error. ENDTRY. TRY. ls_otgr-cls_type_group-name = lo_otgr->if_cls_object_type_group~get_name( ). ls_otgr-cls_type_group-proxy_flag = lo_otgr->if_cls_object_type_group~get_proxy_filter( ). TRY. CALL METHOD lo_otgr->('GET_ELEMENTS') EXPORTING im_explicit_elements_only = abap_true " doesn't exist on lower releases. Eg. 752 SP04 IMPORTING ex_elements = ls_otgr-elements. CATCH cx_sy_dyn_call_param_not_found. lo_otgr->get_elements( IMPORTING ex_elements = ls_otgr-elements ). ENDTRY. " Remove children since they are created automatically (by the child group) LOOP AT ls_otgr-elements ASSIGNING . SELECT SINGLE name FROM cls_type_group INTO lv_name WHERE name = -type. IF sy-subrc = 0. DELETE ls_otgr-elements. ENDIF. ENDLOOP. IF IS ASSIGNED. CALL METHOD lo_otgr->('IF_CLS_OBJECT_TYPE_GROUP~GET_PARENT_GROUPS') EXPORTING im_explicit_parents_only = abap_true IMPORTING ex_parent_groups = . ENDIF. " Beware: the following method returns the main language description only if the object is locked! -text = lo_otgr->if_cls_object_type_group~get_description( ). -langu = lo_otgr->if_pak_wb_object~get_master_language( ). lo_otgr->unlock( ). CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. lo_otgr->unlock( ). lv_text = lx_pak_error->get_text( ). zcx_abapgit_exception=>raise( |OTGR { ms_item-obj_name }: serialize: { lv_text }| ). ENDTRY. CLEAR: ls_otgr-cls_type_group-created_by, ls_otgr-cls_type_group-created_on, ls_otgr-cls_type_group-changed_by, ls_otgr-cls_type_group-changed_on. * Description part 2: * * lt_lang_sel TYPE RANGE OF langu, * ls_lang_sel LIKE LINE OF lt_lang_sel, * * IF io_xml->i18n_params( )-main_language_only = abap_true. * ls_lang_sel-low = mv_language. * ls_lang_sel-sign = 'I'. * ls_lang_sel-option = 'EQ'. * ENDIF. * * SELECT * FROM cls_type_groupt INTO TABLE ls_otgr-texts * WHERE name = ms_item-obj_name * AND activation_state = 'A' * AND langu in lt_lang_sel. * * Description ideas end LOOP AT ls_otgr-texts ASSIGNING . " Not necessary as we serialize only Active CLEAR -activation_state. " Not necessary as we have it in the root XML node CLEAR -name. ENDLOOP. LOOP AT ls_otgr-elements ASSIGNING . " Not necessary as we serialize only Active CLEAR -activation_state. " Not necessary as we have it in the root XML node CLEAR -obj_type_group. ENDLOOP. io_xml->add( iv_name = 'OTGR' ig_data = ls_otgr ). IF IS ASSIGNED. LOOP AT ASSIGNING . ASSIGN COMPONENT 'ACTIVATION_STATE' OF STRUCTURE TO . IF sy-subrc = 0. " Not necessary as we serialize only Active CLEAR . ENDIF. ASSIGN COMPONENT 'OBJ_TYPE_GROUP' OF STRUCTURE TO . IF sy-subrc = 0. " Not necessary as we have it in the root XML node CLEAR . ENDIF. ENDLOOP. io_xml->add( iv_name = 'PARENTS' ig_data = ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_odso IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cg_metadata TO . ASSERT sy-subrc = 0. CLEAR: . ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_dsonam TYPE c LENGTH 30, ls_return TYPE bapiret2, lr_details TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE DATA lr_details TYPE ('BAPI6116'). CATCH cx_sy_create_data_error. zcx_abapgit_exception=>raise( |ODSO is not supported on this system| ). ENDTRY. ASSIGN lr_details->* TO . lv_dsonam = ms_item-obj_name. CALL FUNCTION 'BAPI_ODSO_GETDETAIL' EXPORTING odsobject = lv_dsonam IMPORTING details = return = ls_return. IF ls_return-type = 'E'. zcx_abapgit_exception=>raise( |Error when getting changed by of ODSO: { ls_return-message }| ). ENDIF. ASSIGN COMPONENT 'TSTPNM' OF STRUCTURE TO . rv_user = . ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_odsonam TYPE c LENGTH 30, lv_objname TYPE sobj_name, lo_collection TYPE REF TO object, lt_msg TYPE STANDARD TABLE OF bal_s_msg, ls_msg TYPE bal_s_msg. TRY. CREATE OBJECT lo_collection TYPE ('CL_RSD_ODSO_COLLECTION'). CATCH cx_sy_create_data_error. zcx_abapgit_exception=>raise( |ODSO is not supported on this system| ). ENDTRY. lv_odsonam = ms_item-obj_name. lv_objname = ms_item-obj_name. TRY. CALL METHOD lo_collection->('ADD_TLOGO') EXPORTING i_objnm = lv_objname i_modify = abap_true i_delete = abap_true. CALL METHOD lo_collection->('DELETE'). CALL METHOD ('CL_RSO_APPLICATION_LOG')=>('APPL_LOG_MSG_READ') IMPORTING e_t_msg = lt_msg. READ TABLE lt_msg WITH KEY msgty = 'E' INTO ls_msg. IF sy-subrc = 0. zcx_abapgit_exception=>raise( |Error when deleting ODSO: { ms_item-obj_name } { ls_msg-msgv1 } { ls_msg-msgv2 }| ). ENDIF. CATCH cx_root. zcx_abapgit_exception=>raise( |Canceled deletion of ODSO: { ms_item-obj_name }| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_dsonam TYPE c LENGTH 30, lr_details TYPE REF TO data, lr_infoobjects TYPE REF TO data, lr_navigation TYPE REF TO data, lr_indexes TYPE REF TO data, lr_index_iobj TYPE REF TO data, lt_return TYPE STANDARD TABLE OF bapiret2, ls_return TYPE bapiret2. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE. TRY. CREATE DATA lr_details TYPE ('BAPI6116'). CREATE DATA lr_infoobjects TYPE STANDARD TABLE OF ('BAPI6116IO'). CREATE DATA lr_navigation TYPE STANDARD TABLE OF ('BAPI6116NA'). CREATE DATA lr_indexes TYPE STANDARD TABLE OF ('BAPI6116IN'). CREATE DATA lr_index_iobj TYPE STANDARD TABLE OF ('BAPI6116II'). CATCH cx_sy_create_data_error. zcx_abapgit_exception=>raise( |ODSO is not supported on this system| ). ENDTRY. ASSIGN lr_details->* TO . ASSIGN lr_infoobjects->* TO . ASSIGN lr_navigation->* TO . ASSIGN lr_indexes->* TO . ASSIGN lr_index_iobj->* TO . io_xml->read( EXPORTING iv_name = 'ODSO' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'INFOOBJECTS' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'NAVIGATION' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'INDEXES' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'INDEX_IOBJ' CHANGING cg_data = ). TRY. ASSIGN COMPONENT 'ODSOBJECT' OF STRUCTURE TO . ASSERT sy-subrc = 0. IF zif_abapgit_object~exists( ) = abap_false. CALL FUNCTION 'BAPI_ODSO_CREATE' EXPORTING details = IMPORTING odsobject = lv_dsonam TABLES infoobjects = navigationattributes = indexes = indexesinfoobjects = return = lt_return. ELSE. CALL FUNCTION 'BAPI_ODSO_CHANGE' EXPORTING odsobject = details = TABLES infoobjects = navigationattributes = indexes = indexesinfoobjects = return = lt_return. ENDIF. CATCH cx_sy_dyn_call_illegal_func. zcx_abapgit_exception=>raise( |Necessary BW function modules not found or object not supported| ). ENDTRY. READ TABLE lt_return WITH KEY type = 'E' INTO ls_return. IF sy-subrc = 0. zcx_abapgit_exception=>raise( |Error when creating ODSO: { ls_return-message }| ). ENDIF. CALL FUNCTION 'BAPI_ODSO_ACTIVATE' EXPORTING odsobject = TABLES return = lt_return. READ TABLE lt_return WITH KEY type = 'E' INTO ls_return. IF sy-subrc = 0. zcx_abapgit_exception=>raise( |Error when activating ODSO: { ls_return-message }| ). ENDIF. tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_iobjnm TYPE c LENGTH 30. SELECT SINGLE odsobject FROM ('RSDODSO') INTO lv_iobjnm WHERE odsobject = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. DATA: lv_dsona TYPE c LENGTH 30, lo_odso TYPE REF TO object, lv_isact TYPE abap_bool. lv_dsona = ms_item-obj_name. CALL METHOD ('CL_RSD_ODSO')=>('FACTORY') EXPORTING i_odsobject = lv_dsona RECEIVING r_r_odso = lo_odso. CALL METHOD lo_odso->('IS_ACTIVE') RECEIVING r_is_active = lv_isact. rv_active = lv_isact. ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_object TYPE eqegraarg. lv_object = ms_item-obj_name. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'RSD_S_PROV' iv_argument = lv_object ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_dsonam TYPE c LENGTH 30, lr_details TYPE REF TO data, lr_infoobjects TYPE REF TO data, lr_navigation TYPE REF TO data, lr_indexes TYPE REF TO data, lr_index_iobj TYPE REF TO data, ls_return TYPE bapiret2. FIELD-SYMBOLS: TYPE any, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE. TRY. CREATE DATA lr_details TYPE ('BAPI6116'). CREATE DATA lr_infoobjects TYPE STANDARD TABLE OF ('BAPI6116IO'). CREATE DATA lr_navigation TYPE STANDARD TABLE OF ('BAPI6116NA'). CREATE DATA lr_indexes TYPE STANDARD TABLE OF ('BAPI6116IN'). CREATE DATA lr_index_iobj TYPE STANDARD TABLE OF ('BAPI6116II'). CATCH cx_sy_create_data_error. zcx_abapgit_exception=>raise( |ODSO is not supported on this system| ). ENDTRY. ASSIGN lr_details->* TO . ASSIGN lr_infoobjects->* TO . ASSIGN lr_navigation->* TO . ASSIGN lr_indexes->* TO . ASSIGN lr_index_iobj->* TO . lv_dsonam = ms_item-obj_name. CALL FUNCTION 'BAPI_ODSO_GETDETAIL' EXPORTING odsobject = lv_dsonam IMPORTING details = return = ls_return TABLES infoobjects = navigationattributes = indexes = indexesinfoobjects = . IF ls_return-type = 'E'. zcx_abapgit_exception=>raise( |Error when getting details of ODSO: { ls_return-message }| ). ENDIF. clear_field( EXPORTING iv_fieldname = 'TSTPNM' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'TIMESTMP' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'CONTTIMESTMP' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'OWNER' CHANGING cg_metadata = ). io_xml->add( iv_name = 'ODSO' ig_data = ). io_xml->add( iv_name = 'INFOOBJECTS' ig_data = ). io_xml->add( iv_name = 'NAVIGATION' ig_data = ). io_xml->add( iv_name = 'INDEXES' ig_data = ). io_xml->add( iv_name = 'INDEX_IOBJ' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_oa2p IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_profile = is_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lo_persist TYPE REF TO object, lr_wb TYPE REF TO data, lo_profile TYPE REF TO object, lv_profile_key TYPE seu_objkey. FIELD-SYMBOLS: TYPE any. lv_profile_key = mv_profile. CREATE OBJECT lo_persist TYPE ('CL_OA2P_OBJECT_PERSIST'). CREATE OBJECT lo_profile TYPE ('CL_OA2P_OBJECT_DATA'). CREATE DATA lr_wb TYPE REF TO ('IF_WB_OBJECT_DATA_MODEL'). ASSIGN lr_wb->* TO . ?= lo_profile. TRY. CALL METHOD lo_persist->('IF_WB_OBJECT_PERSIST~GET') EXPORTING p_object_key = lv_profile_key " Object Key p_version = 'A' " Version (Active/Inactive) CHANGING p_object_data = . " Object Data CATCH cx_swb_object_does_not_exist. zcx_abapgit_exception=>raise( |OAuth2 Profile { lv_profile_key } doesn't exist.| ). CATCH cx_swb_exception. zcx_abapgit_exception=>raise( |Error when getting details of OAuth2 Profile { lv_profile_key }.| ). ENDTRY. lo_profile = . CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~GET_CHANGED_BY') RECEIVING p_user_name = rv_user. ENDMETHOD. METHOD zif_abapgit_object~delete. CONSTANTS: lc_actvt TYPE c LENGTH 2 VALUE `06`. DATA: lo_persist TYPE REF TO object, lv_profile_key TYPE seu_objkey. "authority check AUTHORITY-CHECK OBJECT 'S_OA2C_ADM' ID 'ACTVT' FIELD lc_actvt. IF sy-subrc <> 0. MESSAGE e463(01) WITH mv_profile INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. "delete profile lv_profile_key = mv_profile. CREATE OBJECT lo_persist TYPE ('CL_OA2P_OBJECT_PERSIST'). TRY. CALL METHOD lo_persist->('IF_WB_OBJECT_PERSIST~DELETE') EXPORTING p_object_key = lv_profile_key. " Object Key CATCH cx_swb_object_does_not_exist. CATCH cx_swb_exception. zcx_abapgit_exception=>raise( |Error when deleting OAuth2 Profile { lv_profile_key }.| ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_persist TYPE REF TO object, lo_profile TYPE REF TO object, lr_wb TYPE REF TO data, lr_profile_data TYPE REF TO data. FIELD-SYMBOLS: TYPE data, TYPE any. CREATE DATA lr_profile_data TYPE ('OA2C_SX_OA2P_OBJECT_DATA'). ASSIGN lr_profile_data->* TO . io_xml->read( EXPORTING iv_name = 'PROFILE' CHANGING cg_data = ). CREATE OBJECT lo_profile TYPE ('CL_OA2P_OBJECT_DATA'). CREATE DATA lr_wb TYPE REF TO ('IF_WB_OBJECT_DATA_MODEL'). ASSIGN lr_wb->* TO . ?= lo_profile. CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_DATA') EXPORTING p_data = . CREATE OBJECT lo_persist TYPE ('CL_OA2P_OBJECT_PERSIST'). TRY. CALL METHOD lo_persist->('IF_WB_OBJECT_PERSIST~SAVE') EXPORTING p_object_data = . " Object Data CATCH cx_swb_exception. zcx_abapgit_exception=>raise( |Error deserialize profile { mv_profile }.| ). ENDTRY. tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. CALL METHOD ('CL_OA2P_OBJECT_PERSIST')=>('CHECK_EXISTS_ON_DB') EXPORTING i_profile = mv_profile RECEIVING r_exists = rv_bool. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_profile_name TYPE eqegraarg, lv_lock_number TYPE i, lt_locks TYPE STANDARD TABLE OF seqg3. lv_profile_name = mv_profile. CALL FUNCTION 'ENQUEUE_READ' EXPORTING gclient = sy-mandt " Client gname = 'OA2C_PROFILES' " Granularity name (-> table name) garg = lv_profile_name " Granularity value(->values of key fields) IMPORTING number = lv_lock_number TABLES enq = lt_locks. " Number of chosen lock entries rv_is_locked = boolc( lv_lock_number > 0 ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_persist TYPE REF TO object, lo_profile TYPE REF TO object, lv_profile_key TYPE seu_objkey, lr_profile_data TYPE REF TO data, lr_wb TYPE REF TO data. FIELD-SYMBOLS: TYPE data, TYPE any, TYPE any. CREATE DATA lr_profile_data TYPE ('OA2C_SX_OA2P_OBJECT_DATA'). ASSIGN lr_profile_data->* TO . lv_profile_key = mv_profile. CREATE OBJECT lo_persist TYPE ('CL_OA2P_OBJECT_PERSIST'). CREATE OBJECT lo_profile TYPE ('CL_OA2P_OBJECT_DATA'). CREATE DATA lr_wb TYPE REF TO ('IF_WB_OBJECT_DATA_MODEL'). ASSIGN lr_wb->* TO . ?= lo_profile. TRY. CALL METHOD lo_persist->('IF_WB_OBJECT_PERSIST~GET') EXPORTING p_object_key = lv_profile_key " Object Key p_version = 'A' " Version (Active/Inactive) CHANGING p_object_data = . " Object Data CATCH cx_swb_object_does_not_exist. zcx_abapgit_exception=>raise( |OAuth2 Profile { lv_profile_key } doesn't exist.| ). CATCH cx_swb_exception. zcx_abapgit_exception=>raise( |Error when getting details of OAuth2 Profile { lv_profile_key }.| ). ENDTRY. "remove system specific information lo_profile = . CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_CHANGED_BY') EXPORTING p_user_name = ''. CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_CHANGED_ON') EXPORTING p_date = '00000000' p_time = '000000'. CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_CREATED_BY') EXPORTING p_user_name = ''. CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~SET_CREATED_ON') EXPORTING p_date = '00000000' p_time = '000000'. CALL METHOD lo_profile->('IF_WB_OBJECT_DATA_MODEL~GET_DATA') IMPORTING p_data = . "remove runtime information ASSIGN COMPONENT 'O_SPECIFICS' OF STRUCTURE TO . CLEAR . io_xml->add( iv_name = 'PROFILE' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_nspc IMPLEMENTATION. METHOD add_to_transport. DATA: li_sap_package TYPE REF TO zif_abapgit_sap_package. li_sap_package = zcl_abapgit_factory=>get_sap_package( iv_package ). IF li_sap_package->are_changes_recorded_in_tr_req( ) = abap_true. corr_insert( iv_package ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_component = replace( val = is_item-obj_name sub = '/' with = '' occ = 0 ). ENDMETHOD. METHOD deserialize_sw_component. DATA: ls_cvers_old TYPE cvers, ls_cvers_new TYPE cvers, ls_cvers_ref TYPE cvers_ref. ii_xml->read( EXPORTING iv_name = 'CVERS' CHANGING cg_data = ls_cvers_new ). ii_xml->read( EXPORTING iv_name = 'CVERS_REF' CHANGING cg_data = ls_cvers_ref ). IF ls_cvers_new IS NOT INITIAL. SELECT SINGLE * FROM cvers INTO ls_cvers_old WHERE component = mv_component. IF sy-subrc = 0. IF ls_cvers_old <> ls_cvers_new. zcx_abapgit_exception=>raise( `Update of software component not supported.` && ` Use Software Update Manager (SUM)` ). ENDIF. ELSE. INSERT cvers FROM ls_cvers_new. ENDIF. ENDIF. IF ls_cvers_ref IS NOT INITIAL. MODIFY cvers_ref FROM ls_cvers_ref. IF sy-subrc <> 0. INSERT cvers_ref FROM ls_cvers_ref. ENDIF. ENDIF. ENDMETHOD. METHOD deserialize_texts. DATA: ls_trnspacett TYPE trnspacett, lt_i18n_langs TYPE TABLE OF langu, lt_cvers_refs TYPE TABLE OF cvers_ref, ls_cvers_ref TYPE cvers_ref, lt_nspc_texts TYPE ty_nspc_texts. FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, LIKE LINE OF lt_nspc_texts. ii_xml->read( EXPORTING iv_name = 'I18N_LANGS' CHANGING cg_data = lt_i18n_langs ). ii_xml->read( EXPORTING iv_name = 'NSPC_TEXTS' CHANGING cg_data = lt_nspc_texts ). ii_xml->read( EXPORTING iv_name = 'CVERS_REFS' CHANGING cg_data = lt_cvers_refs ). SORT lt_i18n_langs. SORT lt_nspc_texts BY spras. " Optimization SORT lt_cvers_refs BY langu. " Optimization LOOP AT lt_i18n_langs ASSIGNING . ls_trnspacett-namespace = iv_namespace. READ TABLE lt_nspc_texts ASSIGNING WITH KEY spras = . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Cannot find language { } in XML| ). ENDIF. MOVE-CORRESPONDING TO ls_trnspacett. MODIFY trnspacett FROM ls_trnspacett. IF sy-subrc <> 0. INSERT trnspacett FROM ls_trnspacett. ENDIF. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error upserting text for namespace| ). ENDIF. READ TABLE lt_cvers_refs INTO ls_cvers_ref WITH KEY langu = . IF sy-subrc = 0. MODIFY cvers_ref FROM ls_cvers_ref. IF sy-subrc <> 0. INSERT cvers_ref FROM ls_cvers_ref. ENDIF. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error upserting text for software component| ). ENDIF. ENDIF. ENDLOOP. ENDMETHOD. METHOD serialize_sw_component. DATA: ls_cvers TYPE cvers, ls_cvers_ref TYPE cvers_ref. SELECT SINGLE * FROM cvers INTO ls_cvers WHERE component = mv_component. IF sy-subrc = 0. ii_xml->add( iv_name = 'CVERS' ig_data = ls_cvers ). ENDIF. SELECT SINGLE * FROM cvers_ref INTO ls_cvers_ref WHERE component = mv_component AND langu = mv_language. IF sy-subrc = 0. ii_xml->add( iv_name = 'CVERS_REF' ig_data = ls_cvers_ref ). ENDIF. ENDMETHOD. METHOD serialize_texts. DATA: ls_trnspacett TYPE trnspacett, lt_nspc_texts TYPE ty_nspc_texts, lt_cvers_refs TYPE TABLE OF cvers_ref, lt_i18n_langs TYPE TABLE OF langu. FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, LIKE LINE OF lt_nspc_texts. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. " Collect additional languages, skip main lang - it was serialized already SELECT DISTINCT spras AS langu FROM trnspacett INTO TABLE lt_i18n_langs WHERE namespace = ms_item-obj_name AND spras <> mv_language ORDER BY langu. "#EC CI_SUBRC LOOP AT lt_i18n_langs ASSIGNING . SELECT SINGLE * FROM trnspacett INTO ls_trnspacett WHERE namespace = ms_item-obj_name AND spras = . IF sy-subrc = 0. APPEND INITIAL LINE TO lt_nspc_texts ASSIGNING . MOVE-CORRESPONDING ls_trnspacett TO . ENDIF. SELECT * FROM cvers_ref APPENDING TABLE lt_cvers_refs WHERE component = mv_component AND langu = ORDER BY PRIMARY KEY. ENDLOOP. SORT lt_i18n_langs ASCENDING. SORT lt_nspc_texts BY spras ASCENDING. SORT lt_cvers_refs. IF lines( lt_i18n_langs ) > 0. ii_xml->add( iv_name = 'I18N_LANGS' ig_data = lt_i18n_langs ). ii_xml->add( iv_name = 'NSPC_TEXTS' ig_data = lt_nspc_texts ). ii_xml->add( iv_name = 'CVERS_REFS' ig_data = lt_cvers_refs ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changeuser FROM trnspacet INTO rv_user WHERE namespace = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. RETURN. " not supported ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_nspc TYPE ty_nspc, ls_nspc_text TYPE ty_nspc_text, lv_modifiable TYPE abap_bool, ls_trnspacet TYPE trnspacet, ls_trnspacett TYPE trnspacett. io_xml->read( EXPORTING iv_name = 'NSPC' CHANGING cg_data = ls_nspc ). io_xml->read( EXPORTING iv_name = 'NSPC_TEXT' CHANGING cg_data = ls_nspc_text ). add_to_transport( iv_package ). SELECT SINGLE * FROM trnspacet INTO ls_trnspacet WHERE namespace = ls_nspc-namespace. IF sy-subrc = 0. " For existing namespace, check if it's modifiable (SE03) SELECT SINGLE editflag FROM trnspace INTO lv_modifiable WHERE namespace = ls_nspc-namespace. IF sy-subrc = 0 AND lv_modifiable = abap_false. zcx_abapgit_exception=>raise( |Namespace is not modifiable| ). ENDIF. " keep existing role ls_trnspacet-replicense = ls_nspc-replicense. ls_trnspacet-sscrflag = ls_nspc-sscrflag. ls_trnspacet-sapflag = ls_nspc-sapflag. ls_trnspacet-gen_only = ls_nspc-gen_only. ls_trnspacet-changeuser = sy-uname. ls_trnspacet-changedate = sy-datum. MODIFY trnspacet FROM ls_trnspacet. ELSE. MOVE-CORRESPONDING ls_nspc TO ls_trnspacet. ls_trnspacet-role = 'C'. " customer repair license ls_trnspacet-changeuser = sy-uname. ls_trnspacet-changedate = sy-datum. INSERT trnspacet FROM ls_trnspacet. ENDIF. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error upserting namespace| ). ENDIF. SELECT SINGLE * FROM trnspacett INTO ls_trnspacett WHERE namespace = ls_nspc-namespace AND spras = mv_language. IF sy-subrc = 0. ls_trnspacett-descriptn = ls_nspc_text-descriptn. ls_trnspacett-owner = ls_nspc_text-owner. MODIFY trnspacett FROM ls_trnspacett. ELSE. MOVE-CORRESPONDING ls_nspc_text TO ls_trnspacett. ls_trnspacett-namespace = ls_nspc-namespace. INSERT trnspacett FROM ls_trnspacett. ENDIF. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error upserting text for namespace| ). ENDIF. deserialize_texts( ii_xml = io_xml iv_namespace = ls_nspc-namespace ). deserialize_sw_component( io_xml ). " Fill trnspace and trnspacel tables CALL FUNCTION 'TR_ACTIVATE_NAMESPACE' EXPORTING iv_namespace = ls_nspc-namespace EXCEPTIONS deletion_not_allowed = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error activating namespace| ). ENDIF. " Make namespace modifiable UPDATE trnspace SET editflag = abap_true WHERE namespace = ls_nspc-namespace. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA lv_namespace TYPE trnspace-namespace. lv_namespace = ms_item-obj_name. CALL FUNCTION 'TR_CHECK_NAMESPACE' EXPORTING iv_namespace = lv_namespace EXCEPTIONS namespace_not_valid = 1 OTHERS = 2. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = zif_abapgit_object~exists( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Launch general maintenance for namespaces CALL FUNCTION 'VIEW_MAINTENANCE_CALL' EXPORTING action = 'S' view_name = 'V_TRNSPACE' no_warning_for_clientindep = 'X' variant_for_selection = 'STANDARD' EXCEPTIONS client_reference = 1 foreign_lock = 2 invalid_action = 3 no_clientindependent_auth = 4 no_database_function = 5 no_editor_function = 6 no_show_auth = 7 no_tvdir_entry = 8 no_upd_auth = 9 only_show_allowed = 10 system_failure = 11 unknown_field_in_dba_sellist = 12 view_not_found = 13 OTHERS = 14. rv_exit = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_nspc TYPE ty_nspc, ls_nspc_text TYPE ty_nspc_text. SELECT SINGLE * FROM trnspacet INTO CORRESPONDING FIELDS OF ls_nspc WHERE namespace = ms_item-obj_name. SELECT SINGLE * FROM trnspacett INTO CORRESPONDING FIELDS OF ls_nspc_text WHERE namespace = ms_item-obj_name AND spras = mv_language. io_xml->add( iv_name = 'NSPC' ig_data = ls_nspc ). io_xml->add( iv_name = 'NSPC_TEXT' ig_data = ls_nspc_text ). serialize_texts( io_xml ). serialize_sw_component( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_nrob IMPLEMENTATION. METHOD delete_intervals. DATA: lv_error TYPE c LENGTH 1, ls_error TYPE inrer, lt_list TYPE STANDARD TABLE OF inriv WITH DEFAULT KEY, lt_error_iv TYPE STANDARD TABLE OF inriv WITH DEFAULT KEY. FIELD-SYMBOLS: LIKE LINE OF lt_list. CALL FUNCTION 'NUMBER_RANGE_INTERVAL_LIST' EXPORTING object = iv_object TABLES interval = lt_list EXCEPTIONS nr_range_nr1_not_found = 1 nr_range_nr1_not_intern = 2 nr_range_nr2_must_be_space = 3 nr_range_nr2_not_extern = 4 nr_range_nr2_not_found = 5 object_not_found = 6 subobject_must_be_space = 7 subobject_not_found = 8 OTHERS = 9. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF lines( lt_list ) = 0. RETURN. ENDIF. LOOP AT lt_list ASSIGNING . CLEAR -nrlevel. -procind = 'D'. ENDLOOP. CALL FUNCTION 'NUMBER_RANGE_INTERVAL_UPDATE' EXPORTING object = iv_object IMPORTING error = ls_error error_occured = lv_error TABLES error_iv = lt_error_iv interval = lt_list EXCEPTIONS object_not_found = 1 OTHERS = 2. IF sy-subrc <> 0 OR lv_error = abap_true. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'NUMBER_RANGE_UPDATE_CLOSE' EXPORTING object = iv_object EXCEPTIONS no_changes_made = 1 object_not_initialized = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_objectid TYPE cdhdr-objectid, lt_cdhdr TYPE cdhdr_tab. FIELD-SYMBOLS: LIKE LINE OF lt_cdhdr. lv_objectid = ms_item-obj_name. CALL FUNCTION 'CHANGEDOCUMENT_READ_HEADERS' EXPORTING objectclass = 'NRKROBJ' objectid = lv_objectid TABLES i_cdhdr = lt_cdhdr EXCEPTIONS no_position_found = 1 wrong_access_to_archive = 2 time_zone_conversion_error = 3 OTHERS = 4. IF sy-subrc <> 0. rv_user = c_user_unknown. RETURN. ENDIF. SORT lt_cdhdr BY udate DESCENDING utime DESCENDING. READ TABLE lt_cdhdr INDEX 1 ASSIGNING . ASSERT sy-subrc = 0. rv_user = -username. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_object TYPE tnro-object. lv_object = ms_item-obj_name. delete_intervals( lv_object ). CALL FUNCTION 'NUMBER_RANGE_OBJECT_DELETE' EXPORTING language = mv_language object = lv_object EXCEPTIONS delete_not_allowed = 1 object_not_found = 2 wrong_indicator = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lt_errors TYPE TABLE OF inoer, ls_attributes TYPE tnro, ls_text TYPE tnrot. FIELD-SYMBOLS TYPE any. io_xml->read( EXPORTING iv_name = 'ATTRIBUTES' CHANGING cg_data = ls_attributes ). io_xml->read( EXPORTING iv_name = 'TEXT' CHANGING cg_data = ls_text ). ASSIGN COMPONENT 'CHANGED_AT' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. GET TIME STAMP FIELD . ENDIF. ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. = sy-uname. ENDIF. ASSIGN COMPONENT 'ENAME' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. = sy-uname. ENDIF. ASSIGN COMPONENT 'EDATE' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. = sy-datum. ENDIF. ASSIGN COMPONENT 'ETIME' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. = sy-uzeit. ENDIF. ASSIGN COMPONENT 'UNAME' OF STRUCTURE ls_text TO . IF sy-subrc = 0. = sy-uname. ENDIF. ASSIGN COMPONENT 'UDATE' OF STRUCTURE ls_text TO . IF sy-subrc = 0. = sy-datum. ENDIF. ASSIGN COMPONENT 'UTIME' OF STRUCTURE ls_text TO . IF sy-subrc = 0. = sy-uzeit. ENDIF. ASSIGN COMPONENT 'ENAME' OF STRUCTURE ls_text TO . IF sy-subrc = 0. = sy-uname. ENDIF. ASSIGN COMPONENT 'EDATE' OF STRUCTURE ls_text TO . IF sy-subrc = 0. = sy-datum. ENDIF. ASSIGN COMPONENT 'ETIME' OF STRUCTURE ls_text TO . IF sy-subrc = 0. = sy-uzeit. ENDIF. CALL FUNCTION 'NUMBER_RANGE_OBJECT_UPDATE' EXPORTING indicator = 'I' object_attributes = ls_attributes object_text = ls_text TABLES errors = lt_errors EXCEPTIONS object_already_exists = 1 object_attributes_missing = 2 object_not_found = 3 object_text_missing = 4 wrong_indicator = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. tadir_insert( iv_package ). corr_insert( iv_package ). CALL FUNCTION 'NUMBER_RANGE_OBJECT_CLOSE' EXPORTING object = ls_attributes-object EXCEPTIONS object_not_initialized = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_object TYPE tnro-object. SELECT SINGLE object FROM tnro INTO lv_object WHERE object = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_bcdata TYPE bdcdata, lt_bcdata TYPE STANDARD TABLE OF bdcdata. ls_bcdata-program = 'SAPMSNRO'. ls_bcdata-dynpro = '0150'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'NRIV-OBJECT'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=DISP'. APPEND ls_bcdata TO lt_bcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SNRO' it_bdcdata = lt_bcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_object TYPE tnro-object, ls_attributes TYPE tnro, ls_text TYPE tnrot. FIELD-SYMBOLS TYPE any. lv_object = ms_item-obj_name. CALL FUNCTION 'NUMBER_RANGE_OBJECT_READ' EXPORTING language = mv_language object = lv_object IMPORTING object_attributes = ls_attributes object_text = ls_text EXCEPTIONS object_not_found = 1 OTHERS = 2. IF sy-subrc = 1. RETURN. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ASSIGN COMPONENT 'CHANGED_AT' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'ENAME' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'EDATE' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'ETIME' OF STRUCTURE ls_attributes TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'UNAME' OF STRUCTURE ls_text TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'UDATE' OF STRUCTURE ls_text TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'UTIME' OF STRUCTURE ls_text TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'ENAME' OF STRUCTURE ls_text TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'EDATE' OF STRUCTURE ls_text TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'ETIME' OF STRUCTURE ls_text TO . IF sy-subrc = 0. CLEAR . ENDIF. io_xml->add( iv_name = 'ATTRIBUTES' ig_data = ls_attributes ). io_xml->add( iv_name = 'TEXT' ig_data = ls_text ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_msag IMPLEMENTATION. METHOD delete_documentation. DATA: lv_key_s TYPE dokhl-object. CLEAR lv_key_s. CALL FUNCTION 'DOCU_OBJECT_NAME_CONCATENATE' EXPORTING docu_id = c_longtext_id_msag element = iv_message_id addition = ' ' IMPORTING object = lv_key_s EXCEPTIONS OTHERS = 0. CALL FUNCTION 'DOKU_DELETE_ALL' EXPORTING doku_id = c_longtext_id_msag doku_object = lv_key_s generic_use = 'X' suppress_authority = space suppress_enqueue = space suppress_transport = space EXCEPTIONS header_without_text = 1 index_without_header = 2 no_authority_for_devclass_xxxx = 3 no_docu_found = 4 object_is_already_enqueued = 5 object_is_enqueued_by_corr = 6 user_break = 7. ENDMETHOD. METHOD delete_msgid. delete_documentation( iv_message_id ). DELETE FROM t100a WHERE arbgb = iv_message_id. IF sy-subrc = 0 OR sy-subrc = 4. CALL FUNCTION 'RS_TREE_OBJECT_PLACEMENT' EXPORTING object = iv_message_id operation = 'DELETE' program = space type = 'CN'. DELETE FROM t100o WHERE arbgb = iv_message_id. DELETE FROM t100t WHERE arbgb = iv_message_id. "#EC CI_NOFIRST DELETE FROM t100u WHERE arbgb = iv_message_id. DELETE FROM t100x WHERE arbgb = iv_message_id. DELETE FROM t100 WHERE arbgb = iv_message_id. ENDIF. ENDMETHOD. METHOD deserialize_texts. DATA: lv_msg_id TYPE rglif-message_id, ls_t100 TYPE t100, lt_t100t TYPE TABLE OF t100t, lt_t100_texts TYPE ty_t100_texts, lt_t100u TYPE TABLE OF t100u. FIELD-SYMBOLS: TYPE ty_t100_text. lv_msg_id = ms_item-obj_name. SELECT * FROM t100u INTO TABLE lt_t100u WHERE arbgb = lv_msg_id ORDER BY PRIMARY KEY. "#EC CI_GENBUFF ii_xml->read( EXPORTING iv_name = 'T100_TEXTS' CHANGING cg_data = lt_t100_texts ). ii_xml->read( EXPORTING iv_name = 'T100T' CHANGING cg_data = lt_t100t ). mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'SPRSL' CHANGING ct_tab = lt_t100_texts ). mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'SPRSL' CHANGING ct_tab = lt_t100t ). MODIFY t100t FROM TABLE lt_t100t. "#EC CI_SUBRC LOOP AT lt_t100_texts ASSIGNING . "check if message exists READ TABLE lt_t100u TRANSPORTING NO FIELDS WITH KEY arbgb = lv_msg_id msgnr = -msgnr BINARY SEARCH. CHECK sy-subrc = 0. "if original message doesn't exist no translations added MOVE-CORRESPONDING TO ls_t100. ls_t100-arbgb = lv_msg_id. MODIFY t100 FROM ls_t100. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'MSAG: Table T100 modify failed' ). ENDIF. ENDLOOP. ENDMETHOD. METHOD free_access_permission. CALL FUNCTION 'RS_ACCESS_PERMISSION' EXPORTING mode = 'FREE' object = iv_message_id object_class = 'T100'. ENDMETHOD. METHOD serialize_longtexts_msag. DATA: lv_doku_object_name TYPE dokhl-object, lt_doku_object_names TYPE STANDARD TABLE OF dokhl-object WITH NON-UNIQUE DEFAULT KEY, lt_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt, ls_dokil LIKE LINE OF lt_dokil, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. FIELD-SYMBOLS: TYPE t100. IF lines( it_t100 ) = 0. RETURN. ENDIF. LOOP AT it_t100 ASSIGNING . lv_doku_object_name = -arbgb && -msgnr. INSERT lv_doku_object_name INTO TABLE lt_doku_object_names. ENDLOOP. IF mo_i18n_params->ms_params-main_language_only = abap_true. SELECT * FROM dokil INTO TABLE lt_dokil FOR ALL ENTRIES IN lt_doku_object_names WHERE id = c_longtext_id_msag AND object = lt_doku_object_names-table_line AND masterlang = abap_true ORDER BY PRIMARY KEY. ELSE. lt_language_filter = mo_i18n_params->build_language_filter( ). SELECT * FROM dokil INTO TABLE lt_dokil FOR ALL ENTRIES IN lt_doku_object_names WHERE id = c_longtext_id_msag AND object = lt_doku_object_names-table_line AND langu IN lt_language_filter ORDER BY PRIMARY KEY. ENDIF. CLEAR ls_dokil-dokstate. MODIFY lt_dokil FROM ls_dokil TRANSPORTING dokstate WHERE dokstate IS NOT INITIAL. IF lines( lt_dokil ) > 0. serialize_longtexts( ii_xml = ii_xml it_dokil = lt_dokil ). ENDIF. ENDMETHOD. METHOD serialize_texts. DATA: lv_msg_id TYPE rglif-message_id, lt_t100_texts TYPE ty_t100_texts, lt_t100t TYPE TABLE OF t100t, lt_i18n_langs TYPE TABLE OF langu, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. lv_msg_id = ms_item-obj_name. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. " skip ENDIF. " Collect additional languages " Skip main lang - it has been already serialized and also technical languages lt_language_filter = mo_i18n_params->build_language_filter( ). SELECT DISTINCT sprsl AS langu INTO TABLE lt_i18n_langs FROM t100t WHERE arbgb = lv_msg_id AND sprsl IN lt_language_filter AND sprsl <> mv_language ORDER BY langu. "#EC CI_BYPASS "#EC CI_GENBUFF SORT lt_i18n_langs ASCENDING. IF lines( lt_i18n_langs ) > 0. SELECT * FROM t100t INTO CORRESPONDING FIELDS OF TABLE lt_t100t WHERE sprsl IN lt_language_filter AND sprsl <> mv_language AND arbgb = lv_msg_id ORDER BY PRIMARY KEY. "#EC CI_GENBUFF SELECT * FROM t100 INTO CORRESPONDING FIELDS OF TABLE lt_t100_texts WHERE sprsl IN lt_language_filter AND sprsl <> mv_language AND arbgb = lv_msg_id ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF SORT lt_t100t BY sprsl ASCENDING. SORT lt_t100_texts BY sprsl msgnr ASCENDING. ii_xml->add( iv_name = 'I18N_LANGS' ig_data = lt_i18n_langs ). ii_xml->add( iv_name = 'T100T' ig_data = lt_t100t ). ii_xml->add( iv_name = 'T100_TEXTS' ig_data = lt_t100_texts ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE lastuser FROM t100a INTO rv_user WHERE arbgb = ms_item-obj_name. "#EC CI_GENBUFF IF sy-subrc <> 0 OR rv_user = ''. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_t100a TYPE t100a, lv_frozen TYPE abap_bool, lv_message_id TYPE arbgb. * parameter SUPPRESS_DIALOG doesn't exist in all versions of FM RS_DELETE_MESSAGE_ID * replaced with a copy lv_message_id = ms_item-obj_name. IF ms_item-obj_name = space. zcx_abapgit_exception=>raise( 'Error from (copy of) RS_DELETE_MESSAGE_ID' )."blank message id ENDIF. SELECT SINGLE * FROM t100a INTO ls_t100a WHERE arbgb = ms_item-obj_name. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error from (copy of) RS_DELETE_MESSAGE_ID' )."not found ENDIF. CLEAR lv_frozen. CALL FUNCTION 'RS_ACCESS_PERMISSION' EXPORTING authority_check = 'X' global_lock = 'X' mode = 'MODIFY' object = lv_message_id object_class = 'T100' IMPORTING frozen = lv_frozen EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0 OR lv_frozen <> space. zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( iv_object = 'MSAG' iv_obj_name = lv_message_id iv_package = iv_package iv_language = mv_language iv_mode = zif_abapgit_cts_api=>c_transport_mode-delete ). delete_msgid( lv_message_id ). free_access_permission( lv_message_id ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. * fm RPY_MESSAGE_ID_INSERT almost works, but not in older versions DATA: ls_t100a TYPE t100a, ls_t100t TYPE t100t, ls_t100u TYPE t100u, lt_t100 TYPE TABLE OF t100, lt_before TYPE TABLE OF t100u. FIELD-SYMBOLS: LIKE LINE OF lt_t100. io_xml->read( EXPORTING iv_name = 'T100A' CHANGING cg_data = ls_t100a ). io_xml->read( EXPORTING iv_name = 'T100' CHANGING cg_data = lt_t100 ). corr_insert( iv_package ). SELECT * FROM t100u INTO TABLE lt_before WHERE arbgb = ls_t100a-arbgb ORDER BY msgnr. "#EC CI_GENBUFF "#EC CI_BYPASS LOOP AT lt_t100 ASSIGNING . DELETE lt_before WHERE msgnr = -msgnr. MODIFY t100 FROM . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'MSAG: Table T100 modify failed' ). ENDIF. CLEAR ls_t100u. MOVE-CORRESPONDING TO ls_t100u ##ENH_OK. ls_t100u-name = sy-uname. ls_t100u-datum = sy-datum. ls_t100u-selfdef = '3'. MODIFY t100u FROM ls_t100u. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'MSAG: Table T100U modify failed' ). ENDIF. ENDLOOP. ls_t100a-masterlang = mv_language. ls_t100a-lastuser = sy-uname. ls_t100a-respuser = sy-uname. ls_t100a-ldate = sy-datum. ls_t100a-ltime = sy-uzeit. MODIFY t100a FROM ls_t100a. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'MSAG: Table T100A modify failed' ). ENDIF. ls_t100t-sprsl = mv_language. ls_t100t-arbgb = ls_t100a-arbgb. ls_t100t-stext = ls_t100a-stext. MODIFY t100t FROM ls_t100t. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'MSAG: Table T100T modify failed' ). ENDIF. LOOP AT lt_before INTO ls_t100u. DELETE FROM t100 WHERE arbgb = ls_t100u-arbgb AND msgnr = ls_t100u-msgnr. "#EC CI_SUBRC DELETE FROM t100u WHERE arbgb = ls_t100u-arbgb AND msgnr = ls_t100u-msgnr. "#EC CI_SUBRC ENDLOOP. deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_msag ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. deserialize_texts( io_xml ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_arbgb TYPE t100a-arbgb. SELECT SINGLE arbgb FROM t100a INTO lv_arbgb WHERE arbgb = ms_item-obj_name. "#EC CI_GENBUFF rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_argument TYPE seqg3-garg. lv_argument = |{ ms_item-obj_name }|. OVERLAY lv_argument WITH ' '. lv_argument = lv_argument && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = |ES_MSGSI| iv_argument = lv_argument ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_msg_id TYPE rglif-message_id, ls_inf TYPE t100a, lt_source TYPE ty_t100s. lv_msg_id = ms_item-obj_name. SELECT SINGLE * FROM t100a INTO ls_inf WHERE arbgb = lv_msg_id. "#EC CI_GENBUFF IF sy-subrc <> 0. RETURN. ENDIF. CLEAR ls_inf-respuser. SELECT * FROM t100 INTO TABLE lt_source WHERE sprsl = mv_language AND arbgb = lv_msg_id ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF CLEAR: ls_inf-lastuser, ls_inf-ldate, ls_inf-ltime. io_xml->add( iv_name = 'T100A' ig_data = ls_inf ). io_xml->add( ig_data = lt_source iv_name = 'T100' ). serialize_longtexts_msag( it_t100 = lt_source ii_xml = io_xml ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. serialize_texts( io_xml ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_jobd IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lr_job_definition TYPE REF TO data, lo_job_definition TYPE REF TO object, lv_name TYPE ty_jd_name. FIELD-SYMBOLS: TYPE any, TYPE any. lv_name = ms_item-obj_name. TRY. CREATE DATA lr_job_definition TYPE ('CL_JR_JOB_DEFINITION=>TY_JOB_DEFINITION'). ASSIGN lr_job_definition->* TO . ASSERT sy-subrc = 0. CREATE OBJECT lo_job_definition TYPE ('CL_JR_JOB_DEFINITION') EXPORTING im_jd_name = lv_name. CALL METHOD lo_job_definition->('GET_JD_ATTRIBUTES') IMPORTING ex_jd_attributes = . ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . IF sy-subrc = 0. rv_user = . ENDIF. CATCH cx_root ##NO_HANDLER. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_job_definition TYPE REF TO object, lv_name TYPE c LENGTH 32. lv_name = ms_item-obj_name. TRY. CREATE OBJECT lo_job_definition TYPE ('CL_JR_JOB_DEFINITION') EXPORTING im_jd_name = lv_name. CALL METHOD lo_job_definition->('DELETE_JD'). CATCH cx_root. zcx_abapgit_exception=>raise( |Error deleting JOBD| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lr_job_definition TYPE REF TO data, lo_job_definition TYPE REF TO object, lv_name TYPE ty_jd_name. FIELD-SYMBOLS: TYPE any, TYPE any. lv_name = ms_item-obj_name. TRY. CREATE DATA lr_job_definition TYPE ('CL_JR_JOB_DEFINITION=>TY_JOB_DEFINITION'). ASSIGN lr_job_definition->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'JOBD' CHANGING cg_data = ). CREATE OBJECT lo_job_definition TYPE ('CL_JR_JOB_DEFINITION') EXPORTING im_jd_name = lv_name. ASSIGN COMPONENT 'JDPACKAGE' OF STRUCTURE TO . = iv_package. CALL METHOD lo_job_definition->('CREATE_JD') EXPORTING im_jd_attributes = . CATCH cx_root. zcx_abapgit_exception=>raise( |Error deserializing JOBD| ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_name TYPE ty_jd_name. lv_name = ms_item-obj_name. TRY. CALL METHOD ('CL_JR_JD_MANAGER')=>('CHECK_JD_EXISTENCE') EXPORTING im_jd_name = lv_name IMPORTING ex_is_existing = rv_bool. CATCH cx_root. zcx_abapgit_exception=>raise( |JOBD not supported| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lv_obj_name TYPE e071-obj_name. lv_obj_name = ms_item-obj_name. CALL FUNCTION 'TR_OBJECT_JUMP_TO_TOOL' EXPORTING iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = lv_obj_name iv_action = 'SHOW' EXCEPTIONS jump_not_possible = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lr_job_definition TYPE REF TO data, lo_job_definition TYPE REF TO object, lv_name TYPE ty_jd_name. FIELD-SYMBOLS: TYPE any, TYPE any. lv_name = ms_item-obj_name. TRY. CREATE DATA lr_job_definition TYPE ('CL_JR_JOB_DEFINITION=>TY_JOB_DEFINITION'). ASSIGN lr_job_definition->* TO . ASSERT sy-subrc = 0. CREATE OBJECT lo_job_definition TYPE ('CL_JR_JOB_DEFINITION') EXPORTING im_jd_name = lv_name. CALL METHOD lo_job_definition->('GET_JD_ATTRIBUTES') IMPORTING ex_jd_attributes = . ASSIGN COMPONENT 'JDPACKAGE' OF STRUCTURE TO . CLEAR . ASSIGN COMPONENT 'BTCJOB_USER' OF STRUCTURE TO . CLEAR . ASSIGN COMPONENT 'OWNER' OF STRUCTURE TO . CLEAR . ASSIGN COMPONENT 'CREATED_DATE' OF STRUCTURE TO . CLEAR . ASSIGN COMPONENT 'CREATED_TIME' OF STRUCTURE TO . CLEAR . ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . CLEAR . ASSIGN COMPONENT 'CHANGED_DATE' OF STRUCTURE TO . CLEAR . ASSIGN COMPONENT 'CHANGED_TIME' OF STRUCTURE TO . CLEAR . io_xml->add( iv_name = 'JOBD' ig_data = ). CATCH cx_root. zcx_abapgit_exception=>raise( |Error serializing JOBD| ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iwvb IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). ro_result->add( iv_table = '/IWBEP/I_MGW_VAH' iv_field = 'CREATED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_MGW_VAH' iv_field = 'CREATED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_MGW_VAH' iv_field = 'CHANGED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_MGW_VAH' iv_field = 'CHANGED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lv_created TYPE sy-uname. DATA lv_changed TYPE sy-uname. " Get entry with highest version SELECT created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_MGW_VAH') WHERE technical_name = ms_item-obj_name ORDER BY PRIMARY KEY. rv_user = lv_changed. IF lv_changed IS INITIAL. rv_user = lv_created. ENDIF. ENDSELECT. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. SUBMIT /iwbep/r_dst_vocan_register WITH ip_aname = ms_item-obj_name WITH ip_avers = ms_item-obj_name+32(4) AND RETURN. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iwsv IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). ro_result->add( iv_table = '/IWBEP/I_MGW_SRH' iv_field = 'CREATED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_MGW_SRH' iv_field = 'CREATED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_MGW_SRH' iv_field = 'CHANGED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_MGW_SRH' iv_field = 'CHANGED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lv_created TYPE sy-uname. DATA lv_changed TYPE sy-uname. " Get entry with highest version SELECT created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_MGW_SRH') WHERE technical_name = ms_item-obj_name ORDER BY PRIMARY KEY. rv_user = lv_changed. IF lv_changed IS INITIAL. rv_user = lv_created. ENDIF. ENDSELECT. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lv_technical_name TYPE c LENGTH 35, lv_version TYPE bdc_fval, lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. lv_technical_name = ms_item-obj_name(36). lv_version = ms_item-obj_name+36(4). APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = '/IWBEP/R_DST_SERVICE_BUILDER'. -dynpro = '0100'. -dynbegin = 'X'. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'GS_SCREEN_100-TECHNICAL_NAME'. -fval = lv_technical_name. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'GS_SCREEN_100-VERSION'. -fval = lv_version. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = '/IWBEP/REG_SERVICE' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iwsg IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). ro_result->add( iv_table = '/IWFND/I_MED_SRH' iv_field = 'CREATED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWFND/I_MED_SRH' iv_field = 'CREATED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWFND/I_MED_SRH' iv_field = 'CHANGED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWFND/I_MED_SRH' iv_field = 'CHANGED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changed_by FROM ('/IWFND/I_MED_SRH') INTO rv_user WHERE srv_identifier = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iwpr IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). ro_result->add( iv_table = '/IWBEP/I_SBD_GA' iv_field = 'CREATION_USER_ID' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_SBD_GA' iv_field = 'CREATION_TIME' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_SBD_GA' iv_field = 'LAST_CHG_USER_ID' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_SBD_GA' iv_field = 'LAST_CHG_TIME' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE last_chg_user_id FROM ('/IWBEP/I_SBD_PR') INTO rv_user WHERE project = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. SUBMIT /iwbep/r_sbui_service_builder WITH i_prname = ms_item-obj_name AND RETURN. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iwom IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). ro_result->add( iv_table = '/IWFND/I_MED_OHD' iv_field = 'CREATED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWFND/I_MED_OHD' iv_field = 'CREATED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWFND/I_MED_OHD' iv_field = 'CHANGED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWFND/I_MED_OHD' iv_field = 'CHANGED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changed_by FROM ('/IWFND/I_MED_OHD') INTO rv_user WHERE model_identifier = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iwmo IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). ro_result->add( iv_table = '/IWBEP/I_MGW_OHD' iv_field = 'CREATED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_MGW_OHD' iv_field = 'CREATED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_MGW_OHD' iv_field = 'CHANGED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_MGW_OHD' iv_field = 'CHANGED_TIMESTMP' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lv_created TYPE sy-uname. DATA lv_changed TYPE sy-uname. " Get entry with highest version SELECT created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_MGW_OHD') WHERE technical_name = ms_item-obj_name ORDER BY PRIMARY KEY. rv_user = lv_changed. IF lv_changed IS INITIAL. rv_user = lv_created. ENDIF. ENDSELECT. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lv_mdl_technical_name TYPE c LENGTH 32, lv_version TYPE bdc_fval, lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. lv_mdl_technical_name = ms_item-obj_name. lv_version = ms_item-obj_name+32(4). APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = '/IWBEP/R_DST_MODEL_BUILDER'. -dynpro = '0100'. -dynbegin = 'X'. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'GS_MODEL_SCREEN_100-TECHNICAL_NAME'. -fval = lv_mdl_technical_name. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'GS_MODEL_SCREEN_100-VERSION'. -fval = lv_version. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = '/IWBEP/REG_MODEL' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iobj IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cg_metadata TO . ASSERT sy-subrc = 0. CLEAR: . ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_objna TYPE c LENGTH 30, lr_viobj TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any. lv_objna = ms_item-obj_name. TRY. CREATE DATA lr_viobj TYPE ('RSD_S_VIOBJ'). CATCH cx_sy_create_data_error. zcx_abapgit_exception=>raise( |IOBJ is not supported on this system| ). ENDTRY. ASSIGN lr_viobj->* TO . CALL FUNCTION 'RSD_IOBJ_GET' EXPORTING i_iobjnm = lv_objna i_objvers = 'A' IMPORTING e_s_viobj = EXCEPTIONS iobj_not_found = 1 illegal_input = 2 bct_comp_invalid = 3 not_authorized = 4 OTHERS = 5. IF sy-subrc = 0. ASSIGN COMPONENT 'TSTPNM' OF STRUCTURE TO . rv_user = . ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. TYPES: BEGIN OF ty_iobj, objnm TYPE c LENGTH 30. TYPES END OF ty_iobj. DATA: lt_iobjname TYPE STANDARD TABLE OF ty_iobj, lv_subrc TYPE sy-subrc. APPEND ms_item-obj_name TO lt_iobjname. CALL FUNCTION 'RSDG_IOBJ_MULTI_DELETE' EXPORTING i_t_iobjnm = lt_iobjname i_check_dependent = abap_false i_manual = abap_false IMPORTING e_subrc = lv_subrc. IF lv_subrc <> 0. zcx_abapgit_exception=>raise( |Error when deleting InfoObject { ms_item-obj_name }| ). ENDIF. corr_insert( iv_package ). TRY. " In case of IOBJ dependencies, tadir entry might be leftover so we remove it tadir_delete( ). CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lr_details TYPE REF TO data, lr_infoobj TYPE REF TO data, ls_return TYPE bapiret2, lt_return TYPE STANDARD TABLE OF bapiret2, lr_compounds TYPE REF TO data, lr_attributes TYPE REF TO data, lr_navigationattributes TYPE REF TO data, lr_atrnavinfoprovider TYPE REF TO data, lr_hierarchycharacteristics TYPE REF TO data, lr_elimination TYPE REF TO data, lr_hanafieldsmapping TYPE REF TO data, lr_xxlattributes TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE data, TYPE STANDARD TABLE. TRY. CREATE DATA lr_details TYPE ('BAPI6108'). CREATE DATA lr_compounds TYPE STANDARD TABLE OF ('BAPI6108CM'). CREATE DATA lr_attributes TYPE STANDARD TABLE OF ('BAPI6108AT'). CREATE DATA lr_navigationattributes TYPE STANDARD TABLE OF ('BAPI6108AN'). CREATE DATA lr_atrnavinfoprovider TYPE STANDARD TABLE OF ('BAPI6108NP'). CREATE DATA lr_hierarchycharacteristics TYPE STANDARD TABLE OF ('BAPI6108HC'). CREATE DATA lr_elimination TYPE STANDARD TABLE OF ('BAPI6108IE'). CREATE DATA lr_hanafieldsmapping TYPE STANDARD TABLE OF ('BAPI6108HANA_MAP'). CREATE DATA lr_xxlattributes TYPE STANDARD TABLE OF ('BAPI6108ATXXL'). CREATE DATA lr_infoobj TYPE STANDARD TABLE OF ('BAPI6108'). CATCH cx_sy_create_data_error. zcx_abapgit_exception=>raise( |IOBJ is not supported on this system| ). ENDTRY. ASSIGN lr_details->* TO . ASSIGN lr_compounds->* TO . ASSIGN lr_attributes->* TO . ASSIGN lr_navigationattributes->* TO . ASSIGN lr_atrnavinfoprovider->* TO . ASSIGN lr_hierarchycharacteristics->* TO . ASSIGN lr_elimination->* TO . ASSIGN lr_hanafieldsmapping->* TO . ASSIGN lr_xxlattributes->* TO . ASSIGN lr_infoobj->* TO . io_xml->read( EXPORTING iv_name = 'IOBJ' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'COMPOUNDS' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'ATTRIBUTES' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'NAVIGATION_ATTRIBUTES' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'ATTR_NAVIGATION' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'HIERARCHY' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'ELIMINATION' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'HANA_FIELDS_MAPPING' CHANGING cg_data = ). io_xml->read( EXPORTING iv_name = 'XXL_ATTRIBUTES' CHANGING cg_data = ). " Number ranges are local (should not have been serialized) clear_field( EXPORTING iv_fieldname = 'NUMBRANR' CHANGING cg_metadata = ). TRY. ASSIGN COMPONENT 'INFOOBJECT' OF STRUCTURE TO . ASSERT sy-subrc = 0. IF zif_abapgit_object~exists( ) = abap_false. CALL FUNCTION 'BAPI_IOBJ_CREATE' EXPORTING details = IMPORTING return = ls_return TABLES compounds = attributes = navigationattributes = atrnavinfoprovider = hierarchycharacteristics = elimination = hanafieldsmapping = xxlattributes = . ELSE. CALL FUNCTION 'BAPI_IOBJ_CHANGE' EXPORTING infoobject = details = IMPORTING return = ls_return TABLES compounds = attributes = navigationattributes = atrnavinfoprovider = hierarchycharacteristics = elimination = hanafieldsmapping = xxlattributes = . ENDIF. IF ls_return-type = 'E'. zcx_abapgit_exception=>raise( |Error when creating iobj: { ls_return-message }| ). ENDIF. APPEND TO . CALL FUNCTION 'BAPI_IOBJ_ACTIVATE_MULTIPLE' TABLES infoobjects = return = lt_return. READ TABLE lt_return WITH KEY type = 'E' INTO ls_return. IF sy-subrc = 0. zcx_abapgit_exception=>raise( |Error when activating iobj: { ls_return-message }| ). ENDIF. CATCH cx_sy_dyn_call_illegal_func. zcx_abapgit_exception=>raise( |Necessary BW function modules not found| ). ENDTRY. tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_iobjnm TYPE c LENGTH 30. SELECT SINGLE iobjnm FROM ('RSDIOBJ') INTO lv_iobjnm WHERE iobjnm = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. DATA: lv_objna TYPE c LENGTH 30, lr_viobj TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any. lv_objna = ms_item-obj_name. TRY. CREATE DATA lr_viobj TYPE ('RSD_S_VIOBJ'). CATCH cx_sy_create_data_error. zcx_abapgit_exception=>raise( |IOBJ is not supported on this system| ). ENDTRY. ASSIGN lr_viobj->* TO . CALL FUNCTION 'RSD_IOBJ_GET' EXPORTING i_iobjnm = lv_objna i_objvers = 'A' IMPORTING e_s_viobj = . ASSIGN COMPONENT 'OBJSTAT' OF STRUCTURE TO . IF = 'ACT' AND sy-subrc = 0. rv_active = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_object TYPE eqegraarg. lv_object = ms_item-obj_name. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_BIW_PROV' iv_argument = lv_object ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_iobjnam TYPE rsiobjnm, ls_return TYPE bapiret2, lr_details TYPE REF TO data, lr_compounds TYPE REF TO data, lr_attributes TYPE REF TO data, lr_navigationattributes TYPE REF TO data, lr_atrnavinfoprovider TYPE REF TO data, lr_hierarchycharacteristics TYPE REF TO data, lr_elimination TYPE REF TO data, lr_hanafieldsmapping TYPE REF TO data, lr_xxlattributes TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE, TYPE STANDARD TABLE. TRY. CREATE DATA lr_details TYPE ('BAPI6108'). CREATE DATA lr_compounds TYPE STANDARD TABLE OF ('BAPI6108CM'). CREATE DATA lr_attributes TYPE STANDARD TABLE OF ('BAPI6108AT'). CREATE DATA lr_navigationattributes TYPE STANDARD TABLE OF ('BAPI6108AN'). CREATE DATA lr_atrnavinfoprovider TYPE STANDARD TABLE OF ('BAPI6108NP'). CREATE DATA lr_hierarchycharacteristics TYPE STANDARD TABLE OF ('BAPI6108HC'). CREATE DATA lr_elimination TYPE STANDARD TABLE OF ('BAPI6108IE'). CREATE DATA lr_hanafieldsmapping TYPE STANDARD TABLE OF ('BAPI6108HANA_MAP'). CREATE DATA lr_xxlattributes TYPE STANDARD TABLE OF ('BAPI6108ATXXL'). CATCH cx_sy_create_data_error. zcx_abapgit_exception=>raise( |IOBJ is not supported on this system| ). ENDTRY. ASSIGN lr_details->* TO . ASSIGN lr_compounds->* TO . ASSIGN lr_attributes->* TO . ASSIGN lr_navigationattributes->* TO . ASSIGN lr_atrnavinfoprovider->* TO . ASSIGN lr_hierarchycharacteristics->* TO . ASSIGN lr_elimination->* TO . ASSIGN lr_hanafieldsmapping->* TO . ASSIGN lr_xxlattributes->* TO . lv_iobjnam = ms_item-obj_name. CALL FUNCTION 'BAPI_IOBJ_GETDETAIL' EXPORTING infoobject = lv_iobjnam IMPORTING details = return = ls_return TABLES compounds = attributes = navigationattributes = atrnavinfoprovider = hierarchycharacteristics = elimination = hanafieldsmapping = xxlattributes = . IF ls_return-type = 'E'. zcx_abapgit_exception=>raise( |Error getting details of InfoObject: { ls_return-message }| ). ENDIF. clear_field( EXPORTING iv_fieldname = 'TSTPNM' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'TIMESTMP' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'DBROUTID' CHANGING cg_metadata = ). " Number ranges are local clear_field( EXPORTING iv_fieldname = 'NUMBRANR' CHANGING cg_metadata = ). io_xml->add( iv_name = 'IOBJ' ig_data = ). io_xml->add( iv_name = 'COMPOUNDS' ig_data = ). io_xml->add( iv_name = 'ATTRIBUTES' ig_data = ). io_xml->add( iv_name = 'NAVIGATION_ATTRIBUTES' ig_data = ). io_xml->add( iv_name = 'ATTR_NAVIGATION' ig_data = ). io_xml->add( iv_name = 'HIERARCHY' ig_data = ). io_xml->add( iv_name = 'ELIMINATION' ig_data = ). io_xml->add( iv_name = 'HANA_FIELDS_MAPPING' ig_data = ). io_xml->add( iv_name = 'XXL_ATTRIBUTES' ig_data = ). ENDMETHOD. ENDCLASS. CLASS kHGwlUKtFBXjILcBRBJOrsxFJiznPf DEFINITION DEFERRED. CLASS kHGwlUKtFBXjILcBRBJOvDDGtKNvAd DEFINITION DEFERRED. CLASS kHGwlUKtFBXjILcBRBJOnvUCODLJDd DEFINITION DEFERRED. * renamed: zcl_abapgit_object_intf :: lcl_aff_helper CLASS kHGwlUKtFBXjILcBRBJOnvUCODLJDd DEFINITION. PUBLIC SECTION. CLASS-METHODS: get_descriptions_compo_subco IMPORTING iv_language TYPE sy-langu iv_clif_name TYPE seoclsname RETURNING VALUE(rs_properties) TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions , get_descr_comp_subc_w_exposure IMPORTING iv_language TYPE sy-langu iv_clif_name TYPE seoclsname iv_exposure TYPE seoexpose DEFAULT seoc_exposure_public RETURNING VALUE(rs_properties) TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions , set_descriptions_compo_subco IMPORTING iv_clif_name TYPE seoclsname iv_language TYPE langu is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions . PRIVATE SECTION. TYPES: BEGIN OF ty_component, visibility TYPE seoexpose, cmpname TYPE seocmpname, descript TYPE seodescr, cmptype TYPE seocmptype, END OF ty_component, BEGIN OF ty_sub_component, cmpname TYPE seocmpname, sconame TYPE seosconame, descript TYPE seodescr, scotype TYPE seoscotype, END OF ty_sub_component, ty_compontents TYPE SORTED TABLE OF ty_component WITH UNIQUE DEFAULT KEY, ty_sub_compontents TYPE SORTED TABLE OF ty_sub_component WITH UNIQUE DEFAULT KEY. CLASS-METHODS: get_attributes IMPORTING is_components TYPE ty_compontents RETURNING VALUE(rs_result) TYPE zif_abapgit_aff_oo_types_v1=>ty_component_descriptions, get_methods IMPORTING is_components TYPE ty_compontents is_sub_components TYPE ty_sub_compontents RETURNING VALUE(rs_result) TYPE zif_abapgit_aff_oo_types_v1=>ty_methods, get_types IMPORTING is_components TYPE ty_compontents RETURNING VALUE(rs_result) TYPE zif_abapgit_aff_oo_types_v1=>ty_component_descriptions, get_events IMPORTING is_components TYPE ty_compontents is_sub_components TYPE ty_sub_compontents RETURNING VALUE(rs_result) TYPE zif_abapgit_aff_oo_types_v1=>ty_events, set_methods IMPORTING iv_clif_name TYPE seoclsname iv_language TYPE langu is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions, set_attributes IMPORTING iv_clif_name TYPE seoclsname iv_language TYPE langu is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions, set_events IMPORTING iv_clif_name TYPE seoclsname iv_language TYPE langu is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions, set_types IMPORTING iv_clif_name TYPE seoclsname iv_language TYPE langu is_properties TYPE zif_abapgit_aff_oo_types_v1=>ty_descriptions . ENDCLASS. CLASS kHGwlUKtFBXjILcBRBJOnvUCODLJDd IMPLEMENTATION. METHOD get_descr_comp_subc_w_exposure. DATA: lt_components TYPE ty_compontents, lt_sub_components TYPE ty_sub_compontents. SELECT df~exposure AS visibility component~cmpname component_text~descript component~cmptype INTO TABLE lt_components FROM seocompo AS component LEFT OUTER JOIN seocompotx AS component_text ON component~cmpname = component_text~cmpname AND component~clsname = component_text~clsname AND component_text~langu = iv_language INNER JOIN seocompodf AS df ON component~clsname = df~clsname AND component~cmpname = df~cmpname WHERE component~clsname = iv_clif_name AND df~exposure = iv_exposure. "#EC CI_BUFFJOIN SELECT sub_component~cmpname sub_component~sconame sub_component_text~descript sub_component~scotype INTO TABLE lt_sub_components FROM seosubco AS sub_component JOIN seosubcotx AS sub_component_text ON sub_component~clsname = sub_component_text~clsname AND sub_component~cmpname = sub_component_text~cmpname AND sub_component~sconame = sub_component_text~sconame INNER JOIN seocompodf AS df ON sub_component~clsname = df~clsname AND sub_component~cmpname = df~cmpname WHERE sub_component~clsname = iv_clif_name AND df~exposure = iv_exposure AND sub_component_text~langu = iv_language AND sub_component_text~descript <> space. "#EC CI_BUFFJOIN rs_properties-attributes = get_attributes( lt_components ). rs_properties-methods = get_methods( is_components = lt_components is_sub_components = lt_sub_components ). rs_properties-events = get_events( is_components = lt_components is_sub_components = lt_sub_components ). rs_properties-types = get_types( lt_components ). ENDMETHOD. METHOD get_descriptions_compo_subco. TYPES: BEGIN OF ty_helper_type, cmpname TYPE seocmpname, descript TYPE seodescr, cmptype TYPE seocmptype, END OF ty_helper_type. DATA: lt_components TYPE STANDARD TABLE OF ty_helper_type, lt_sub_components TYPE ty_sub_compontents, lt_components_exp TYPE ty_compontents, ls_component_exp LIKE LINE OF lt_components_exp. FIELD-SYMBOLS: LIKE LINE OF lt_components. SELECT component~cmpname component_text~descript component~cmptype INTO TABLE lt_components FROM seocompo AS component LEFT OUTER JOIN seocompotx AS component_text ON component~cmpname = component_text~cmpname AND component~clsname = component_text~clsname AND component_text~langu = iv_language WHERE component~clsname = iv_clif_name ORDER BY component~cmpname. "#EC CI_BUFFJOIN SELECT sub_component~cmpname sub_component~sconame sub_component_text~descript sub_component~scotype INTO TABLE lt_sub_components FROM seosubco AS sub_component JOIN seosubcotx AS sub_component_text ON sub_component~clsname = sub_component_text~clsname AND sub_component~cmpname = sub_component_text~cmpname AND sub_component~sconame = sub_component_text~sconame WHERE sub_component~clsname = iv_clif_name AND sub_component_text~langu = iv_language AND sub_component_text~descript <> space. "#EC CI_BUFFJOIN LOOP AT lt_components ASSIGNING . CLEAR ls_component_exp. MOVE-CORRESPONDING TO ls_component_exp. INSERT ls_component_exp INTO TABLE lt_components_exp. ENDLOOP. rs_properties-attributes = get_attributes( lt_components_exp ). rs_properties-methods = get_methods( is_components = lt_components_exp is_sub_components = lt_sub_components ). rs_properties-events = get_events( is_components = lt_components_exp is_sub_components = lt_sub_components ). rs_properties-types = get_types( lt_components_exp ). ENDMETHOD. METHOD get_attributes. DATA: lo_component TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. FIELD-SYMBOLS TYPE ty_component. LOOP AT is_components ASSIGNING WHERE cmptype = seoo_cmptype_attribute AND descript IS NOT INITIAL. lo_component-name = -cmpname. lo_component-description = -descript. INSERT lo_component INTO TABLE rs_result. ENDLOOP. ENDMETHOD. METHOD get_methods. DATA: lo_method TYPE zif_abapgit_aff_oo_types_v1=>ty_method, lo_exception TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description, lo_parameter TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. FIELD-SYMBOLS TYPE ty_sub_component. FIELD-SYMBOLS TYPE ty_component. LOOP AT is_components ASSIGNING WHERE cmptype = seoo_cmptype_method. lo_method-name = -cmpname. lo_method-description = -descript. LOOP AT is_sub_components ASSIGNING WHERE cmpname = -cmpname. CASE -scotype. WHEN seos_scotype_parameter. lo_parameter-name = -sconame. lo_parameter-description = -descript. INSERT lo_parameter INTO TABLE lo_method-parameters. WHEN seos_scotype_exception. lo_exception-name = -sconame. lo_exception-description = -descript. INSERT lo_exception INTO TABLE lo_method-exceptions. ENDCASE. ENDLOOP. IF lo_method-description IS NOT INITIAL OR lo_method-exceptions IS NOT INITIAL OR lo_method-parameters IS NOT INITIAL. INSERT lo_method INTO TABLE rs_result. ENDIF. ENDLOOP. ENDMETHOD. METHOD get_types. DATA: lo_type TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. FIELD-SYMBOLS: TYPE ty_component. LOOP AT is_components ASSIGNING WHERE cmptype = seoo_cmptype_type AND descript IS NOT INITIAL. lo_type-name = -cmpname. lo_type-description = -descript. INSERT lo_type INTO TABLE rs_result. ENDLOOP. ENDMETHOD. METHOD get_events. DATA: lo_parameter TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description, lo_event TYPE zif_abapgit_aff_oo_types_v1=>ty_event. FIELD-SYMBOLS TYPE ty_component. FIELD-SYMBOLS TYPE ty_sub_component. LOOP AT is_components ASSIGNING WHERE cmptype = seoo_cmptype_event. lo_event-name = -cmpname. lo_event-description = -descript. LOOP AT is_sub_components ASSIGNING WHERE cmpname = -cmpname. lo_parameter-name = -sconame. lo_parameter-description = -descript. INSERT lo_parameter INTO TABLE lo_event-parameters. ENDLOOP. IF lo_event-description IS NOT INITIAL OR lo_event-parameters IS NOT INITIAL. INSERT lo_event INTO TABLE rs_result. ENDIF. ENDLOOP. ENDMETHOD. METHOD set_attributes. DATA: lo_attribute TYPE seocompotx. FIELD-SYMBOLS: TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. LOOP AT is_properties-attributes ASSIGNING . lo_attribute-clsname = iv_clif_name. lo_attribute-cmpname = -name. lo_attribute-langu = iv_language. lo_attribute-descript = -description. MODIFY seocompotx FROM lo_attribute. ENDLOOP. ENDMETHOD. METHOD set_methods. DATA: lo_method TYPE seocompotx, lo_method_exception TYPE seosubcotx, lo_method_parameter TYPE seosubcotx. FIELD-SYMBOLS: TYPE zif_abapgit_aff_oo_types_v1=>ty_method, TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description, TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. LOOP AT is_properties-methods ASSIGNING . lo_method-clsname = iv_clif_name. lo_method-cmpname = -name. lo_method-langu = iv_language. lo_method-descript = -description. MODIFY seocompotx FROM lo_method. LOOP AT -parameters ASSIGNING . lo_method_parameter-clsname = iv_clif_name. lo_method_parameter-cmpname = -name. lo_method_parameter-sconame = -name. lo_method_parameter-langu = iv_language. lo_method_parameter-descript = -description. MODIFY seosubcotx FROM lo_method_parameter. ENDLOOP. LOOP AT -exceptions ASSIGNING . lo_method_exception-clsname = iv_clif_name. lo_method_exception-cmpname = -name. lo_method_exception-sconame = -name. lo_method_exception-langu = iv_language. lo_method_exception-descript = -description. MODIFY seosubcotx FROM lo_method_exception. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD set_events. DATA: lo_event_parameter TYPE seosubcotx, lo_event TYPE seocompotx. FIELD-SYMBOLS: TYPE zif_abapgit_aff_oo_types_v1=>ty_event, TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. LOOP AT is_properties-events ASSIGNING . lo_event-clsname = iv_clif_name. lo_event-cmpname = -name. lo_event-langu = iv_language. lo_event-descript = -description. MODIFY seocompotx FROM lo_event. LOOP AT -parameters ASSIGNING . lo_event_parameter-clsname = iv_clif_name. lo_event_parameter-cmpname = -name. lo_event_parameter-sconame = -name. lo_event_parameter-langu = iv_language. lo_event_parameter-descript = -description. MODIFY seosubcotx FROM lo_event_parameter. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD set_types. DATA: lo_type TYPE seocompotx. FIELD-SYMBOLS: TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. LOOP AT is_properties-types ASSIGNING . lo_type-clsname = iv_clif_name. lo_type-cmpname = -name. lo_type-langu = iv_language. lo_type-descript = -description. MODIFY seocompotx FROM lo_type. ENDLOOP. ENDMETHOD. METHOD set_descriptions_compo_subco. set_attributes( is_properties = is_properties iv_clif_name = iv_clif_name iv_language = iv_language ). set_methods( is_properties = is_properties iv_clif_name = iv_clif_name iv_language = iv_language ). set_events( is_properties = is_properties iv_clif_name = iv_clif_name iv_language = iv_language ). set_types( is_properties = is_properties iv_clif_name = iv_clif_name iv_language = iv_language ). ENDMETHOD. ENDCLASS. * renamed: zcl_abapgit_object_intf :: lcl_aff_type_mapping CLASS kHGwlUKtFBXjILcBRBJOvDDGtKNvAd DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_aff_type_mapping. PRIVATE SECTION. METHODS set_abapgit_descriptions IMPORTING is_clsname TYPE seoclsname is_intf_aff TYPE zif_abapgit_aff_intf_v1=>ty_main EXPORTING et_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt et_descriptions_sub TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt. ENDCLASS. CLASS kHGwlUKtFBXjILcBRBJOvDDGtKNvAd IMPLEMENTATION. METHOD zif_abapgit_aff_type_mapping~to_aff. DATA: ls_data_abapgit TYPE zcl_abapgit_object_intf=>ty_intf, ls_data_aff TYPE zif_abapgit_aff_intf_v1=>ty_main. ls_data_abapgit = iv_data. ls_data_aff-format_version = '1'. " get header ls_data_aff-header-description = ls_data_abapgit-vseointerf-descript. ls_data_aff-header-abap_language_version = ls_data_abapgit-vseointerf-unicode. ls_data_aff-header-original_language = ls_data_abapgit-vseointerf-langu. " get category and proxy ls_data_aff-category = ls_data_abapgit-vseointerf-category. ls_data_aff-proxy = ls_data_abapgit-vseointerf-clsproxy. " get descriptions ls_data_aff-descriptions = kHGwlUKtFBXjILcBRBJOnvUCODLJDd=>get_descriptions_compo_subco( iv_language = ls_data_aff-header-original_language iv_clif_name = ls_data_abapgit-vseointerf-clsname ). es_data = ls_data_aff. ENDMETHOD. METHOD zif_abapgit_aff_type_mapping~to_abapgit. DATA: ls_data_abapgit TYPE zcl_abapgit_object_intf=>ty_intf, ls_data_aff TYPE zif_abapgit_aff_intf_v1=>ty_main, lv_classname TYPE seoclsname. ls_data_aff = iv_data. lv_classname = to_upper( iv_object_name ). set_abapgit_descriptions( EXPORTING is_clsname = lv_classname is_intf_aff = ls_data_aff IMPORTING et_descriptions = ls_data_abapgit-description et_descriptions_sub = ls_data_abapgit-description_sub ). ls_data_abapgit-vseointerf-clsname = lv_classname. ls_data_abapgit-vseointerf-descript = ls_data_aff-header-description. ls_data_abapgit-vseointerf-category = ls_data_aff-category. ls_data_abapgit-vseointerf-unicode = ls_data_aff-header-abap_language_version. ls_data_abapgit-vseointerf-langu = ls_data_aff-header-original_language. ls_data_abapgit-vseointerf-clsproxy = ls_data_aff-proxy. ls_data_abapgit-vseointerf-exposure = seoc_exposure_public. ls_data_abapgit-vseointerf-state = seoc_state_implemented. es_data = ls_data_abapgit. ENDMETHOD. METHOD set_abapgit_descriptions. DATA ls_description TYPE seocompotx. DATA ls_description_subco TYPE seosubcotx. FIELD-SYMBOLS TYPE zif_abapgit_aff_oo_types_v1=>ty_component_description. FIELD-SYMBOLS TYPE zif_abapgit_aff_oo_types_v1=>ty_method. FIELD-SYMBOLS TYPE zif_abapgit_aff_oo_types_v1=>ty_event. LOOP AT is_intf_aff-descriptions-types ASSIGNING . ls_description-clsname = is_clsname. ls_description-cmpname = -name. ls_description-langu = is_intf_aff-header-original_language. ls_description-descript = -description. APPEND ls_description TO et_descriptions. ENDLOOP. LOOP AT is_intf_aff-descriptions-attributes ASSIGNING . ls_description-clsname = is_clsname. ls_description-cmpname = -name. ls_description-langu = is_intf_aff-header-original_language. ls_description-descript = -description. APPEND ls_description TO et_descriptions. ENDLOOP. LOOP AT is_intf_aff-descriptions-methods ASSIGNING . ls_description-clsname = is_clsname. ls_description-cmpname = -name. ls_description-langu = is_intf_aff-header-original_language. ls_description-descript = -description. APPEND ls_description TO et_descriptions. LOOP AT -parameters ASSIGNING . ls_description_subco-clsname = ls_description-clsname. ls_description_subco-cmpname = ls_description-cmpname. ls_description_subco-langu = ls_description-langu. ls_description_subco-sconame = -name. ls_description_subco-descript = -description. APPEND ls_description_subco TO et_descriptions_sub. ENDLOOP. LOOP AT -exceptions ASSIGNING . ls_description_subco-clsname = ls_description-clsname. ls_description_subco-cmpname = ls_description-cmpname. ls_description_subco-langu = ls_description-langu. ls_description_subco-sconame = -name. ls_description_subco-descript = -description. APPEND ls_description_subco TO et_descriptions_sub. ENDLOOP. ENDLOOP. LOOP AT is_intf_aff-descriptions-events ASSIGNING . ls_description-clsname = is_clsname. ls_description-cmpname = -name. ls_description-langu = is_intf_aff-header-original_language. ls_description-descript = -description. APPEND ls_description TO et_descriptions. LOOP AT -parameters ASSIGNING . ls_description_subco-clsname = ls_description-clsname. ls_description_subco-cmpname = ls_description-cmpname. ls_description_subco-langu = ls_description-langu. ls_description_subco-sconame = -name. ls_description_subco-descript = -description. APPEND ls_description_subco TO et_descriptions_sub. ENDLOOP. ENDLOOP. ENDMETHOD. ENDCLASS. * renamed: zcl_abapgit_object_intf :: lcl_aff_metadata_handler CLASS kHGwlUKtFBXjILcBRBJOrsxFJiznPf DEFINITION. PUBLIC SECTION. CLASS-METHODS serialize IMPORTING is_intf TYPE zcl_abapgit_object_intf=>ty_intf RETURNING VALUE(rv_result) TYPE xstring RAISING zcx_abapgit_exception. CLASS-METHODS serialize_translations IMPORTING is_intf TYPE zcl_abapgit_object_intf=>ty_intf it_language TYPE zif_abapgit_definitions=>ty_languages RETURNING VALUE(rt_result) TYPE zif_abapgit_i18n_file=>ty_table_of RAISING zcx_abapgit_exception. CLASS-METHODS deserialize IMPORTING iv_data TYPE string RETURNING VALUE(rv_result) TYPE zif_abapgit_aff_intf_v1=>ty_main RAISING zcx_abapgit_exception. CLASS-METHODS deserialize_translation IMPORTING io_files TYPE REF TO zcl_abapgit_objects_files is_item TYPE zif_abapgit_definitions=>ty_item EXPORTING et_description TYPE zcl_abapgit_object_intf=>ty_intf-description et_description_sub TYPE zcl_abapgit_object_intf=>ty_intf-description_sub RAISING zcx_abapgit_exception. PRIVATE SECTION. CLASS-METHODS: "! For serialization "! @parameter rt_result | Map/table that associates ABAP values to JSON values (enums) get_mappings RETURNING VALUE(rt_result) TYPE zcl_abapgit_json_handler=>ty_enum_mappings, "! For serialization "! @parameter rt_result | Paths that will not be serialized (depending on value) get_paths_to_skip RETURNING VALUE(rt_result) TYPE zcl_abapgit_json_handler=>ty_skip_paths, fill_translation IMPORTING iv_name TYPE seoclsname iv_language TYPE laiso RETURNING VALUE(rt_result) TYPE zif_abapgit_aff_intf_v1=>ty_main. ENDCLASS. CLASS kHGwlUKtFBXjILcBRBJOrsxFJiznPf IMPLEMENTATION. METHOD serialize. DATA: ls_data_aff TYPE zif_abapgit_aff_intf_v1=>ty_main, lx_exception TYPE REF TO cx_root, lo_aff_handler TYPE REF TO zcl_abapgit_json_handler, lo_aff_mapper TYPE REF TO zif_abapgit_aff_type_mapping, lt_enum_mappings TYPE zcl_abapgit_json_handler=>ty_enum_mappings, lt_paths_to_skip TYPE zcl_abapgit_json_handler=>ty_skip_paths. CREATE OBJECT lo_aff_mapper TYPE kHGwlUKtFBXjILcBRBJOvDDGtKNvAd. lo_aff_mapper->to_aff( EXPORTING iv_data = is_intf IMPORTING es_data = ls_data_aff ). lt_enum_mappings = get_mappings( ). lt_paths_to_skip = get_paths_to_skip( ). CREATE OBJECT lo_aff_handler. TRY. rv_result = lo_aff_handler->serialize( iv_data = ls_data_aff iv_enum_mappings = lt_enum_mappings iv_skip_paths = lt_paths_to_skip ). CATCH cx_root INTO lx_exception. zcx_abapgit_exception=>raise_with_text( lx_exception ). ENDTRY. ENDMETHOD. METHOD get_mappings. DATA: ls_category_mapping TYPE zcl_abapgit_json_handler=>ty_enum_mapping, ls_json_abap_mapping TYPE zcl_abapgit_json_handler=>ty_json_abap_mapping, lt_json_abap_mappings TYPE zcl_abapgit_json_handler=>ty_json_abap_mappings. ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-general. ls_json_abap_mapping-json = 'standard'. APPEND ls_json_abap_mapping TO lt_json_abap_mappings. ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-classic_badi. ls_json_abap_mapping-json = 'classicBadi'. APPEND ls_json_abap_mapping TO lt_json_abap_mappings. ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-business_static_components. ls_json_abap_mapping-json = 'businessStaticComponents'. APPEND ls_json_abap_mapping TO lt_json_abap_mappings. ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-db_procedure_proxy. ls_json_abap_mapping-json = 'dbProcedureProxy'. APPEND ls_json_abap_mapping TO lt_json_abap_mappings. ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-web_dynpro_runtime. ls_json_abap_mapping-json = 'webDynproRuntime'. APPEND ls_json_abap_mapping TO lt_json_abap_mappings. ls_json_abap_mapping-abap = zif_abapgit_aff_intf_v1=>co_category-enterprise_service. ls_json_abap_mapping-json = 'enterpriseService'. APPEND ls_json_abap_mapping TO lt_json_abap_mappings. ls_category_mapping-path = '/category'. ls_category_mapping-mappings = lt_json_abap_mappings. APPEND ls_category_mapping TO rt_result. ENDMETHOD. METHOD get_paths_to_skip. DATA: ls_path_to_skipp TYPE zcl_abapgit_json_handler=>ty_path_value_pair. ls_path_to_skipp-path = '/category'. ls_path_to_skipp-value = 'standard'. APPEND ls_path_to_skipp TO rt_result. ENDMETHOD. METHOD deserialize. DATA: lo_ajson TYPE REF TO zcl_abapgit_json_handler, lx_exception TYPE REF TO cx_static_check, lt_enum_mappings TYPE zcl_abapgit_json_handler=>ty_enum_mappings, lt_default_abap_langu_version TYPE zcl_abapgit_json_handler=>ty_path_value_pair, lt_values_for_initial TYPE zcl_abapgit_json_handler=>ty_skip_paths. lt_values_for_initial = get_paths_to_skip( ). lt_default_abap_langu_version-path = '/header/abap_language_version'. lt_default_abap_langu_version-value = zif_abapgit_dot_abapgit=>c_abap_language_version-standard. APPEND lt_default_abap_langu_version TO lt_values_for_initial. lt_enum_mappings = get_mappings( ). CREATE OBJECT lo_ajson. TRY. lo_ajson->deserialize( EXPORTING iv_content = iv_data iv_defaults = lt_values_for_initial iv_enum_mappings = lt_enum_mappings IMPORTING ev_data = rv_result ). CATCH cx_static_check INTO lx_exception. zcx_abapgit_exception=>raise_with_text( lx_exception ). ENDTRY. ENDMETHOD. METHOD serialize_translations. DATA: ls_data TYPE zif_abapgit_aff_intf_v1=>ty_main, lv_langu TYPE laiso, lv_json TYPE string, lo_ajson TYPE REF TO zif_abapgit_ajson, lo_json_path TYPE REF TO zcl_abapgit_json_path, lt_translation TYPE string_table, lx_exception TYPE REF TO zcx_abapgit_ajson_error, lo_trans_file TYPE REF TO zcl_abapgit_properties_file. LOOP AT it_language INTO lv_langu. ls_data = fill_translation( iv_name = is_intf-vseointerf-clsname iv_language = lv_langu ). " convert AFF type to JSON TRY. lo_ajson = zcl_abapgit_ajson=>new( iv_keep_item_order = abap_true )->set( iv_path = '/' iv_val = ls_data )->map( zcl_abapgit_ajson_mapping=>create_to_camel_case( ) )->filter( zcl_abapgit_ajson_filter_lib=>create_empty_filter( ) ). " remove manually the non-primitive types that are initial or not relevant for translation lo_ajson->delete( '/category/' ). lo_ajson->delete( '/proxy/' ). lv_json = lo_ajson->stringify( ). CATCH zcx_abapgit_ajson_error INTO lx_exception. zcx_abapgit_exception=>raise_with_text( lx_exception ). ENDTRY. CREATE OBJECT lo_json_path. lt_translation = lo_json_path->serialize( lv_json ). CREATE OBJECT lo_trans_file EXPORTING iv_lang = lv_langu. lo_trans_file->push_text_pairs( lt_translation ). APPEND lo_trans_file TO rt_result. ENDLOOP. ENDMETHOD. METHOD fill_translation. DATA: lv_langu_sap1 TYPE sy-langu. lv_langu_sap1 = zcl_abapgit_convert=>language_sap2_to_sap1( iv_language ). rt_result-descriptions = kHGwlUKtFBXjILcBRBJOnvUCODLJDd=>get_descriptions_compo_subco( iv_clif_name = iv_name iv_language = lv_langu_sap1 ). SELECT SINGLE descript FROM seoclasstx INTO rt_result-header-description WHERE clsname = iv_name AND langu = lv_langu_sap1. ENDMETHOD. METHOD deserialize_translation. DATA: lo_properties_file TYPE REF TO zcl_abapgit_properties_file, lt_translation_file TYPE zif_abapgit_i18n_file=>ty_table_of, li_translation_file LIKE LINE OF lt_translation_file, ls_aff_data TYPE zif_abapgit_aff_intf_v1=>ty_main, lo_type_mapper TYPE REF TO zif_abapgit_aff_type_mapping, ls_ag_data TYPE zcl_abapgit_object_intf=>ty_intf. lt_translation_file = io_files->read_i18n_files( ). LOOP AT lt_translation_file INTO li_translation_file. CLEAR ls_ag_data. lo_properties_file ?= li_translation_file. lo_properties_file->get_translations( IMPORTING ev_data = ls_aff_data ). ls_aff_data-header-original_language = to_upper( li_translation_file->lang( ) ). " is target language CREATE OBJECT lo_type_mapper TYPE kHGwlUKtFBXjILcBRBJOvDDGtKNvAd. lo_type_mapper->to_abapgit( EXPORTING iv_data = ls_aff_data iv_object_name = is_item-obj_name IMPORTING es_data = ls_ag_data ). APPEND LINES OF ls_ag_data-description TO et_description. APPEND LINES OF ls_ag_data-description_sub TO et_description_sub. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_intf IMPLEMENTATION. METHOD constructor. DATA li_aff_registry TYPE REF TO zif_abapgit_aff_registry. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mi_object_oriented_object_fct = zcl_abapgit_oo_factory=>get_by_type( ms_item-obj_type ). CREATE OBJECT li_aff_registry TYPE zcl_abapgit_aff_registry. mv_aff_enabled = li_aff_registry->is_supported_object_type( 'INTF' ). ENDMETHOD. METHOD deserialize_descriptions. DATA: ls_clskey TYPE seoclskey. ls_clskey-clsname = ms_item-obj_name. mi_object_oriented_object_fct->update_descriptions( is_key = ls_clskey it_descriptions = it_description ). ENDMETHOD. METHOD deserialize_descr_sub. DATA: ls_clskey TYPE seoclskey. ls_clskey-clsname = ms_item-obj_name. mi_object_oriented_object_fct->update_descriptions_sub( is_key = ls_clskey it_descriptions = it_description ). ENDMETHOD. METHOD deserialize_docu. DATA: lv_object TYPE dokhl-object, ls_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_line. lv_object = ms_item-obj_name. IF lines( is_docu-lines ) = 0. mi_object_oriented_object_fct->delete_documentation( iv_id = c_longtext_id-interface iv_object_name = lv_object iv_language = mv_language ). RETURN. ENDIF. mi_object_oriented_object_fct->create_documentation( it_lines = is_docu-lines iv_id = c_longtext_id-interface iv_object_name = lv_object iv_language = mv_language ). LOOP AT is_docu-i18n_lines INTO ls_i18n_lines. mi_object_oriented_object_fct->create_documentation( it_lines = ls_i18n_lines-lines iv_id = c_longtext_id-interface iv_object_name = lv_object iv_language = ls_i18n_lines-language iv_no_masterlang = abap_true ). ENDLOOP. deserialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-attributes iv_longtext_id = c_longtext_id-attributes ). deserialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-methods iv_longtext_id = c_longtext_id-methods ). deserialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-events iv_longtext_id = c_longtext_id-events ). ENDMETHOD. METHOD deserialize_pre_ddic. DATA ls_intf TYPE ty_intf. IF mv_aff_enabled = abap_true. ls_intf = read_json( ). ELSE. ii_xml->read( EXPORTING iv_name = 'VSEOINTERF' CHANGING cg_data = ls_intf-vseointerf ). ENDIF. set_abap_language_version( CHANGING cv_abap_language_version = ls_intf-vseointerf-unicode ). mi_object_oriented_object_fct->create( EXPORTING iv_check = abap_false iv_package = iv_package CHANGING cg_properties = ls_intf-vseointerf ). ENDMETHOD. METHOD deserialize_proxy. DATA: lv_transport TYPE trkorr, li_proxy_object TYPE REF TO if_px_main, lv_name TYPE prx_r3name, lx_proxy_fault TYPE REF TO cx_proxy_fault. lv_name = ms_item-obj_name. lv_transport = iv_transport. TRY. li_proxy_object = cl_pxn_factory=>create( application = 'PROXY_UI' display_only = abap_false saveable = abap_true )->if_pxn_factory~load_by_abap_name( object = ms_item-obj_type obj_name = lv_name ). li_proxy_object->activate( EXPORTING activate_all = abap_true CHANGING transport_number = lv_transport ). li_proxy_object->dequeue( ). CATCH cx_proxy_fault INTO lx_proxy_fault. IF li_proxy_object IS BOUND. TRY. li_proxy_object->dequeue( ). CATCH cx_proxy_fault ##NO_HANDLER. ENDTRY. ENDIF. zcx_abapgit_exception=>raise_with_text( lx_proxy_fault ). ENDTRY. ENDMETHOD. METHOD read_json. DATA lv_json_data TYPE string. DATA ls_intf_aff TYPE zif_abapgit_aff_intf_v1=>ty_main. DATA lo_aff_mapper TYPE REF TO zif_abapgit_aff_type_mapping. lv_json_data = mo_files->read_string( 'json' ). ls_intf_aff = kHGwlUKtFBXjILcBRBJOrsxFJiznPf=>deserialize( lv_json_data ). CREATE OBJECT lo_aff_mapper TYPE kHGwlUKtFBXjILcBRBJOvDDGtKNvAd. lo_aff_mapper->to_abapgit( EXPORTING iv_data = ls_intf_aff iv_object_name = ms_item-obj_name IMPORTING es_data = rs_intf ). ENDMETHOD. METHOD read_xml. ii_xml->read( EXPORTING iv_name = 'VSEOINTERF' CHANGING cg_data = rs_intf-vseointerf ). ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS' CHANGING cg_data = rs_intf-description ). ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS_SUB' CHANGING cg_data = rs_intf-description_sub ). ii_xml->read( EXPORTING iv_name = 'LINES' CHANGING cg_data = rs_intf-docu-lines ). ii_xml->read( EXPORTING iv_name = 'I18N_LINES' CHANGING cg_data = rs_intf-docu-i18n_lines ). ENDMETHOD. METHOD serialize_descr. DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, lv_language TYPE spras, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. IF mo_i18n_params->ms_params-main_language_only = abap_true. lv_language = mv_language. ENDIF. lt_descriptions = mi_object_oriented_object_fct->read_descriptions( iv_object_name = iv_clsname iv_language = lv_language ). " Remove technical languages lt_language_filter = mo_i18n_params->build_language_filter( ). DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. IF lines( lt_descriptions ) = 0. RETURN. ENDIF. rs_description = lt_descriptions. ENDMETHOD. METHOD serialize_descr_sub. DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt, lv_language TYPE spras, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. IF mo_i18n_params->ms_params-main_language_only = abap_true. lv_language = mv_language. ENDIF. lt_descriptions = mi_object_oriented_object_fct->read_descriptions_sub( iv_object_name = iv_clsname iv_language = lv_language ). " Remove technical languages lt_language_filter = mo_i18n_params->build_language_filter( ). DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. IF lines( lt_descriptions ) = 0. RETURN. ENDIF. rs_description = lt_descriptions. ENDMETHOD. METHOD serialize_docu. DATA: lt_lines TYPE tlinetab, lv_object TYPE dokhl-object, lv_langu TYPE sy-langu, lt_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_lines, ls_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_line. lv_object = iv_clsname. lt_lines = mi_object_oriented_object_fct->read_documentation( iv_id = c_longtext_id-interface iv_object_name = lv_object iv_language = mv_language ). rs_docu-lines = lt_lines. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. LOOP AT it_langu_additional INTO lv_langu. lt_lines = mi_object_oriented_object_fct->read_documentation( iv_id = c_longtext_id-interface iv_object_name = lv_object iv_language = lv_langu ). IF lines( lt_lines ) > 0. CLEAR ls_i18n_lines. ls_i18n_lines-language = lv_langu. ls_i18n_lines-lines = lt_lines. INSERT ls_i18n_lines INTO TABLE lt_i18n_lines. ENDIF. ENDLOOP. rs_docu-i18n_lines = lt_i18n_lines. ENDMETHOD. METHOD serialize_xml. DATA: ls_intf TYPE ty_intf, ls_clskey TYPE seoclskey, lv_serialized_data TYPE xstring, lt_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus, lt_i18n_file TYPE zif_abapgit_i18n_file=>ty_table_of, lo_i18n_file TYPE REF TO zif_abapgit_i18n_file. ls_clskey-clsname = ms_item-obj_name. ls_intf-vseointerf = mi_object_oriented_object_fct->get_interface_properties( ls_clskey ). clear_abap_language_version( CHANGING cv_abap_language_version = ls_intf-vseointerf-unicode ). " Select all active translations of documentation " Skip main language - it was already serialized SELECT DISTINCT langu INTO TABLE lt_langu_additional FROM dokhl WHERE id = c_longtext_id-interface AND object = ls_clskey-clsname AND langu <> mv_language ORDER BY langu. ls_intf-docu = serialize_docu( iv_clsname = ls_clskey-clsname it_langu_additional = lt_langu_additional ). ls_intf-description = serialize_descr( ls_clskey-clsname ). ls_intf-description_sub = serialize_descr_sub( ls_clskey-clsname ). " HERE: switch with feature flag for XML or JSON file format IF mv_aff_enabled = abap_true. lv_serialized_data = kHGwlUKtFBXjILcBRBJOrsxFJiznPf=>serialize( ls_intf ). mo_files->add_raw( iv_ext = 'json' iv_data = lv_serialized_data ). lt_i18n_file = kHGwlUKtFBXjILcBRBJOrsxFJiznPf=>serialize_translations( is_intf = ls_intf it_language = mo_i18n_params->ms_params-translation_languages ). LOOP AT lt_i18n_file INTO lo_i18n_file. mo_files->add_i18n_file( lo_i18n_file ). ENDLOOP. ELSE. io_xml->add( iv_name = 'VSEOINTERF' ig_data = ls_intf-vseointerf ). io_xml->add( iv_name = 'DESCRIPTIONS' ig_data = ls_intf-description ). io_xml->add( iv_name = 'DESCRIPTIONS_SUB' ig_data = ls_intf-description_sub ). io_xml->add( iv_name = 'LINES' ig_data = ls_intf-docu-lines ). io_xml->add( iv_name = 'I18N_LINES' ig_data = ls_intf-docu-i18n_lines ). serialize_longtexts( ii_xml = io_xml iv_longtext_name = c_longtext_name-attributes iv_longtext_id = c_longtext_id-attributes ). serialize_longtexts( ii_xml = io_xml iv_longtext_name = c_longtext_name-methods iv_longtext_id = c_longtext_id-methods ). serialize_longtexts( ii_xml = io_xml iv_longtext_name = c_longtext_name-events iv_longtext_id = c_longtext_id-events ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. TYPES: BEGIN OF ty_includes, programm TYPE syrepid, END OF ty_includes. TYPES: BEGIN OF ty_reposrc, unam TYPE reposrc-unam, udat TYPE reposrc-udat, utime TYPE reposrc-utime, END OF ty_reposrc. DATA: lt_reposrc TYPE STANDARD TABLE OF ty_reposrc, ls_reposrc LIKE LINE OF lt_reposrc, lt_includes TYPE STANDARD TABLE OF ty_includes. lt_includes = mi_object_oriented_object_fct->get_includes( ms_item-obj_name ). ASSERT lines( lt_includes ) > 0. SELECT unam udat utime FROM reposrc INTO TABLE lt_reposrc FOR ALL ENTRIES IN lt_includes WHERE progname = lt_includes-programm AND r3state = 'A'. IF sy-subrc <> 0. rv_user = c_user_unknown. ELSE. SORT lt_reposrc BY udat DESCENDING utime DESCENDING. READ TABLE lt_reposrc INDEX 1 INTO ls_reposrc. ASSERT sy-subrc = 0. rv_user = ls_reposrc-unam. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_clskey TYPE seoclskey, ls_vseointerf TYPE vseointerf. ls_clskey-clsname = ms_item-obj_name. ls_vseointerf = mi_object_oriented_object_fct->get_interface_properties( ls_clskey ). IF ls_vseointerf-clsproxy = abap_true. " Proxy interfaces are managed via SPRX RETURN. ENDIF. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. corr_insert( iv_package ). mi_object_oriented_object_fct->delete( ls_clskey ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lt_source TYPE rswsourcet, ls_clskey TYPE seoclskey, ls_intf TYPE ty_intf, lt_description TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, lt_description_sub TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt. IF iv_step = zif_abapgit_object=>gc_step_id-abap. " HERE: switch with feature flag between XML and JSON file format IF mv_aff_enabled = abap_true. ls_intf = read_json( ). kHGwlUKtFBXjILcBRBJOrsxFJiznPf=>deserialize_translation( EXPORTING io_files = mo_files is_item = ms_item IMPORTING et_description = lt_description et_description_sub = lt_description_sub ). APPEND LINES OF lt_description TO ls_intf-description. APPEND LINES OF lt_description_sub TO ls_intf-description_sub. ELSE. ls_intf = read_xml( io_xml ). ENDIF. set_abap_language_version( CHANGING cv_abap_language_version = ls_intf-vseointerf-unicode ). IF ls_intf-vseointerf-clsproxy = abap_true. " Proxy interfaces are managed via SPRX deserialize_proxy( iv_transport ). ELSE. mi_object_oriented_object_fct->create( EXPORTING iv_check = abap_true iv_package = iv_package CHANGING cg_properties = ls_intf-vseointerf ). ls_clskey-clsname = ms_item-obj_name. lt_source = mo_files->read_abap( ). mi_object_oriented_object_fct->deserialize_source( is_key = ls_clskey iv_package = iv_package iv_version = ls_intf-vseointerf-unicode it_source = lt_source ). deserialize_descriptions( ls_intf-description ). deserialize_descr_sub( ls_intf-description_sub ). deserialize_docu( is_docu = ls_intf-docu ii_xml = io_xml ). mi_object_oriented_object_fct->add_to_activation_list( ms_item ). ENDIF. ELSEIF iv_step = zif_abapgit_object=>gc_step_id-early. " If interface does not exist, create it " so DDIC that depends on it does not fail activation IF zif_abapgit_object~exists( ) = abap_false. deserialize_pre_ddic( ii_xml = io_xml iv_package = iv_package ). ELSE. corr_insert( iv_package ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_class_key TYPE seoclskey, lv_category TYPE seoclassdf-category. ls_class_key-clsname = ms_item-obj_name. rv_bool = mi_object_oriented_object_fct->exists( ls_class_key ). IF rv_bool = abap_true. SELECT SINGLE category FROM seoclassdf INTO lv_category WHERE clsname = ls_class_key-clsname AND ( version = '1' OR version = '0' ) ##WARN_OK. "#EC CI_GENBUFF IF sy-subrc = 0 AND lv_category = seoc_category_webdynpro_class. rv_bool = abap_false. ELSE. SELECT SINGLE obj_name FROM sproxhdr INTO ls_class_key-clsname WHERE object = 'INTF' AND obj_name = ls_class_key-clsname. IF sy-subrc = 0. " generated by proxy rv_bool = abap_false. ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-early TO rt_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_object TYPE eqegraarg. lv_object = |{ ms_item-obj_name }|. OVERLAY lv_object WITH '==============================P'. lv_object = lv_object && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESEOCLASS' iv_argument = lv_object ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lt_source TYPE seop_source_string, ls_interface_key TYPE seoclskey. ls_interface_key-clsname = ms_item-obj_name. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. CALL FUNCTION 'SEO_BUFFER_REFRESH' EXPORTING version = seoc_version_active force = abap_true. CALL FUNCTION 'SEO_BUFFER_REFRESH' EXPORTING version = seoc_version_inactive force = abap_true. lt_source = mi_object_oriented_object_fct->serialize_abap( ls_interface_key ). mo_files->add_abap( lt_source ). serialize_xml( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iext IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_extension = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: ls_attributes TYPE edi_iapi01. CALL FUNCTION 'EXTTYPE_READ' EXPORTING pi_cimtyp = mv_extension IMPORTING pe_attributes = ls_attributes EXCEPTIONS OTHERS = 1. rv_user = ls_attributes-plast. ENDMETHOD. METHOD zif_abapgit_object~delete. CALL FUNCTION 'EXTTYPE_DELETE' EXPORTING pi_cimtyp = mv_extension EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_extension TYPE ty_extention, ls_attributes TYPE edi_iapi05. io_xml->read( EXPORTING iv_name = c_dataname_iext CHANGING cg_data = ls_extension ). MOVE-CORRESPONDING ls_extension-attributes TO ls_attributes. ls_attributes-presp = sy-uname. ls_attributes-pwork = ls_attributes-presp. IF zif_abapgit_object~exists( ) = abap_true. CALL FUNCTION 'EXTTYPE_UPDATE' EXPORTING pi_cimtyp = mv_extension pi_attributes = ls_attributes TABLES pt_syntax = ls_extension-t_syntax EXCEPTIONS OTHERS = 1. ELSE. CALL FUNCTION 'EXTTYPE_CREATE' EXPORTING pi_cimtyp = mv_extension pi_devclass = iv_package pi_attributes = ls_attributes TABLES pt_syntax = ls_extension-t_syntax EXCEPTIONS OTHERS = 1. ENDIF. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. CALL FUNCTION 'EXTTYPE_READ' EXPORTING pi_cimtyp = mv_extension EXCEPTIONS OTHERS = 1. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMSED5'. -dynpro = '0010'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'SED5STRUC-OBJECT'. -fval = ms_item-obj_name. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'SED5STRUC-SELECT_EXT'. -fval = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=DISP'. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'WE30' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA ls_extension TYPE ty_extention. CALL FUNCTION 'EXTTYPE_READ' EXPORTING pi_cimtyp = mv_extension IMPORTING pe_attributes = ls_extension-attributes TABLES pt_syntax = ls_extension-t_syntax EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_object_idoc=>clear_idoc_segement_fields( CHANGING cg_structure = ls_extension-attributes ). io_xml->add( iv_name = c_dataname_iext ig_data = ls_extension ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_idoc IMPLEMENTATION. METHOD clear_idoc_segement_field. FIELD-SYMBOLS TYPE any. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cg_structure TO . IF sy-subrc = 0. CLEAR . ENDIF. ENDMETHOD. METHOD clear_idoc_segement_fields. clear_idoc_segement_field( EXPORTING iv_fieldname = 'DEVC' CHANGING cg_structure = cg_structure ). clear_idoc_segement_field( EXPORTING iv_fieldname = 'PLAST' CHANGING cg_structure = cg_structure ). clear_idoc_segement_field( EXPORTING iv_fieldname = 'PWORK' CHANGING cg_structure = cg_structure ). clear_idoc_segement_field( EXPORTING iv_fieldname = 'PRESP' CHANGING cg_structure = cg_structure ). clear_idoc_segement_field( EXPORTING iv_fieldname = 'CREDATE' CHANGING cg_structure = cg_structure ). clear_idoc_segement_field( EXPORTING iv_fieldname = 'CRETIME' CHANGING cg_structure = cg_structure ). clear_idoc_segement_field( EXPORTING iv_fieldname = 'LDATE' CHANGING cg_structure = cg_structure ). clear_idoc_segement_field( EXPORTING iv_fieldname = 'LTIME' CHANGING cg_structure = cg_structure ). ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_idoctyp = ms_item-obj_name. ENDMETHOD. METHOD is_closed. DATA ls_idoc TYPE ty_idoc. CALL FUNCTION 'IDOCTYPE_READ' EXPORTING pi_idoctyp = mv_idoctyp IMPORTING pe_attributes = ls_idoc-attributes EXCEPTIONS object_not_found = 1 db_error = 2 no_authority = 3 OTHERS = 4. rv_closed = boolc( sy-subrc = 0 AND ls_idoc-attributes-closed = abap_true ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: ls_attributes TYPE edi_iapi01. CALL FUNCTION 'IDOCTYPE_READ' EXPORTING pi_idoctyp = mv_idoctyp IMPORTING pe_attributes = ls_attributes EXCEPTIONS object_not_found = 1 db_error = 2 no_authority = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. rv_user = ls_attributes-plast. ENDMETHOD. METHOD zif_abapgit_object~delete. CALL FUNCTION 'IDOCTYPE_DELETE' EXPORTING pi_idoctyp = mv_idoctyp EXCEPTIONS object_not_found = 1 lock_error = 2 action_not_possible = 3 transport_error = 4 db_error = 5 no_authority = 6 OTHERS = 7. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_idoc TYPE ty_idoc, lv_transport TYPE trkorr, ls_edbas TYPE edbas, ls_attributes TYPE edi_iapi05. io_xml->read( EXPORTING iv_name = 'IDOC' CHANGING cg_data = ls_idoc ). MOVE-CORRESPONDING ls_idoc-attributes TO ls_attributes. IF zif_abapgit_object~exists( ) = abap_false. CALL FUNCTION 'IDOCTYPE_CREATE' EXPORTING pi_idoctyp = mv_idoctyp pi_devclass = iv_package pi_attributes = ls_attributes TABLES pt_syntax = ls_idoc-t_syntax EXCEPTIONS object_not_found = 1 object_exists = 2 syntax_error = 3 segment_error = 4 transport_error = 5 db_error = 6 no_authority = 7 OTHERS = 8. ELSE. IF is_closed( ) = abap_true. CALL FUNCTION 'IDOCTYPE_UNCLOSE' EXPORTING pi_idoctyp = mv_idoctyp EXCEPTIONS object_not_found = 1 action_not_possible = 2 db_error = 3 no_authority = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. CALL FUNCTION 'IDOCTYPE_UPDATE' EXPORTING pi_idoctyp = mv_idoctyp pi_attributes = ls_attributes TABLES pt_syntax = ls_idoc-t_syntax EXCEPTIONS object_not_found = 1 object_exists = 2 syntax_error = 3 segment_error = 4 transport_error = 5 db_error = 6 no_authority = 7 OTHERS = 8. ENDIF. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF ls_idoc-attributes-closed = abap_true. IF iv_transport IS NOT INITIAL. lv_transport = iv_transport. CALL FUNCTION 'IDOCTYPE_CLOSE' EXPORTING pi_idoctyp = mv_idoctyp CHANGING pc_order = lv_transport EXCEPTIONS object_not_found = 1 action_not_possible = 2 db_error = 3 no_authority = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. " IDOCTYPE_CLOSE saves current release but it should be same as in repo SELECT SINGLE * FROM edbas INTO ls_edbas WHERE idoctyp = mv_idoctyp. ls_edbas-released = ls_idoc-attributes-released. ls_edbas-applrel = ls_idoc-attributes-applrel. ls_edbas-closed = ls_idoc-attributes-closed. UPDATE edbas FROM ls_edbas. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error updating IDOC { mv_idoctyp }| ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. CALL FUNCTION 'IDOCTYPE_EXISTENCE_CHECK' EXPORTING pi_idoctyp = mv_idoctyp EXCEPTIONS object_not_found = 1 db_error = 2 OTHERS = 3. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMSED5'. -dynpro = '0010'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'SED5STRUC-OBJECT'. -fval = ms_item-obj_name. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'SED5STRUC-SELECT_ORG'. -fval = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=DISP'. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'WE30' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_idoc TYPE ty_idoc. CALL FUNCTION 'IDOCTYPE_READ' EXPORTING pi_idoctyp = mv_idoctyp IMPORTING pe_attributes = ls_idoc-attributes TABLES pt_syntax = ls_idoc-t_syntax EXCEPTIONS object_not_found = 1 db_error = 2 no_authority = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. clear_idoc_segement_fields( CHANGING cg_structure = ls_idoc-attributes ). io_xml->add( iv_name = 'IDOC' ig_data = ls_idoc ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iaxu IMPLEMENTATION. METHOD read. DATA: ls_name TYPE iacikeyt. ls_name = ms_item-obj_name. w3_api_load( EXPORTING is_name = ls_name IMPORTING es_attr = rs_attr ). CLEAR: rs_attr-chname, rs_attr-tdate, rs_attr-ttime, rs_attr-devclass. ENDMETHOD. METHOD save. DATA: lo_xml_api TYPE REF TO object. lo_xml_api = w3_api_create_new( is_attr ). w3_api_save( lo_xml_api ). w3_api_set_changeable( io_xml_api = lo_xml_api iv_changeable = abap_false ). ENDMETHOD. METHOD w3_api_create_new. DATA: lr_xml_api TYPE REF TO data. FIELD-SYMBOLS: TYPE any. CREATE DATA lr_xml_api TYPE REF TO ('CL_W3_API_XML3'). ASSIGN lr_xml_api->* TO . ASSERT sy-subrc = 0. CALL METHOD ('CL_W3_API_XML3')=>create_new EXPORTING p_source_style_2006 = mv_source_style_2006 p_xml_data = is_attr p_generator_class = mv_generator_class p_program_name = is_attr-programm IMPORTING p_xml = EXCEPTIONS undefined_name = 1 error_occured = 2 object_already_existing = 3 not_authorized = 4 action_cancelled = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_xml3~create_new subrc={ sy-subrc }| ). ENDIF. ro_xml_api ?= . ENDMETHOD. METHOD w3_api_delete. CALL METHOD io_xml_api->('IF_W3_API_OBJECT~DELETE') EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 error_occured = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_xml3~delete subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_load. DATA: lr_xml_api TYPE REF TO data. FIELD-SYMBOLS: TYPE any. CREATE DATA lr_xml_api TYPE REF TO ('CL_W3_API_XML3'). ASSIGN lr_xml_api->* TO . ASSERT sy-subrc = 0. CALL METHOD ('CL_W3_API_XML3')=>load EXPORTING p_xml_name = is_name IMPORTING p_attributes = es_attr p_xml = EXCEPTIONS object_not_existing = 1 permission_failure = 2 data_corrupt = 3 error_occured = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_xml3~load subrc={ sy-subrc }| ). ENDIF. eo_xml_api ?= . ENDMETHOD. METHOD w3_api_save. CALL METHOD io_xml_api->('IF_W3_API_OBJECT~SAVE') EXCEPTIONS object_invalid = 1 object_not_changeable = 2 action_cancelled = 3 permission_failure = 4 not_changed = 5 data_invalid = 6 error_occured = 7 OTHERS = 8. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_xml3~save subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_changeable. CALL METHOD io_xml_api->('IF_W3_API_OBJECT~SET_CHANGEABLE') EXPORTING p_changeable = iv_changeable EXCEPTIONS action_cancelled = 1 object_locked_by_other_user = 2 permission_failure = 3 object_already_changeable = 4 object_already_unlocked = 5 object_just_created = 6 object_deleted = 7 object_modified = 8 object_not_existing = 9 object_invalid = 10 error_occured = 11 OTHERS = 12. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_xml3~set_changeable subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = read( )-chname. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_xml_api TYPE REF TO object, ls_name TYPE iacikeyt. ls_name = ms_item-obj_name. w3_api_load( EXPORTING is_name = ls_name IMPORTING eo_xml_api = lo_xml_api ). w3_api_set_changeable( io_xml_api = lo_xml_api iv_changeable = abap_true ). w3_api_delete( lo_xml_api ). w3_api_save( lo_xml_api ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_attr TYPE w3tempattr. io_xml->read( EXPORTING iv_name = 'ATTR' CHANGING cg_data = ls_attr ). ls_attr-devclass = iv_package. IF zif_abapgit_object~exists( ) = abap_true. zif_abapgit_object~delete( iv_package = iv_package iv_transport = iv_transport ). ENDIF. save( ls_attr ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_name TYPE iacikeyt. ls_name = ms_item-obj_name. CALL METHOD ('CL_W3_API_XML3')=>s_check_exist EXPORTING p_xml_name = ls_name IMPORTING p_exists = rv_bool. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_attr TYPE w3tempattr. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. ls_attr = read( ). io_xml->add( iv_name = 'ATTR' ig_data = ls_attr ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iatu IMPLEMENTATION. METHOD read. DATA: li_template TYPE REF TO if_w3_api_template, lt_source TYPE w3htmltabtype, ls_name TYPE iacikeyt. ls_name = ms_item-obj_name. li_template = w3_api_load( ls_name ). es_attr = w3_api_get_attributes( li_template ). CLEAR: es_attr-chname, es_attr-tdate, es_attr-ttime, es_attr-devclass. lt_source = w3_api_get_source( li_template ). CONCATENATE LINES OF lt_source INTO ev_source RESPECTING BLANKS. ENDMETHOD. METHOD save. DATA: lt_source TYPE w3htmltabtype, lv_source TYPE string, li_template TYPE REF TO if_w3_api_template. li_template = w3_api_create_new( is_attr ). w3_api_set_attributes( ii_template = li_template is_attr = is_attr ). lv_source = iv_source. WHILE strlen( lv_source ) >= 255. APPEND lv_source(255) TO lt_source. lv_source = lv_source+255. ENDWHILE. IF NOT lv_source IS INITIAL. APPEND lv_source TO lt_source. ENDIF. w3_api_set_source( ii_template = li_template it_source = lt_source ). w3_api_save( li_template ). " Release locks w3_api_set_changeable( ii_template = li_template iv_changeable = abap_false ). ENDMETHOD. METHOD w3_api_create_new. cl_w3_api_template=>if_w3_api_template~create_new( EXPORTING p_template_data = is_template_data p_program_name = is_template_data-programm IMPORTING p_template = ri_template EXCEPTIONS object_already_existing = 1 object_just_created = 2 not_authorized = 3 undefined_name = 4 author_not_existing = 5 action_cancelled = 6 error_occured = 7 user_error = 8 OTHERS = 9 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_template~create_new subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_delete. ii_template->if_w3_api_object~delete( EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 error_occured = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_template~delete subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_get_attributes. ii_template->get_attributes( IMPORTING p_attributes = rs_attributes EXCEPTIONS object_invalid = 1 template_deleted = 2 error_occured = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_template~get_attributes subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_get_source. ii_template->get_source( IMPORTING p_source = rt_source EXCEPTIONS object_invalid = 1 template_deleted = 2 error_occured = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_template~get_source subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_load. cl_w3_api_template=>if_w3_api_template~load( EXPORTING p_template_name = is_name IMPORTING p_template = ri_template EXCEPTIONS object_not_existing = 1 permission_failure = 2 error_occured = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from if_w3_api_template~load subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_save. ii_template->if_w3_api_object~save( EXCEPTIONS object_invalid = 1 object_not_changeable = 2 action_cancelled = 3 permission_failure = 4 not_changed = 5 data_invalid = 6 error_occured = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_template~save subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_attributes. ii_template->set_attributes( EXPORTING p_attributes = is_attr EXCEPTIONS object_not_changeable = 1 object_deleted = 2 object_invalid = 3 author_not_existing = 4 authorize_failure = 5 error_occured = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_template~set_attributes subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_changeable. ii_template->if_w3_api_object~set_changeable( EXPORTING p_changeable = iv_changeable EXCEPTIONS action_cancelled = 1 object_locked_by_other_user = 2 permission_failure = 3 object_already_changeable = 4 object_already_unlocked = 5 object_just_created = 6 object_deleted = 7 object_modified = 8 object_not_existing = 9 object_invalid = 10 error_occured = 11 OTHERS = 12 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_template~set_changeable subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_source. ii_template->set_source( EXPORTING p_source = it_source EXCEPTIONS object_not_changeable = 1 object_deleted = 2 object_invalid = 3 authorize_failure = 4 invalid_parameter = 5 error_occured = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from w3_api_template~set_source subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA ls_attributes TYPE w3tempattr. read( IMPORTING es_attr = ls_attributes ). rv_user = ls_attributes-chname. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: li_template TYPE REF TO if_w3_api_template, ls_name TYPE iacikeyt. ls_name = ms_item-obj_name. li_template = w3_api_load( ls_name ). w3_api_set_changeable( ii_template = li_template iv_changeable = abap_true ). w3_api_delete( li_template ). w3_api_save( li_template ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_attr TYPE w3tempattr, lv_source TYPE string. io_xml->read( EXPORTING iv_name = 'ATTR' CHANGING cg_data = ls_attr ). lv_source = mo_files->read_string( 'html' ). ls_attr-devclass = iv_package. save( is_attr = ls_attr iv_source = lv_source ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_name TYPE iacikeyt. ls_name = ms_item-obj_name. cl_w3_api_template=>s_check_exist( EXPORTING p_template_name = ls_name IMPORTING p_exists = rv_bool ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_attr TYPE w3tempattr, lv_source TYPE string. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. read( IMPORTING es_attr = ls_attr ev_source = lv_source ). io_xml->add( iv_name = 'ATTR' ig_data = ls_attr ). mo_files->add_string( iv_ext = 'html' iv_string = lv_source ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iasp IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_name = ms_item-obj_name. ENDMETHOD. METHOD read. DATA: li_service TYPE REF TO if_w3_api_service. li_service = w3_api_load( ). es_attr = w3_api_get_attributes( li_service ). CLEAR: es_attr-chname, es_attr-tdate, es_attr-ttime, es_attr-devclass. et_parameters = w3_api_get_parameters( li_service ). ENDMETHOD. METHOD save. DATA: li_service TYPE REF TO if_w3_api_service. li_service = w3_api_create_new( is_attr ). w3_api_set_attributes( ii_service = li_service is_attributes = is_attr ). w3_api_set_parameters( ii_service = li_service it_parameters = it_parameters ). w3_api_save( li_service ). " Release locks w3_api_set_changeable( ii_service = li_service iv_changeable = abap_false ). ENDMETHOD. METHOD w3_api_create_new. cl_w3_api_service=>if_w3_api_service~create_new( EXPORTING p_service_data = is_attributes IMPORTING p_service = ri_service EXCEPTIONS object_already_existing = 1 object_just_created = 2 not_authorized = 3 undefined_name = 4 author_not_existing = 5 action_cancelled = 6 error_occured = 7 invalid_parameter = 8 OTHERS = 9 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_service~create_new. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_delete. ii_service->if_w3_api_object~delete( EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 error_occured = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_object~delete. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_get_attributes. ii_service->get_attributes( IMPORTING p_attributes = rs_attributes ). ENDMETHOD. METHOD w3_api_get_parameters. ii_service->get_parameters( IMPORTING p_parameters = rt_parameters ). ENDMETHOD. METHOD w3_api_load. cl_w3_api_service=>if_w3_api_service~load( EXPORTING p_service_name = mv_name IMPORTING p_service = ri_service EXCEPTIONS object_not_existing = 1 permission_failure = 2 error_occured = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from w3api_service~load' ). ENDIF. ENDMETHOD. METHOD w3_api_save. ii_service->if_w3_api_object~save( EXCEPTIONS object_invalid = 1 object_not_changeable = 2 action_cancelled = 3 permission_failure = 4 not_changed = 5 data_invalid = 6 error_occured = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_object~save. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_attributes. ii_service->set_attributes( EXPORTING p_attributes = is_attributes EXCEPTIONS object_not_changeable = 1 object_deleted = 2 object_invalid = 3 author_not_existing = 4 authorize_failure = 5 error_occured = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_service~set_attributes. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_changeable. ii_service->if_w3_api_object~set_changeable( EXPORTING p_changeable = iv_changeable EXCEPTIONS action_cancelled = 1 object_locked_by_other_user = 2 permission_failure = 3 object_already_changeable = 4 object_already_unlocked = 5 object_just_created = 6 object_deleted = 7 object_modified = 8 object_not_existing = 9 object_invalid = 10 error_occured = 11 OTHERS = 12 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_object~set_changeable. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_parameters. ii_service->set_parameters( EXPORTING p_parameters = it_parameters EXCEPTIONS object_not_changeable = 1 object_deleted = 2 object_invalid = 3 authorize_failure = 4 invalid_parameter = 5 error_occured = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_service~set_parameters. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " todo ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: li_service TYPE REF TO if_w3_api_service. li_service = w3_api_load( ). w3_api_set_changeable( li_service ). w3_api_delete( li_service ). w3_api_save( li_service ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_attr TYPE w3servattr, lt_parameters TYPE w3servpara_tabletype. io_xml->read( EXPORTING iv_name = 'ATTR' CHANGING cg_data = ls_attr ). io_xml->read( EXPORTING iv_name = 'PARAMETERS' CHANGING cg_data = lt_parameters ). ls_attr-devclass = iv_package. save( is_attr = ls_attr it_parameters = lt_parameters ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lx_error TYPE REF TO zcx_abapgit_exception. TRY. w3_api_load( ). rv_bool = abap_true. CATCH zcx_abapgit_exception INTO lx_error. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_attr TYPE w3servattr, lt_parameters TYPE w3servpara_tabletype. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. read( IMPORTING es_attr = ls_attr et_parameters = lt_parameters ). io_xml->add( iv_name = 'ATTR' ig_data = ls_attr ). io_xml->add( iv_name = 'PARAMETERS' ig_data = lt_parameters ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iarp IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). ms_name = ms_item-obj_name. ENDMETHOD. METHOD read. DATA: li_resource TYPE REF TO if_w3_api_resource. li_resource = w3_api_load( ). es_attributes = w3_api_get_attributes( li_resource ). CLEAR: es_attributes-chname, es_attributes-tdate, es_attributes-ttime, es_attributes-devclass. et_parameters = w3_api_get_parameters( li_resource ). ENDMETHOD. METHOD save. DATA: li_resource TYPE REF TO if_w3_api_resource. li_resource = w3_api_create_new( is_attributes ). w3_api_set_attributes( ii_resource = li_resource is_attributes = is_attributes ). w3_api_set_parameters( ii_resource = li_resource it_parameters = it_parameters ). w3_api_save( li_resource ). " Release locks w3_api_set_changeable( ii_resource = li_resource iv_changeable = abap_false ). ENDMETHOD. METHOD w3_api_create_new. cl_w3_api_resource=>if_w3_api_resource~create_new( EXPORTING p_resource_data = is_attributes IMPORTING p_resource = ri_resource EXCEPTIONS object_already_existing = 1 object_just_created = 2 not_authorized = 3 undefined_name = 4 author_not_existing = 5 action_cancelled = 6 error_occured = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_resource~create_new. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_delete. ii_resource->if_w3_api_object~delete( EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 error_occured = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_object~delete. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_get_attributes. ii_resource->get_attributes( IMPORTING p_attributes = rs_attributes EXCEPTIONS object_invalid = 1 resource_deleted = 2 error_occured = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_resource~get_attributes. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_get_parameters. ii_resource->get_parameters( IMPORTING p_parameters = rt_parameters EXCEPTIONS object_invalid = 1 resource_deleted = 2 error_occured = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_resource~get_parameters. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_load. cl_w3_api_resource=>if_w3_api_resource~load( EXPORTING p_resource_name = ms_name IMPORTING p_resource = ri_resource EXCEPTIONS object_not_existing = 1 permission_failure = 2 error_occured = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from w3api_resource~load. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_save. ii_resource->if_w3_api_object~save( EXCEPTIONS object_invalid = 1 object_not_changeable = 2 action_cancelled = 3 permission_failure = 4 not_changed = 5 data_invalid = 6 error_occured = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_object~save. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_attributes. ii_resource->set_attributes( EXPORTING p_attributes = is_attributes EXCEPTIONS object_not_changeable = 1 object_deleted = 2 object_invalid = 3 author_not_existing = 4 authorize_failure = 5 error_occured = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_resource~set_attributes. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_changeable. ii_resource->if_w3_api_object~set_changeable( EXPORTING p_changeable = iv_changeable EXCEPTIONS action_cancelled = 1 object_locked_by_other_user = 2 permission_failure = 3 object_already_changeable = 4 object_already_unlocked = 5 object_just_created = 6 object_deleted = 7 object_modified = 8 object_not_existing = 9 object_invalid = 10 error_occured = 11 OTHERS = 12 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_object~set_changeable. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD w3_api_set_parameters. ii_resource->set_parameters( EXPORTING p_parameters = it_parameters EXCEPTIONS object_not_changeable = 1 object_deleted = 2 object_invalid = 3 authorize_failure = 4 invalid_parameter = 5 error_occured = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |error from if_w3_api_resource~set_parameters. Subrc={ sy-subrc }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA ls_attributes TYPE w3resoattr. read( IMPORTING es_attributes = ls_attributes ). rv_user = ls_attributes-chname. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: li_resource TYPE REF TO if_w3_api_resource. li_resource = w3_api_load( ). w3_api_set_changeable( li_resource ). w3_api_delete( li_resource ). w3_api_save( li_resource ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_attr TYPE w3resoattr, lt_parameters TYPE w3resopara_tabletype. io_xml->read( EXPORTING iv_name = 'ATTR' CHANGING cg_data = ls_attr ). io_xml->read( EXPORTING iv_name = 'PARAMETERS' CHANGING cg_data = lt_parameters ). ls_attr-devclass = iv_package. save( is_attributes = ls_attr it_parameters = lt_parameters ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lx_error TYPE REF TO zcx_abapgit_exception. TRY. w3_api_load( ). rv_bool = abap_true. CATCH zcx_abapgit_exception INTO lx_error. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_attr TYPE w3resoattr, lt_parameters TYPE w3resopara_tabletype. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. read( IMPORTING es_attributes = ls_attr et_parameters = lt_parameters ). io_xml->add( iv_name = 'ATTR' ig_data = ls_attr ). io_xml->add( iv_name = 'PARAMETERS' ig_data = lt_parameters ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_iamu IMPLEMENTATION. METHOD get_extension. CONSTANTS: lc_jpg TYPE xstring VALUE 'FFD8FF', lc_png TYPE xstring VALUE '89504E470D0A1A0A', lc_gif TYPE xstring VALUE '47494638', lc_bmp TYPE xstring VALUE '424D'. DATA lv_len TYPE i. " Try to derive type of MIME object from the long name FIND REGEX '\.(\w)$' IN iv_name SUBMATCHES rv_extension. IF sy-subrc = 0. rv_extension = to_lower( rv_extension ). ELSEIF zcl_abapgit_utils=>is_binary( iv_data ) = abap_true. " Use magic numbers to detect common file types lv_len = xstrlen( iv_data ). IF lv_len > 3 AND iv_data(3) = lc_jpg. rv_extension = 'jpg'. ELSEIF lv_len > 8 AND iv_data(8) = lc_png. rv_extension = 'png'. ELSEIF lv_len > 4 AND iv_data(4) = lc_gif. rv_extension = 'git'. ELSEIF lv_len > 2 AND iv_data(2) = lc_bmp. rv_extension = 'bmp'. ELSE. rv_extension = 'bin'. ENDIF. ELSE. rv_extension = 'txt'. ENDIF. ENDMETHOD. METHOD load_mime_api. DATA: ls_mime_name TYPE iacikeym. ls_mime_name = ms_item-obj_name. cl_w3_api_mime=>if_w3_api_mime~load( EXPORTING p_mime_name = ls_mime_name IMPORTING p_mime = mi_mime_api EXCEPTIONS object_not_existing = 1 permission_failure = 2 data_corrupt = 3 error_occured = 4 OTHERS = 6 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from if_w3_api_mime~load' ). ENDIF. ENDMETHOD. METHOD lock. " As a side effect this method removes also existing locks mi_mime_api->if_w3_api_object~set_changeable( EXPORTING p_changeable = iv_changable EXCEPTIONS action_cancelled = 1 object_locked_by_other_user = 2 permission_failure = 3 object_already_changeable = 4 object_already_unlocked = 5 object_just_created = 6 object_deleted = 7 object_modified = 8 object_not_existing = 9 object_invalid = 10 error_occured = 11 OTHERS = 12 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~set_changeable| ). ENDIF. ENDMETHOD. METHOD read. load_mime_api( ). mi_mime_api->get_attributes( IMPORTING p_attributes = rs_internet_appl_comp_binary-attributes EXCEPTIONS object_invalid = 1 mime_deleted = 2 error_occured = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~get_attributes| ). ENDIF. CLEAR: rs_internet_appl_comp_binary-attributes-chname, rs_internet_appl_comp_binary-attributes-tdate, rs_internet_appl_comp_binary-attributes-ttime, rs_internet_appl_comp_binary-attributes-devclass. mi_mime_api->get_source( IMPORTING p_source = rs_internet_appl_comp_binary-source p_datalength = rs_internet_appl_comp_binary-length EXCEPTIONS object_invalid = 1 mime_deleted = 2 error_occured = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~get_source| ). ENDIF. ENDMETHOD. METHOD save. IF zif_abapgit_object~exists( ) = abap_true. load_mime_api( ). lock( abap_true ). mi_mime_api->set_source( EXPORTING p_source = is_internet_appl_comp_binary-source p_datalength = is_internet_appl_comp_binary-length EXCEPTIONS object_not_changeable = 1 object_deleted = 2 object_invalid = 3 authorize_failure = 4 invalid_content = 5 error_occured = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error { sy-subrc } from set_source| ). ENDIF. ELSE. cl_w3_api_mime=>if_w3_api_mime~create_new( EXPORTING p_mime_data = is_internet_appl_comp_binary-attributes p_mime_content = is_internet_appl_comp_binary-source p_datalength = is_internet_appl_comp_binary-length IMPORTING p_mime = mi_mime_api EXCEPTIONS object_already_existing = 1 object_just_created = 2 not_authorized = 3 undefined_name = 4 author_not_existing = 5 action_cancelled = 6 error_occured = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error { sy-subrc } from create_new| ). ENDIF. ENDIF. " Create_new does not update text, so set attributes explicitly mi_mime_api->set_attributes( EXPORTING p_attributes = is_internet_appl_comp_binary-attributes EXCEPTIONS object_not_changeable = 1 object_deleted = 2 object_invalid = 3 author_not_existing = 4 authorize_failure = 5 error_occured = 6 OTHERS = 7 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error { sy-subrc } from set_attributes| ). ENDIF. mi_mime_api->if_w3_api_object~save( EXCEPTIONS object_invalid = 1 object_not_changeable = 2 action_cancelled = 3 permission_failure = 4 not_changed = 5 data_invalid = 6 error_occured = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error { sy-subrc } from save| ). ENDIF. lock( abap_false ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = read( )-attributes-chname. ENDMETHOD. METHOD zif_abapgit_object~delete. load_mime_api( ). mi_mime_api->if_w3_api_object~set_changeable( EXPORTING p_changeable = abap_true EXCEPTIONS action_cancelled = 1 object_locked_by_other_user = 2 permission_failure = 3 object_already_changeable = 4 object_already_unlocked = 5 object_just_created = 6 object_deleted = 7 object_modified = 8 object_not_existing = 9 object_invalid = 10 error_occured = 11 OTHERS = 12 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~set_changeable| ). ENDIF. mi_mime_api->if_w3_api_object~delete( EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 error_occured = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~delete| ). ENDIF. mi_mime_api->if_w3_api_object~save( EXCEPTIONS object_invalid = 1 object_not_changeable = 2 action_cancelled = 3 permission_failure = 4 not_changed = 5 data_invalid = 6 error_occured = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error from if_w3_api_mime~save| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_internet_appl_comp_binary TYPE ty_internet_appl_comp_binary. DATA lv_xstring TYPE xstring. io_xml->read( EXPORTING iv_name = 'IAMU' CHANGING cg_data = ls_internet_appl_comp_binary ). ls_internet_appl_comp_binary-attributes-devclass = iv_package. IF io_xml->get_metadata( )-version = 'v2.0.0'. lv_xstring = mo_files->read_raw( ls_internet_appl_comp_binary-extension ). zcl_abapgit_convert=>xstring_to_bintab( EXPORTING iv_xstr = lv_xstring IMPORTING et_bintab = ls_internet_appl_comp_binary-source ev_size = ls_internet_appl_comp_binary-length ). ENDIF. save( ls_internet_appl_comp_binary ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_mime_name TYPE iacikeym. ls_mime_name = ms_item-obj_name. cl_w3_api_mime=>s_check_exist( EXPORTING p_mime_name = ls_mime_name IMPORTING p_exists = rv_bool ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). rs_metadata-version = 'v2.0.0'. " Serialization v2, separate data file ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_internet_appl_comp_binary TYPE ty_internet_appl_comp_binary. DATA lv_xstring TYPE xstring. FIELD-SYMBOLS: LIKE LINE OF ls_internet_appl_comp_binary-source. ls_internet_appl_comp_binary = read( ). " Serialization v2, separate data file LOOP AT ls_internet_appl_comp_binary-source ASSIGNING . lv_xstring = lv_xstring && -line. ENDLOOP. lv_xstring = lv_xstring(ls_internet_appl_comp_binary-length). CLEAR: ls_internet_appl_comp_binary-source, ls_internet_appl_comp_binary-length. ls_internet_appl_comp_binary-extension = get_extension( iv_name = ls_internet_appl_comp_binary-attributes-longname iv_data = lv_xstring ). mo_files->add_raw( iv_data = lv_xstring iv_ext = ls_internet_appl_comp_binary-extension ). io_xml->add( iv_name = 'IAMU' ig_data = ls_internet_appl_comp_binary ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_g4bs IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). ro_result->add( iv_table = '/IWBEP/I_V4_MSRV' iv_field = 'CREATED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_V4_MSRV' iv_field = 'CHANGED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_V4_MSRV' iv_field = 'CREATED_TS' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_V4_MSRV' iv_field = 'CHANGED_TS' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_V4_MSRT' iv_field = 'CREATED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_V4_MSRT' iv_field = 'CHANGED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_V4_MSRT' iv_field = 'CREATED_TS' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_V4_MSRT' iv_field = 'CHANGED_TS' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lv_created TYPE sy-uname. DATA lv_changed TYPE sy-uname. " Get entry with highest version SELECT created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_V4_MSRV') WHERE service_id = ms_item-obj_name ORDER BY PRIMARY KEY. rv_user = lv_changed. IF lv_changed IS INITIAL. rv_user = lv_created. ENDIF. ENDSELECT. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_g4ba IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). ro_result->add( iv_table = '/IWBEP/I_V4_MSGR' iv_field = 'CREATED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_V4_MSGR' iv_field = 'CHANGED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_V4_MSGR' iv_field = 'CREATED_TS' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_V4_MSGR' iv_field = 'CHANGED_TS' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_V4_MSGA' iv_field = 'CREATED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_V4_MSGA' iv_field = 'CHANGED_BY' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = '/IWBEP/I_V4_MSGA' iv_field = 'CREATED_TS' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp )->add( iv_table = '/IWBEP/I_V4_MSGA' iv_field = 'CHANGED_TS' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-timestamp ). ENDMETHOD. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING io_field_rules = get_field_rules( ) is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lv_created TYPE sy-uname. DATA lv_changed TYPE sy-uname. SELECT SINGLE created_by changed_by INTO (lv_created, lv_changed) FROM ('/IWBEP/I_V4_MSGR') WHERE group_id = ms_item-obj_name. rv_user = lv_changed. IF lv_changed IS INITIAL. rv_user = lv_created. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_fugr IMPLEMENTATION. METHOD check_rfc_parameters. * function module RS_FUNCTIONMODULE_INSERT does the same deep down, but the right error * message is not returned to the user, this is a workaround to give a proper error * message to the user DATA: ls_parameter TYPE rsfbpara, lt_fupa TYPE rsfb_param, ls_fupa LIKE LINE OF lt_fupa. IF is_function-remote_call = 'R'. cl_fb_parameter_conversion=>convert_parameter_old_to_fupa( EXPORTING functionname = is_function-funcname import = is_function-import export = is_function-export change = is_function-changing tables = is_function-tables except = is_function-exception IMPORTING fupararef = lt_fupa ). LOOP AT lt_fupa INTO ls_fupa WHERE paramtype = 'I' OR paramtype = 'E' OR paramtype = 'C' OR paramtype = 'T'. cl_fb_parameter_conversion=>convert_intern_to_extern( EXPORTING parameter_db = ls_fupa IMPORTING parameter_vis = ls_parameter ). CALL FUNCTION 'RS_FB_CHECK_PARAMETER_REMOTE' EXPORTING parameter = ls_parameter basxml_enabled = is_function-remote_basxml EXCEPTIONS not_remote_compatible = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDIF. ENDMETHOD. METHOD deserialize_functions. DATA: lv_include TYPE rs38l-include, lv_area TYPE rs38l-area, lv_group TYPE rs38l-area, lv_namespace TYPE rs38l-namespace, lt_source TYPE TABLE OF abaptxt255, lv_msg TYPE string, lx_error TYPE REF TO zcx_abapgit_exception. FIELD-SYMBOLS: LIKE LINE OF it_functions. LOOP AT it_functions ASSIGNING . lt_source = mo_files->read_abap( iv_extra = -funcname ). lv_area = ms_item-obj_name. CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' EXPORTING complete_area = lv_area IMPORTING namespace = lv_namespace group = lv_group EXCEPTIONS OTHERS = 12. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_msg. ii_log->add_error( iv_msg = |Function module { -funcname }: { lv_msg }| is_item = ms_item ). CONTINUE. "with next function module ENDIF. IF zcl_abapgit_factory=>get_function_module( )->function_exists( -funcname ) = abap_true. * delete the function module to make sure the parameters are updated * haven't found a nice way to update the parameters CALL FUNCTION 'FUNCTION_DELETE' EXPORTING funcname = -funcname suppress_success_message = abap_true EXCEPTIONS error_message = 1 OTHERS = 2. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_msg. ii_log->add_error( iv_msg = |Function module { -funcname }: { lv_msg }| is_item = ms_item ). CONTINUE. "with next function module ENDIF. ENDIF. TRY. check_rfc_parameters( ). CATCH zcx_abapgit_exception INTO lx_error. ii_log->add_error( iv_msg = |Function module { -funcname }: { lx_error->get_text( ) }| is_item = ms_item ). CONTINUE. "with next function module ENDTRY. CALL FUNCTION 'RS_FUNCTIONMODULE_INSERT' EXPORTING funcname = -funcname function_pool = lv_group interface_global = -global_flag remote_call = -remote_call short_text = -short_text update_task = -update_task exception_class = -exception_classes namespace = lv_namespace remote_basxml_supported = -remote_basxml corrnum = iv_transport IMPORTING function_include = lv_include TABLES import_parameter = -import export_parameter = -export tables_parameter = -tables changing_parameter = -changing exception_list = -exception parameter_docu = -documentation EXCEPTIONS double_task = 1 error_message = 2 function_already_exists = 3 invalid_function_pool = 4 invalid_name = 5 too_many_functions = 6 no_modify_permission = 7 no_show_permission = 8 enqueue_system_failure = 9 canceled_in_corr = 10 OTHERS = 11. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_msg. ii_log->add_error( iv_msg = |Function module { -funcname }: { lv_msg }| is_item = ms_item ). CONTINUE. "with next function module ENDIF. zcl_abapgit_factory=>get_sap_report( )->insert_report( iv_name = lv_include iv_package = iv_package iv_version = iv_version it_source = lt_source ). ii_log->add_success( iv_msg = |Function module { -funcname } imported| is_item = ms_item ). ENDLOOP. ENDMETHOD. METHOD deserialize_function_docs. FIELD-SYMBOLS LIKE LINE OF it_functions. zcl_abapgit_factory=>get_longtexts( )->deserialize( iv_longtext_id = c_longtext_id_prog iv_object_name = iv_prog_name ii_xml = ii_xml iv_main_language = mv_language ). LOOP AT it_functions ASSIGNING . zcl_abapgit_factory=>get_longtexts( )->deserialize( iv_longtext_name = |LONGTEXTS_{ -funcname }| iv_longtext_id = c_longtext_id_func iv_object_name = -funcname ii_xml = ii_xml iv_main_language = mv_language ). zcl_abapgit_factory=>get_longtexts( )->deserialize( iv_longtext_name = |LONGTEXTS_{ -funcname }___EXC| iv_longtext_id = c_longtext_id_func_exc iv_object_name = -funcname ii_xml = ii_xml iv_main_language = mv_language ). ENDLOOP. ENDMETHOD. METHOD deserialize_includes. DATA: lo_xml TYPE REF TO zif_abapgit_xml_input, ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, lt_includes TYPE ty_sobj_name_tt, lt_tpool TYPE textpool_table, lt_tpool_ext TYPE zif_abapgit_definitions=>ty_tpool_tt, lt_source TYPE TABLE OF abaptxt255, lx_exc TYPE REF TO zcx_abapgit_exception. FIELD-SYMBOLS: LIKE LINE OF lt_includes. tadir_insert( iv_package ). ii_xml->read( EXPORTING iv_name = 'INCLUDES' CHANGING cg_data = lt_includes ). LOOP AT lt_includes ASSIGNING . "ignore simple transformation includes (as long as they remain in existing repositories) IF strlen( ) = 33 AND +30(3) = 'XTI'. ii_log->add_warning( iv_msg = |Simple Transformation include { } ignored| is_item = ms_item ). CONTINUE. ENDIF. TRY. lt_source = mo_files->read_abap( iv_extra = ). lo_xml = mo_files->read_xml( ). lo_xml->read( EXPORTING iv_name = 'PROGDIR' CHANGING cg_data = ls_progdir ). set_abap_language_version( CHANGING cv_abap_language_version = ls_progdir-uccheck ). lo_xml->read( EXPORTING iv_name = 'TPOOL' CHANGING cg_data = lt_tpool_ext ). lt_tpool = read_tpool( lt_tpool_ext ). deserialize_program( is_progdir = ls_progdir it_source = lt_source it_tpool = lt_tpool iv_package = iv_package ). deserialize_textpool( iv_program = it_tpool = lt_tpool iv_is_include = abap_true ). ii_log->add_success( iv_msg = |Include { ls_progdir-name } imported| is_item = ms_item ). CATCH zcx_abapgit_exception INTO lx_exc. ii_log->add_exception( ix_exc = lx_exc is_item = ms_item ). CONTINUE. ENDTRY. ENDLOOP. ENDMETHOD. METHOD deserialize_texts. DATA: lt_tpool_i18n TYPE ty_tpools_i18n, lt_tpool TYPE textpool_table. FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. ii_xml->read( EXPORTING iv_name = 'I18N_TPOOL' CHANGING cg_data = lt_tpool_i18n ). LOOP AT lt_tpool_i18n ASSIGNING . lt_tpool = read_tpool( -textpool ). deserialize_textpool( iv_program = iv_prog_name iv_language = -language it_tpool = lt_tpool ). ENDLOOP. ENDMETHOD. METHOD deserialize_xml. DATA: lv_complete TYPE rs38l-area, lv_namespace TYPE rs38l-namespace, lv_areat TYPE tlibt-areat, lv_stext TYPE tftit-stext, lv_group TYPE rs38l-area. lv_complete = ms_item-obj_name. CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' EXPORTING complete_area = lv_complete IMPORTING namespace = lv_namespace group = lv_group EXCEPTIONS include_not_exists = 1 group_not_exists = 2 no_selections = 3 no_function_include = 4 no_function_pool = 5 delimiter_wrong_position = 6 no_customer_function_group = 7 no_customer_function_include = 8 reserved_name_customer = 9 namespace_too_long = 10 area_length_error = 11 OTHERS = 12. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ii_xml->read( EXPORTING iv_name = 'AREAT' CHANGING cg_data = lv_areat ). lv_stext = lv_areat. CALL FUNCTION 'RS_FUNCTION_POOL_INSERT' EXPORTING function_pool = lv_group short_text = lv_stext namespace = lv_namespace devclass = iv_package unicode_checks = iv_version corrnum = iv_transport suppress_corr_check = abap_false EXCEPTIONS name_already_exists = 1 name_not_correct = 2 function_already_exists = 3 invalid_function_pool = 4 invalid_name = 5 too_many_functions = 6 no_modify_permission = 7 no_show_permission = 8 enqueue_system_failure = 9 canceled_in_corr = 10 undefined_error = 11 OTHERS = 12. CASE sy-subrc. WHEN 0. " Everything is ok WHEN 1 OR 3. " If the function group exists we need to manually update the short text update_func_group_short_text( iv_group = lv_group iv_short_text = lv_stext ). WHEN OTHERS. zcx_abapgit_exception=>raise_t100( ). ENDCASE. ENDMETHOD. METHOD functions. DATA: lv_area TYPE rs38l-area. FIELD-SYMBOLS: TYPE LINE OF ty_rs38l_incl_tt. lv_area = ms_item-obj_name. CALL FUNCTION 'RS_FUNCTION_POOL_CONTENTS' EXPORTING function_pool = lv_area TABLES functab = rt_functab EXCEPTIONS function_pool_not_found = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. * The result can also contain function which are lowercase. LOOP AT rt_functab ASSIGNING . TRANSLATE TO UPPER CASE. ENDLOOP. SORT rt_functab BY funcname ASCENDING. DELETE ADJACENT DUPLICATES FROM rt_functab COMPARING funcname. ENDMETHOD. METHOD get_abap_version. DATA: lt_includes TYPE ty_sobj_name_tt, ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, lo_xml TYPE REF TO zif_abapgit_xml_input. FIELD-SYMBOLS: LIKE LINE OF lt_includes. ii_xml->read( EXPORTING iv_name = 'INCLUDES' CHANGING cg_data = lt_includes ). LOOP AT lt_includes ASSIGNING . lo_xml = mo_files->read_xml( ). lo_xml->read( EXPORTING iv_name = 'PROGDIR' CHANGING cg_data = ls_progdir ). IF ls_progdir-uccheck IS INITIAL. CONTINUE. ELSEIF rv_abap_version IS INITIAL. rv_abap_version = ls_progdir-uccheck. CONTINUE. ELSEIF rv_abap_version <> ls_progdir-uccheck. *** All includes need to have the same ABAP language version zcx_abapgit_exception=>raise( 'different ABAP Language Versions' ). ENDIF. ENDLOOP. IF rv_abap_version IS INITIAL. set_abap_language_version( CHANGING cv_abap_language_version = rv_abap_version ). ENDIF. ENDMETHOD. METHOD includes. TYPES: BEGIN OF ty_reposrc, progname TYPE reposrc-progname, END OF ty_reposrc. DATA: lt_reposrc TYPE STANDARD TABLE OF ty_reposrc WITH DEFAULT KEY, ls_reposrc LIKE LINE OF lt_reposrc, lv_program TYPE program, lv_maintviewname LIKE LINE OF rt_includes, lv_offset_ns TYPE i, lv_tabix LIKE sy-tabix, lt_functab TYPE ty_rs38l_incl_tt, lt_tadir_includes TYPE HASHED TABLE OF objname WITH UNIQUE KEY table_line. FIELD-SYMBOLS: LIKE LINE OF rt_includes, LIKE LINE OF lt_functab. IF lines( mt_includes_cache ) > 0. rt_includes = mt_includes_cache. RETURN. ENDIF. lv_program = main_name( ). lt_functab = functions( ). CALL FUNCTION 'RS_GET_ALL_INCLUDES' EXPORTING program = lv_program TABLES includetab = rt_includes EXCEPTIONS not_existent = 1 no_program = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error from RS_GET_ALL_INCLUDES' ). ENDIF. LOOP AT lt_functab ASSIGNING . DELETE TABLE rt_includes FROM -include. ENDLOOP. * handle generated maintenance views IF ms_item-obj_name(1) <> '/'. "FGroup name does not contain a namespace lv_maintviewname = |L{ ms_item-obj_name }T00|. ELSE. "FGroup name contains a namespace lv_offset_ns = find( val = ms_item-obj_name+1 sub = '/' ). lv_offset_ns = lv_offset_ns + 2. lv_maintviewname = |{ ms_item-obj_name(lv_offset_ns) }L{ ms_item-obj_name+lv_offset_ns }T00|. ENDIF. READ TABLE rt_includes WITH KEY table_line = lv_maintviewname TRANSPORTING NO FIELDS. IF sy-subrc <> 0. APPEND lv_maintviewname TO rt_includes. ENDIF. SORT rt_includes. IF lines( rt_includes ) > 0. " check which includes have their own tadir entry " these includes might reside in a different package or might be shared between multiple function groups " or other programs and are hence no part of the to serialized FUGR object " they will be handled as individual objects when serializing their package " in addition, referenced XTI includes referencing (simple) transformations must be ignored SELECT obj_name INTO TABLE lt_tadir_includes FROM tadir FOR ALL ENTRIES IN rt_includes WHERE pgmid = 'R3TR' AND object = 'PROG' AND obj_name = rt_includes-table_line. LOOP AT rt_includes ASSIGNING . " skip autogenerated includes from Table Maintenance Generator IF CP 'LSVIM*'. DELETE rt_includes INDEX sy-tabix. CONTINUE. ENDIF. READ TABLE lt_tadir_includes WITH KEY table_line = TRANSPORTING NO FIELDS. IF sy-subrc = 0. DELETE rt_includes. CONTINUE. ENDIF. IF strlen( ) = 33 AND +30(3) = 'XTI'. "ignore referenced (simple) transformation includes DELETE rt_includes. CONTINUE. ENDIF. ENDLOOP. IF lines( rt_includes ) > 0. SELECT progname FROM reposrc INTO TABLE lt_reposrc FOR ALL ENTRIES IN rt_includes WHERE progname = rt_includes-table_line AND r3state = 'A'. ENDIF. SORT lt_reposrc BY progname ASCENDING. ENDIF. LOOP AT rt_includes ASSIGNING . lv_tabix = sy-tabix. * make sure the include exists READ TABLE lt_reposrc INTO ls_reposrc WITH KEY progname = BINARY SEARCH. IF sy-subrc <> 0. DELETE rt_includes INDEX lv_tabix. CONTINUE. ENDIF. "Make sure that the include does not belong to another function group IF is_part_of_other_fugr( ) = abap_true. DELETE rt_includes. ENDIF. ENDLOOP. APPEND lv_program TO rt_includes. SORT rt_includes. mt_includes_cache = rt_includes. ENDMETHOD. METHOD is_any_function_module_locked. DATA: lt_functions TYPE ty_rs38l_incl_tt. FIELD-SYMBOLS: TYPE rs38l_incl. TRY. lt_functions = functions( ). CATCH zcx_abapgit_exception. RETURN. ENDTRY. LOOP AT lt_functions ASSIGNING . IF exists_a_lock_entry_for( iv_lock_object = 'ESFUNCTION' iv_argument = |{ -funcname }| ) = abap_true. rv_any_function_module_locked = abap_true. EXIT. ENDIF. ENDLOOP. ENDMETHOD. METHOD is_any_include_locked. DATA: lt_includes TYPE ty_sobj_name_tt. FIELD-SYMBOLS: TYPE sobj_name. TRY. lt_includes = includes( ). CATCH zcx_abapgit_exception. RETURN. ENDTRY. LOOP AT lt_includes ASSIGNING . IF exists_a_lock_entry_for( iv_lock_object = 'ESRDIRE' iv_argument = |{ }| ) = abap_true. rv_is_any_include_locked = abap_true. EXIT. ENDIF. ENDLOOP. ENDMETHOD. METHOD is_function_group_locked. rv_is_functions_group_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' iv_argument = ms_item-obj_name iv_prefix = 'FG' ). ENDMETHOD. METHOD is_part_of_other_fugr. " make sure that the include belongs to the function group " like in LSEAPFAP Form TADIR_MAINTENANCE DATA ls_tadir TYPE tadir. DATA lv_namespace TYPE rs38l-namespace. DATA lv_function_group TYPE rs38l-area. DATA lv_include TYPE rs38l-include. rv_belongs_to_other_fugr = abap_false. IF iv_include(1) = 'L' OR iv_include+1 CS '/L'. lv_include = iv_include. ls_tadir-object = 'FUGR'. CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' IMPORTING namespace = lv_namespace group = lv_function_group CHANGING include = lv_include EXCEPTIONS OTHERS = 1. IF lv_function_group(1) = 'X'. " "EXIT"-function-module ls_tadir-object = 'FUGS'. ENDIF. IF sy-subrc = 0. CONCATENATE lv_namespace lv_function_group INTO ls_tadir-obj_name. " compare complete tadir key to distinguish between regular and exit function groups IF ls_tadir-obj_name <> ms_item-obj_name OR ls_tadir-object <> ms_item-obj_type. rv_belongs_to_other_fugr = abap_true. ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD main_name. DATA: lv_area TYPE rs38l-area, lv_namespace TYPE rs38l-namespace, lv_group TYPE rs38l-area. lv_area = ms_item-obj_name. CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT' EXPORTING complete_area = lv_area IMPORTING namespace = lv_namespace group = lv_group EXCEPTIONS include_not_exists = 1 group_not_exists = 2 no_selections = 3 no_function_include = 4 no_function_pool = 5 delimiter_wrong_position = 6 no_customer_function_group = 7 no_customer_function_include = 8 reserved_name_customer = 9 namespace_too_long = 10 area_length_error = 11 OTHERS = 12. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CONCATENATE lv_namespace 'SAPL' lv_group INTO rv_program. ENDMETHOD. METHOD serialize_functions. DATA: lt_source TYPE TABLE OF rssource, lt_functab TYPE ty_rs38l_incl_tt, lt_new_source TYPE rsfb_source, ls_function LIKE LINE OF rt_functions. FIELD-SYMBOLS: LIKE LINE OF lt_functab, TYPE LINE OF ty_function-documentation. lt_functab = functions( ). LOOP AT lt_functab ASSIGNING . * fm RPY_FUNCTIONMODULE_READ does not support source code * lines longer than 72 characters CLEAR ls_function. MOVE-CORRESPONDING TO ls_function. CLEAR lt_new_source. CLEAR lt_source. CALL FUNCTION 'RPY_FUNCTIONMODULE_READ_NEW' EXPORTING functionname = -funcname IMPORTING global_flag = ls_function-global_flag remote_call = ls_function-remote_call update_task = ls_function-update_task short_text = ls_function-short_text remote_basxml_supported = ls_function-remote_basxml TABLES import_parameter = ls_function-import changing_parameter = ls_function-changing export_parameter = ls_function-export tables_parameter = ls_function-tables exception_list = ls_function-exception documentation = ls_function-documentation source = lt_source CHANGING new_source = lt_new_source EXCEPTIONS error_message = 1 function_not_found = 2 invalid_name = 3 OTHERS = 4. IF sy-subrc = 2. CONTINUE. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error from RPY_FUNCTIONMODULE_READ_NEW' ). ENDIF. LOOP AT ls_function-documentation ASSIGNING . CLEAR -index. ENDLOOP. SELECT SINGLE exten3 INTO ls_function-exception_classes FROM enlfdir WHERE funcname = -funcname. "#EC CI_SUBRC APPEND ls_function TO rt_functions. IF NOT lt_new_source IS INITIAL. strip_generation_comments( CHANGING ct_source = lt_new_source ). mo_files->add_abap( iv_extra = -funcname it_abap = lt_new_source ). ELSE. strip_generation_comments( CHANGING ct_source = lt_source ). mo_files->add_abap( iv_extra = -funcname it_abap = lt_source ). ENDIF. ENDLOOP. ENDMETHOD. METHOD serialize_function_docs. FIELD-SYMBOLS LIKE LINE OF it_functions. zcl_abapgit_factory=>get_longtexts( )->serialize( iv_longtext_id = c_longtext_id_prog iv_object_name = iv_prog_name io_i18n_params = mo_i18n_params ii_xml = ii_xml ). LOOP AT it_functions ASSIGNING . zcl_abapgit_factory=>get_longtexts( )->serialize( iv_longtext_name = |LONGTEXTS_{ -funcname }| iv_longtext_id = c_longtext_id_func iv_object_name = -funcname io_i18n_params = mo_i18n_params ii_xml = ii_xml ). zcl_abapgit_factory=>get_longtexts( )->serialize( iv_longtext_name = |LONGTEXTS_{ -funcname }___EXC| iv_longtext_id = c_longtext_id_func_exc iv_object_name = -funcname io_i18n_params = mo_i18n_params ii_xml = ii_xml ). ENDLOOP. ENDMETHOD. METHOD serialize_includes. DATA: lt_includes TYPE ty_sobj_name_tt. FIELD-SYMBOLS: LIKE LINE OF lt_includes. lt_includes = includes( ). LOOP AT lt_includes ASSIGNING . * todo, filename is not correct, a include can be used in several programs serialize_program( is_item = ms_item io_files = mo_files iv_program = iv_extra = ). ENDLOOP. ENDMETHOD. METHOD serialize_texts. DATA: lt_tpool_i18n TYPE ty_tpools_i18n, lt_tpool TYPE textpool_table. FIELD-SYMBOLS LIKE LINE OF lt_tpool_i18n. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. " Table d010tinf stores info. on languages in which program is maintained " Select all active translations of program texts " Skip main language - it was already serialized SELECT DISTINCT language INTO CORRESPONDING FIELDS OF TABLE lt_tpool_i18n FROM d010tinf WHERE r3state = 'A' AND prog = iv_prog_name AND language <> mv_language ORDER BY language ##TOO_MANY_ITAB_FIELDS. mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'LANGUAGE' CHANGING ct_tab = lt_tpool_i18n ). SORT lt_tpool_i18n BY language ASCENDING. LOOP AT lt_tpool_i18n ASSIGNING . READ TEXTPOOL iv_prog_name LANGUAGE -language INTO lt_tpool. -textpool = add_tpool( lt_tpool ). ENDLOOP. IF lines( lt_tpool_i18n ) > 0. ii_xml->add( iv_name = 'I18N_TPOOL' ig_data = lt_tpool_i18n ). ENDIF. ENDMETHOD. METHOD serialize_xml. DATA: lt_includes TYPE ty_sobj_name_tt, lv_areat TYPE tlibt-areat. SELECT SINGLE areat INTO lv_areat FROM tlibt WHERE spras = mv_language AND area = ms_item-obj_name. "#EC CI_GENBUFF "#EC CI_SUBRC lt_includes = includes( ). ii_xml->add( iv_name = 'AREAT' ig_data = lv_areat ). ii_xml->add( iv_name = 'INCLUDES' ig_data = lt_includes ). ENDMETHOD. METHOD update_func_group_short_text. " We update the short text directly. " SE80 does the same in " Program SAPLSEUF / LSEUFF07 " FORM GROUP_CHANGE UPDATE tlibt SET areat = iv_short_text WHERE spras = mv_language AND area = iv_group. ENDMETHOD. METHOD update_where_used. * make extra sure the where-used list is updated after deletion * Experienced some problems with the T00 include * this method just tries to update everything DATA: lv_include LIKE LINE OF it_includes, lo_cross TYPE REF TO cl_wb_crossreference. LOOP AT it_includes INTO lv_include. CREATE OBJECT lo_cross EXPORTING p_name = lv_include p_include = lv_include. lo_cross->index_actualize( ). ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object~changed_by. TYPES: BEGIN OF ty_stamps, user TYPE syuname, date TYPE d, time TYPE t, END OF ty_stamps. DATA: lt_stamps TYPE STANDARD TABLE OF ty_stamps WITH DEFAULT KEY, lv_program TYPE program, lv_found TYPE abap_bool, lt_functions TYPE ty_rs38l_incl_tt. FIELD-SYMBOLS: LIKE LINE OF lt_functions, LIKE LINE OF mt_includes_all, LIKE LINE OF lt_stamps. lv_program = main_name( ). IF mt_includes_all IS INITIAL. CALL FUNCTION 'RS_GET_ALL_INCLUDES' EXPORTING program = lv_program TABLES includetab = mt_includes_all EXCEPTIONS not_existent = 1 no_program = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error from RS_GET_ALL_INCLUDES' ). ENDIF. ENDIF. " Check if changed_by for include object was requested LOOP AT mt_includes_all ASSIGNING WHERE table_line = to_upper( iv_extra ). lv_program = . lv_found = abap_true. EXIT. ENDLOOP. " Check if changed_by for function module was requested lt_functions = functions( ). LOOP AT lt_functions ASSIGNING WHERE funcname = to_upper( iv_extra ). lv_program = -include. lv_found = abap_true. EXIT. ENDLOOP. SELECT unam AS user udat AS date utime AS time FROM reposrc APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps WHERE progname = lv_program AND r3state = 'A' ORDER BY PRIMARY KEY. "#EC CI_SUBRC IF mt_includes_all IS NOT INITIAL AND lv_found = abap_false. SELECT unam AS user udat AS date utime AS time FROM reposrc APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps FOR ALL ENTRIES IN mt_includes_all WHERE progname = mt_includes_all-table_line AND r3state = 'A'. "#EC CI_SUBRC ENDIF. SELECT unam AS user udat AS date utime AS time FROM repotext " Program text pool APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps WHERE progname = lv_program AND r3state = 'A' ORDER BY PRIMARY KEY. "#EC CI_SUBRC SELECT vautor AS user vdatum AS date vzeit AS time FROM eudb " GUI APPENDING CORRESPONDING FIELDS OF TABLE lt_stamps WHERE relid = 'CU' AND name = lv_program AND srtf2 = 0 ORDER BY PRIMARY KEY ##TOO_MANY_ITAB_FIELDS. * Screens: username not stored in D020S database table SORT lt_stamps BY date DESCENDING time DESCENDING. READ TABLE lt_stamps INDEX 1 ASSIGNING . IF sy-subrc = 0. rv_user = -user. ELSE. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_area TYPE rs38l-area, lt_includes TYPE ty_sobj_name_tt. " FUGR related to change documents will be deleted by CHDO SELECT SINGLE fgrp FROM tcdrps INTO lv_area WHERE fgrp = ms_item-obj_name. IF sy-subrc = 0. RETURN. ENDIF. lt_includes = includes( ). lv_area = ms_item-obj_name. CALL FUNCTION 'RS_FUNCTION_POOL_DELETE' EXPORTING area = lv_area suppress_popups = abap_true skip_progress_ind = abap_true corrnum = iv_transport EXCEPTIONS canceled_in_corr = 1 enqueue_system_failure = 2 function_exist = 3 not_executed = 4 no_modify_permission = 5 no_show_permission = 6 permission_failure = 7 pool_not_exist = 8 cancelled = 9 OTHERS = 10. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. update_where_used( lt_includes ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_program_name TYPE syrepid, lv_abap_version TYPE trdir-uccheck, lt_functions TYPE ty_function_tt, lt_dynpros TYPE ty_dynpro_tt, ls_cua TYPE ty_cua. lv_abap_version = get_abap_version( io_xml ). deserialize_xml( ii_xml = io_xml iv_version = lv_abap_version iv_package = iv_package iv_transport = iv_transport ). io_xml->read( EXPORTING iv_name = 'FUNCTIONS' CHANGING cg_data = lt_functions ). deserialize_functions( it_functions = lt_functions ii_log = ii_log iv_version = lv_abap_version iv_package = iv_package iv_transport = iv_transport ). deserialize_includes( ii_xml = io_xml iv_package = iv_package ii_log = ii_log ). lv_program_name = main_name( ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. deserialize_texts( iv_prog_name = lv_program_name ii_xml = io_xml ). ENDIF. io_xml->read( EXPORTING iv_name = 'DYNPROS' CHANGING cg_data = lt_dynpros ). deserialize_dynpros( lt_dynpros ). io_xml->read( EXPORTING iv_name = 'CUA' CHANGING cg_data = ls_cua ). deserialize_cua( iv_program_name = lv_program_name is_cua = ls_cua ). deserialize_function_docs( iv_prog_name = lv_program_name it_functions = lt_functions ii_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_pool TYPE tlibg-area. lv_pool = ms_item-obj_name. CALL FUNCTION 'RS_FUNCTION_POOL_EXISTS' EXPORTING function_pool = lv_pool EXCEPTIONS pool_not_exists = 1. rv_bool = boolc( sy-subrc <> 1 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_program TYPE program. lv_program = main_name( ). IF is_function_group_locked( ) = abap_true OR is_any_include_locked( ) = abap_true OR is_any_function_module_locked( ) = abap_true OR is_any_dynpro_locked( lv_program ) = abap_true OR is_cua_locked( lv_program ) = abap_true OR is_text_locked( lv_program ) = abap_true. rv_is_locked = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, lt_functions TYPE ty_rs38l_incl_tt, lt_includes TYPE ty_sobj_name_tt. FIELD-SYMBOLS: LIKE LINE OF lt_functions, LIKE LINE OF lt_includes. ls_item-obj_type = 'PROG'. ls_item-obj_name = to_upper( iv_extra ). lt_functions = functions( ). LOOP AT lt_functions ASSIGNING WHERE funcname = ls_item-obj_name. ls_item-obj_name = -include. rv_exit = zcl_abapgit_objects_factory=>get_gui_jumper( )->jump( ls_item ). IF rv_exit = abap_true. RETURN. ENDIF. ENDLOOP. lt_includes = includes( ). LOOP AT lt_includes ASSIGNING WHERE table_line = ls_item-obj_name. rv_exit = zcl_abapgit_objects_factory=>get_gui_jumper( )->jump( ls_item ). IF rv_exit = abap_true. RETURN. ENDIF. ENDLOOP. " Otherwise covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. * function group SEUF * function group SIFP * function group SUNI DATA: lt_functions TYPE ty_function_tt, ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir, lv_program_name TYPE syrepid, lt_dynpros TYPE ty_dynpro_tt, ls_cua TYPE ty_cua. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. serialize_xml( io_xml ). lt_functions = serialize_functions( ). io_xml->add( iv_name = 'FUNCTIONS' ig_data = lt_functions ). serialize_includes( ). lv_program_name = main_name( ). ls_progdir = zcl_abapgit_factory=>get_sap_report( )->read_progdir( lv_program_name ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. serialize_texts( iv_prog_name = lv_program_name ii_xml = io_xml ). ENDIF. IF ls_progdir-subc = 'F'. lt_dynpros = serialize_dynpros( lv_program_name ). io_xml->add( iv_name = 'DYNPROS' ig_data = lt_dynpros ). ls_cua = serialize_cua( lv_program_name ). io_xml->add( iv_name = 'CUA' ig_data = ls_cua ). ENDIF. serialize_function_docs( iv_prog_name = lv_program_name it_functions = lt_functions ii_xml = io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ftgl IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cg_header TO . ASSERT sy-subrc = 0. CLEAR: . ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_toggle_id = ms_item-obj_name. TRY. CREATE DATA mr_toggle TYPE ('FTGL_S_WB_FEATURE_TOGGLE'). CATCH cx_root. zcx_abapgit_exception=>raise( |FTGL not supported in your NW release| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changedby FROM ('FTGL_ID') INTO rv_user WHERE feature_id = ms_item-obj_name AND version = 'A'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_return_code TYPE i. CALL METHOD ('CL_FEATURE_TOGGLE_OBJECT')=>delete EXPORTING iv_toggle_id = mv_toggle_id RECEIVING rv_rc = lv_return_code. IF lv_return_code <> 0. zcx_abapgit_exception=>raise( |Cannot delete feature toggle { mv_toggle_id }. | && |Error { sy-subrc } from cl_feature_toggle_object=>delete| ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_toggle TYPE REF TO object, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE data. ASSIGN mr_toggle->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'FTGL' CHANGING cg_data = ). TRY. CALL METHOD ('CL_FEATURE_TOGGLE_OBJECT')=>create_toggle_by_content EXPORTING is_content = RECEIVING ro_toggle = lo_toggle. CALL METHOD lo_toggle->('SAVE'). tadir_insert( iv_package ). corr_insert( iv_package ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. CALL METHOD ('CL_FEATURE_TOGGLE')=>is_defined EXPORTING iv_toggle_id = mv_toggle_id RECEIVING rc_exists = rv_bool. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_FTGL' iv_argument = |{ mv_toggle_id }*| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lx_error TYPE REF TO cx_root, lo_toggle TYPE REF TO object. FIELD-SYMBOLS: TYPE data. ASSIGN mr_toggle->* TO . ASSERT sy-subrc = 0. TRY. CALL METHOD ('CL_FEATURE_TOGGLE_OBJECT')=>create_toggle_by_id EXPORTING iv_toggle_id = mv_toggle_id RECEIVING ro_toggle = lo_toggle. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. CALL METHOD lo_toggle->('GET_CONTENT') RECEIVING rs_content = . clear_field( EXPORTING iv_fieldname = 'HEADER-OWNER' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'HEADER-CREATED_DATE' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'HEADER-CREATED_TIME' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'HEADER-CHANGEDBY ' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'HEADER-CHANGED_DATE' CHANGING cg_header = ). clear_field( EXPORTING iv_fieldname = 'HEADER-CHANGED_TIME' CHANGING cg_header = ). io_xml->add( iv_name = 'FTGL' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_form IMPLEMENTATION. METHOD build_extra_from_header. DATA lv_tdspras TYPE laiso. lv_tdspras = zcl_abapgit_convert=>conversion_exit_isola_output( is_header-tdspras ). rv_result = c_objectname_tdlines && '_' && lv_tdspras. ENDMETHOD. METHOD build_extra_from_header_old. rv_result = c_objectname_tdlines && '_' && is_header-tdspras. ENDMETHOD. METHOD compress_lines. DATA lv_string TYPE string. DATA li_xml TYPE REF TO zif_abapgit_xml_output. CREATE OBJECT li_xml TYPE zcl_abapgit_xml_output. li_xml->add( iv_name = c_objectname_tdlines ig_data = it_lines ). lv_string = li_xml->render( ). IF lv_string IS NOT INITIAL. mo_files->add_string( iv_extra = build_extra_from_header( is_form_data-form_header ) iv_ext = c_extension_xml iv_string = lv_string ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_form_name = ms_item-obj_name. ENDMETHOD. METHOD extract_tdlines. DATA lv_string TYPE string. DATA li_xml TYPE REF TO zif_abapgit_xml_input. TRY. lv_string = mo_files->read_string( iv_extra = build_extra_from_header( is_form_data-form_header ) iv_ext = c_extension_xml ). CATCH zcx_abapgit_exception. lv_string = mo_files->read_string( iv_extra = build_extra_from_header_old( is_form_data-form_header ) iv_ext = c_extension_xml ). ENDTRY. CREATE OBJECT li_xml TYPE zcl_abapgit_xml_input EXPORTING iv_xml = lv_string. li_xml->read( EXPORTING iv_name = c_objectname_tdlines CHANGING cg_data = rt_lines ). ENDMETHOD. METHOD find_form. DATA: lv_text_name TYPE thead-tdname. lv_text_name = iv_object_name. CALL FUNCTION 'SELECT_TEXT' EXPORTING database_only = abap_true id = 'TXT' language = '*' name = lv_text_name object = c_objectname_form TABLES selections = rt_text_header EXCEPTIONS OTHERS = 1 ##FM_SUBRC_OK. "#EC CI_SUBRC ENDMETHOD. METHOD get_last_changes. DATA: lv_form_name TYPE thead-tdform. CLEAR rs_last_changed. lv_form_name = iv_form_name. CALL FUNCTION 'READ_FORM' EXPORTING form = lv_form_name read_only_header = abap_true IMPORTING form_header = rs_last_changed. ENDMETHOD. METHOD order_check_and_insert. DATA: lv_order TYPE e071k-trkorr. CALL FUNCTION 'SAPSCRIPT_ORDER_CHECK' EXPORTING objecttype = ms_item-obj_type form = mv_form_name EXCEPTIONS invalid_input = 1 object_locked = 2 object_not_available = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'SAPSCRIPT_ORDER_INSERT' EXPORTING objecttype = ms_item-obj_type form = mv_form_name masterlang = mv_language CHANGING order = lv_order EXCEPTIONS invalid_input = 1 order_canceled = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: ls_last_changed TYPE ty_s_form_header. ls_last_changed = get_last_changes( ms_item-obj_name ). IF ls_last_changed-tdluser IS NOT INITIAL. rv_user = ls_last_changed-tdluser. ELSE. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. CALL FUNCTION 'DELETE_FORM' EXPORTING form = mv_form_name language = '*'. order_check_and_insert( ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lt_form_data TYPE ty_t_form_data. DATA: lt_lines TYPE ty_t_lines. FIELD-SYMBOLS: TYPE LINE OF ty_t_form_data. io_xml->read( EXPORTING iv_name = c_objectname_form CHANGING cg_data = lt_form_data ). LOOP AT lt_form_data ASSIGNING . lt_lines = extract_tdlines( ). _save_form( EXPORTING it_lines = lt_lines CHANGING cs_form_data = ). ENDLOOP. CALL FUNCTION 'SAPSCRIPT_DELETE_LOAD' EXPORTING delete = abap_true form = '*' write = space. tadir_insert( iv_package ). order_check_and_insert( ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA lv_lang TYPE sy-langu. * this will try to read the FORM in language EN * if it exists in other language, then "found" will be set to abap_false * so check the "olanguage" to see if the FORM exists CALL FUNCTION 'READ_FORM' EXPORTING form = mv_form_name read_only_header = abap_true IMPORTING olanguage = lv_lang. rv_bool = boolc( lv_lang IS NOT INITIAL ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_object TYPE seqg3-garg. " example lock entry "'001FORM ZTEST_SAPSCRIPT TXT' lv_object = |{ sy-mandt }{ ms_item-obj_type } { ms_item-obj_name }|. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESSFORM' iv_argument = lv_object ). ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS: LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMSSCF'. -dynpro = '1102'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=SHOW'. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'RSSCF-TDFORM'. -fval = ms_item-obj_name. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SE71' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lt_form_data TYPE ty_t_form_data. DATA: ls_form_data TYPE ty_s_form_data. DATA: lt_text_header TYPE ty_t_text_header. DATA: lt_lines TYPE ty_t_lines. DATA: lv_form_found TYPE abap_bool. FIELD-SYMBOLS: LIKE LINE OF lt_text_header. lt_text_header = find_form( ms_item-obj_name ). LOOP AT lt_text_header ASSIGNING . CLEAR lt_lines. CLEAR ls_form_data. _read_form( EXPORTING is_text_header = IMPORTING ev_form_found = lv_form_found es_form_data = ls_form_data et_lines = lt_lines ). IF lv_form_found = abap_true. _clear_changed_fields( CHANGING cs_form_data = ls_form_data ). compress_lines( is_form_data = ls_form_data it_lines = lt_lines ). INSERT ls_form_data INTO TABLE lt_form_data. ENDIF. ENDLOOP. IF lt_form_data IS NOT INITIAL. io_xml->add( iv_name = c_objectname_form ig_data = lt_form_data ). ENDIF. ENDMETHOD. METHOD _clear_changed_fields. CLEAR: cs_form_data-form_header-tdfuser, cs_form_data-form_header-tdfdate, cs_form_data-form_header-tdftime, cs_form_data-form_header-tdfreles, cs_form_data-form_header-tdluser, cs_form_data-form_header-tdldate, cs_form_data-form_header-tdltime, cs_form_data-form_header-tdlreles. CLEAR: cs_form_data-text_header-tdfuser, cs_form_data-text_header-tdfdate, cs_form_data-text_header-tdftime, cs_form_data-text_header-tdfreles, cs_form_data-text_header-tdluser, cs_form_data-text_header-tdldate, cs_form_data-text_header-tdltime, cs_form_data-text_header-tdlreles. ENDMETHOD. METHOD _read_form. CLEAR es_form_data. CALL FUNCTION 'READ_FORM' EXPORTING form = is_text_header-tdform language = is_text_header-tdspras status = ' ' IMPORTING form_header = es_form_data-form_header found = ev_form_found header = es_form_data-text_header olanguage = es_form_data-orig_language TABLES form_lines = et_lines pages = es_form_data-pages page_windows = es_form_data-page_windows paragraphs = es_form_data-paragraphs strings = es_form_data-strings tabs = es_form_data-tabs windows = es_form_data-windows. _sort_tdlines_by_windows( CHANGING ct_form_windows = es_form_data-windows ct_lines = et_lines ). es_form_data-form_header-tdversion = '00001'. es_form_data-text_header-tdversion = '00001'. ENDMETHOD. METHOD _save_form. CALL FUNCTION 'SAVE_FORM' EXPORTING form_header = cs_form_data-form_header TABLES form_lines = it_lines pages = cs_form_data-pages page_windows = cs_form_data-page_windows paragraphs = cs_form_data-paragraphs strings = cs_form_data-strings tabs = cs_form_data-tabs windows = cs_form_data-windows. CALL FUNCTION 'SAPSCRIPT_CHANGE_OLANGUAGE' EXPORTING forced = abap_true name = cs_form_data-text_header-tdname object = cs_form_data-text_header-tdobject olanguage = cs_form_data-orig_language EXCEPTIONS OTHERS = 1 ##FM_SUBRC_OK. "#EC CI_SUBRC ENDMETHOD. METHOD _sort_tdlines_by_windows. DATA lt_lines TYPE ty_t_lines. DATA ls_lines LIKE LINE OF lt_lines. DATA ls_form_windows LIKE LINE OF ct_form_windows. DATA lv_elt_windows TYPE tdformat VALUE '/W'. DATA lv_firstloop TYPE abap_bool. lt_lines = ct_lines. CLEAR ct_lines. SORT ct_form_windows BY tdwindow. LOOP AT ct_form_windows INTO ls_form_windows. lv_firstloop = abap_true. READ TABLE lt_lines INTO ls_lines WITH KEY tdformat = lv_elt_windows tdline = ls_form_windows-tdwindow. IF sy-subrc <> 0. CONTINUE. " current loop ENDIF. LOOP AT lt_lines INTO ls_lines FROM sy-tabix. IF lv_firstloop = abap_false AND ls_lines-tdformat = lv_elt_windows. EXIT. ENDIF. APPEND ls_lines TO ct_lines. lv_firstloop = abap_false. ENDLOOP. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_fdt0 IMPLEMENTATION. METHOD before_xml_deserialize. DATA lv_application_id TYPE fdt_admn_0000s-application_id. DATA lv_timestamp TYPE timestamp. DATA lv_transport TYPE string. DATA lv_dlvunit TYPE tdevc-dlvunit. DATA lo_node_local TYPE REF TO if_ixml_element. DATA lo_node_package TYPE REF TO if_ixml_element. DATA lo_node_id TYPE REF TO if_ixml_element. DATA lo_xml_element TYPE REF TO if_ixml_element. DATA lv_count TYPE i. lo_node_local = co_dom_tree->find_from_name( name = 'Local' namespace = 'FDTNS' ). IF lo_node_local IS BOUND. ev_is_local = lo_node_local->get_value( ). ENDIF. lo_node_package = co_dom_tree->find_from_name( name = 'DevelopmentPackage' namespace = 'FDTNS' ). IF lo_node_package IS BOUND. lo_node_package->set_value( |{ iv_package }| ). ENDIF. lo_node_id = co_dom_tree->find_from_name( name = 'ApplicationId' namespace = 'FDTNS' ). IF lo_node_id IS BOUND. lv_application_id = lo_node_id->get_value( ). SELECT COUNT( * ) FROM fdt_admn_0000s INTO lv_count WHERE object_type = 'AP' AND id = lv_application_id AND deleted = ''. ev_create = boolc( lv_count = 0 ). ENDIF. " Fill in user/time/system-specific fields GET TIME STAMP FIELD lv_timestamp. lv_transport = |${ sy-sysid }0000000000000001|. lo_xml_element = co_dom_tree->get_root_element( ). IF ev_create = abap_true. set_field( EXPORTING iv_name = 'CreationUser' iv_value = |{ sy-uname }| CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'CreationTimestamp' iv_value = |{ lv_timestamp }| CHANGING co_ixml_element = lo_xml_element ). ENDIF. set_field( EXPORTING iv_name = 'ChangeUser' iv_value = |{ sy-uname }| CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'ChangeTimestamp' iv_value = |{ lv_timestamp }| CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'User' iv_value = |{ sy-uname }| CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'Timestamp' iv_value = |{ lv_timestamp }| CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'Trrequest' iv_value = lv_transport CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'Trversion' iv_value = '000001' CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'Trtimestamp' iv_value = |{ lv_timestamp }| CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'Trsysid' iv_value = |{ sy-sysid }| CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'Trclient' iv_value = |{ sy-mandt }| CHANGING co_ixml_element = lo_xml_element ). set_field( EXPORTING iv_name = 'OversId' iv_value = |{ lv_application_id }| CHANGING co_ixml_element = lo_xml_element ). SELECT SINGLE dlvunit FROM tdevc INTO lv_dlvunit WHERE devclass = iv_package. IF sy-subrc = 0. set_field( EXPORTING iv_name = 'SoftwareComponent' iv_value = |{ lv_dlvunit }| CHANGING co_ixml_element = lo_xml_element ). ENDIF. lo_xml_element->set_attribute( name = 'Client' value = |{ sy-mandt }| ). lo_xml_element->set_attribute( name = 'Date' value = |{ sy-datum }| ). lo_xml_element->set_attribute( name = 'SAPRelease' value = |{ sy-saprl }| ). lo_xml_element->set_attribute( name = 'Server' value = |{ sy-host }| ). lo_xml_element->set_attribute( name = 'SourceExportReqID' value = lv_transport ). lo_xml_element->set_attribute( name = 'SystemID' value = |{ sy-sysid }| ). lo_xml_element->set_attribute( name = 'Time' value = |{ sy-uzeit }| ). lo_xml_element->set_attribute( name = 'User' value = |{ sy-uname }| ). ENDMETHOD. METHOD check_is_local. SELECT SINGLE local_object FROM fdt_admn_0000s INTO rv_is_local WHERE object_type = 'AP' AND name = ms_item-obj_name. ENDMETHOD. METHOD filter_xml_serialize. DATA lo_components_node TYPE REF TO if_ixml_element. lo_components_node = co_ixml_element->find_from_name( name = 'ComponentReleases' namespace = 'FDTNS' ). IF lo_components_node IS BOUND. co_ixml_element->remove_child( lo_components_node ). ENDIF. " Clear user/time/system-specific fields set_field( EXPORTING iv_name = 'CreationUser' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'CreationTimestamp' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'ChangeUser' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'ChangeTimestamp' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'User' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'Timestamp' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'Trrequest' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'Trversion' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'Trtimestamp' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'Trsysid' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'Trclient' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'OversId' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'SoftwareComponent' CHANGING co_ixml_element = co_ixml_element ). set_field( EXPORTING iv_name = 'DevelopmentPackage' CHANGING co_ixml_element = co_ixml_element ). " Clear attributes of root FDTNS:Fdt node co_ixml_element->set_attribute( name = 'Client' value = '' ). co_ixml_element->set_attribute( name = 'Date' value = '' ). co_ixml_element->set_attribute( name = 'SAPRelease' value = '' ). co_ixml_element->set_attribute( name = 'Server' value = '' ). co_ixml_element->set_attribute( name = 'SourceExportReqID' value = '' ). co_ixml_element->set_attribute( name = 'SystemID' value = '' ). co_ixml_element->set_attribute( name = 'Time' value = '' ). co_ixml_element->set_attribute( name = 'User' value = '' ). ENDMETHOD. METHOD get_application_id. SELECT SINGLE application_id FROM fdt_admn_0000s INTO rv_application_id WHERE object_type = 'AP' AND name = ms_item-obj_name. ENDMETHOD. METHOD set_field. DATA: lo_node_collection TYPE REF TO if_ixml_node_collection, lo_node TYPE REF TO if_ixml_node, lv_index TYPE i. lo_node_collection = co_ixml_element->get_elements_by_tag_name( namespace = 'FDTNS' name = iv_name ). lv_index = 0. WHILE lv_index < lo_node_collection->get_length( ). lo_node = lo_node_collection->get_item( lv_index ). lo_node->set_value( iv_value ). lv_index = lv_index + 1. ENDWHILE. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lv_ch_user TYPE fdt_admn_0000s-ch_user. SELECT SINGLE ch_user FROM fdt_admn_0000s INTO lv_ch_user WHERE object_type = 'AP' AND name = ms_item-obj_name. rv_user = lv_ch_user. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA lv_is_local TYPE abap_bool. DATA lt_application_id TYPE TABLE OF fdt_admn_0000s-application_id. DATA ls_object_category_sel TYPE if_fdt_query=>s_object_category_sel. DATA lv_failure TYPE abap_bool. DATA lx_fdt_input TYPE REF TO cx_fdt_input. lv_is_local = check_is_local( ). SELECT application_id FROM fdt_admn_0000s INTO TABLE lt_application_id WHERE object_type = 'AP' AND name = ms_item-obj_name ORDER BY application_id. ls_object_category_sel-system_objects = 'X'. TRY. IF lv_is_local = abap_true. cl_fdt_delete_handling=>mark_for_delete_via_job( EXPORTING is_object_category_sel = ls_object_category_sel ita_application_id = lt_application_id iv_background = abap_true iv_local_option = '1' iv_appl_transported_option = '2' iv_obj_transported_option = '2' IMPORTING ev_failure = lv_failure ). IF lv_failure IS INITIAL. cl_fdt_delete_handling=>delete_logical_via_job( EXPORTING is_object_category_sel = ls_object_category_sel ita_application_id = lt_application_id iv_retention_time = 0 iv_background = abap_true iv_local_option = '1' iv_appl_transported_option = '2' iv_obj_transported_option = '2' IMPORTING ev_failure = lv_failure ). IF lv_failure IS INITIAL. cl_fdt_delete_handling=>delete_physical_via_job( EXPORTING is_object_category_sel = ls_object_category_sel ita_application_id = lt_application_id iv_retention_time = 0 iv_background = abap_true iv_local_option = '1' iv_appl_transported_option = '2' IMPORTING ev_failure = lv_failure ). ENDIF. ENDIF. ELSE. tadir_insert( iv_package ). corr_insert( iv_package ). cl_fdt_delete_handling=>mark_for_delete_via_job( EXPORTING is_object_category_sel = ls_object_category_sel ita_application_id = lt_application_id iv_background = abap_true iv_local_option = '2' iv_appl_transported_option = '1' iv_obj_transported_option = '1' IMPORTING ev_failure = lv_failure ). IF lv_failure IS INITIAL. cl_fdt_delete_handling=>delete_logical_via_job( EXPORTING is_object_category_sel = ls_object_category_sel ita_application_id = lt_application_id iv_retention_time = 0 iv_background = abap_true iv_local_option = '2' iv_appl_transported_option = '1' iv_obj_transported_option = '1' IMPORTING ev_failure = lv_failure ). IF lv_failure IS INITIAL. cl_fdt_delete_handling=>delete_physical_via_job( EXPORTING is_object_category_sel = ls_object_category_sel ita_application_id = lt_application_id iv_retention_time = 0 iv_background = abap_true iv_local_option = '2' iv_appl_transported_option = '1' IMPORTING ev_failure = lv_failure ). ENDIF. ENDIF. ENDIF. IF lv_failure = abap_true. zcx_abapgit_exception=>raise( |Error deleting { ms_item-obj_type } { ms_item-obj_name }| ). ENDIF. CATCH cx_fdt_input INTO lx_fdt_input. zcx_abapgit_exception=>raise_with_text( lx_fdt_input ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA lo_dexc TYPE REF TO if_fdt_data_exchange. DATA lx_fdt_input TYPE REF TO cx_fdt_input. DATA lo_dom_tree TYPE REF TO if_ixml_document. DATA lv_transportable_package TYPE abap_bool. DATA lv_is_local TYPE abap_bool. DATA lt_message TYPE if_fdt_types=>t_message. DATA lv_create TYPE abap_bool. FIELD-SYMBOLS TYPE if_fdt_types=>s_message. lo_dom_tree = io_xml->get_raw( ). before_xml_deserialize( EXPORTING iv_package = iv_package IMPORTING ev_create = lv_create ev_is_local = lv_is_local CHANGING co_dom_tree = lo_dom_tree ). lv_transportable_package = zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ). IF lv_transportable_package = abap_true AND lv_is_local = abap_true. zcx_abapgit_exception=>raise( 'Local applications can only be imported into a local package' ). ELSEIF lv_transportable_package = abap_false AND lv_is_local = abap_false. zcx_abapgit_exception=>raise( 'Transportable application can only be imported into transportable package' ). ENDIF. lo_dexc = cl_fdt_factory=>if_fdt_factory~get_instance( )->get_data_exchange( ). TRY. IF lv_is_local = abap_true. "Local Object lo_dexc->import_xml( EXPORTING io_dom_tree = lo_dom_tree iv_create = lv_create iv_activate = abap_true iv_simulate = abap_false IMPORTING et_message = lt_message ). ELSE. "Transportable Object tadir_insert( iv_package ). corr_insert( iv_package ). lo_dexc->import_xml( EXPORTING io_dom_tree = lo_dom_tree iv_create = lv_create iv_activate = abap_true iv_simulate = abap_false iv_workbench_trrequest = iv_transport IMPORTING et_message = lt_message ). ENDIF. LOOP AT lt_message ASSIGNING . ii_log->add( iv_msg = -text iv_type = -msgty ). ENDLOOP. CATCH cx_fdt_input INTO lx_fdt_input. zcx_abapgit_exception=>raise_with_text( lx_fdt_input ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA lv_count TYPE i. SELECT COUNT( * ) FROM fdt_admn_0000s INTO lv_count WHERE object_type = 'AP' AND name = ms_item-obj_name AND deleted = ''. rv_bool = boolc( lv_count > 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. DATA lo_local_version_output TYPE REF TO zcl_abapgit_xml_output. DATA lo_local_version_input TYPE REF TO zcl_abapgit_xml_input. CREATE OBJECT lo_local_version_output. zif_abapgit_object~serialize( lo_local_version_output ). CREATE OBJECT lo_local_version_input EXPORTING iv_xml = lo_local_version_output->zif_abapgit_xml_output~render( ). CREATE OBJECT ri_comparator TYPE zcl_abapgit_object_tabl_compar EXPORTING ii_local = lo_local_version_input. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. DATA lv_application_id TYPE fdt_admn_0000s-application_id. DATA lx_fdt_input TYPE REF TO cx_fdt_input. DATA lo_instance TYPE REF TO if_fdt_admin_data. DATA lt_version TYPE if_fdt_admin_data=>ts_version. DATA lv_index TYPE sy-tabix. FIELD-SYMBOLS LIKE LINE OF lt_version. lv_application_id = get_application_id( ). TRY. cl_fdt_factory=>get_instance_generic( EXPORTING iv_id = lv_application_id IMPORTING eo_instance = lo_instance ). CATCH cx_fdt_input INTO lx_fdt_input. zcx_abapgit_exception=>raise_with_text( lx_fdt_input ). ENDTRY. lo_instance->get_versions( IMPORTING ets_version = lt_version ). lv_index = lines( lt_version ). READ TABLE lt_version ASSIGNING INDEX lv_index. rv_active = boolc( -state = 'A' ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA lv_application_id TYPE string. lv_application_id = get_application_id( ). rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'FDT_ENQUEUE_ID' iv_argument = |$ST{ lv_application_id }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. DATA lv_application_id TYPE fdt_admn_0000s-application_id. DATA lx_root TYPE REF TO cx_root. DATA lo_fdt_wd TYPE REF TO if_fdt_wd_factory. lv_application_id = get_application_id( ). IF lv_application_id IS NOT INITIAL. TRY. lo_fdt_wd = cl_fdt_wd_factory=>if_fdt_wd_factory~get_instance( ). lo_fdt_wd->get_ui_execution( )->execute_workbench( iv_id = lv_application_id ). CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ELSE. zcx_abapgit_exception=>raise( 'Could not open BRF+ Workbench' ). ENDIF. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA lo_dexc TYPE REF TO if_fdt_data_exchange. DATA lv_application_id TYPE fdt_admn_0000s-application_id. DATA lx_fdt_input TYPE REF TO cx_fdt_input. DATA lv_xml_fdt0_application TYPE string. DATA lo_xml_document TYPE REF TO if_ixml_document. DATA lo_xml_element TYPE REF TO if_ixml_element. lv_application_id = get_application_id( ). lo_dexc = cl_fdt_factory=>if_fdt_factory~get_instance( )->get_data_exchange( ). TRY. lo_dexc->export_xml_application( EXPORTING iv_application_id = lv_application_id iv_schema = if_fdt_data_exchange=>gc_xml_schema_type_external iv_xml_version = if_fdt_data_exchange=>gc_xml_version IMPORTING ev_string = lv_xml_fdt0_application ). lo_xml_document = cl_ixml_80_20=>parse_to_document( stream_string = lv_xml_fdt0_application ). lo_xml_element = lo_xml_document->get_root_element( ). filter_xml_serialize( CHANGING co_ixml_element = lo_xml_element ). io_xml->set_raw( lo_xml_element ). CATCH cx_fdt_input INTO lx_fdt_input. zcx_abapgit_exception=>raise_with_text( lx_fdt_input ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_ENSC IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lv_spot_name TYPE enhspotcompositename, li_spot_ref TYPE REF TO if_enh_spot_composite, lo_spot_ref TYPE REF TO cl_enh_spot_composite. lv_spot_name = ms_item-obj_name. TRY. li_spot_ref = cl_enh_factory=>get_enhancement_spot_comp( lock = '' run_dark = abap_true name = lv_spot_name ). lo_spot_ref ?= li_spot_ref. lo_spot_ref->if_enh_spot_composite~get_change_attributes( IMPORTING changedby = rv_user ). CATCH cx_root. rv_user = c_user_unknown. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_spot_name TYPE enhspotcompositename, lv_message TYPE string, lx_root TYPE REF TO cx_root, li_spot_ref TYPE REF TO if_enh_spot_composite. lv_spot_name = ms_item-obj_name. TRY. li_spot_ref = cl_enh_factory=>get_enhancement_spot_comp( lock = abap_true run_dark = abap_true name = lv_spot_name ). IF li_spot_ref IS BOUND. li_spot_ref->if_enh_object~delete( nevertheless_delete = abap_true run_dark = abap_true ). ENDIF. li_spot_ref->if_enh_object~unlock( ). CATCH cx_enh_root INTO lx_root. lv_message = `Error occurred while deleting ENSC: ` && lx_root->get_text( ). zcx_abapgit_exception=>raise( lv_message ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_spot_name TYPE enhspotcompositename, lv_message TYPE string, lv_enh_shtext TYPE string, lv_enh_spot TYPE enhspotname, lt_enh_spots TYPE enhspotname_it, lt_comp_spots TYPE enhspotname_it, lx_root TYPE REF TO cx_root, lv_package LIKE iv_package, li_spot_ref TYPE REF TO if_enh_spot_composite, lo_spot_ref TYPE REF TO cl_enh_spot_composite. lv_spot_name = ms_item-obj_name. io_xml->read( EXPORTING iv_name = 'SHORTTEXT' CHANGING cg_data = lv_enh_shtext ). io_xml->read( EXPORTING iv_name = 'ENH_SPOTS' "Enhancement spots CHANGING cg_data = lt_enh_spots ). io_xml->read( EXPORTING iv_name = 'COMP_ENH_SPOTS' "Composite enhancement spots CHANGING cg_data = lt_comp_spots ). IF zif_abapgit_object~exists( ) = abap_true. zif_abapgit_object~delete( iv_package = iv_package iv_transport = iv_transport ). ENDIF. lv_package = iv_package. TRY. cl_enh_factory=>create_enhancement_spot_comp( EXPORTING name = lv_spot_name run_dark = abap_true IMPORTING composite = li_spot_ref CHANGING devclass = lv_package ). lo_spot_ref ?= li_spot_ref. lo_spot_ref->if_enh_object_docu~set_shorttext( lv_enh_shtext ). "Add subsequent enhancement spots LOOP AT lt_enh_spots INTO lv_enh_spot. lo_spot_ref->if_enh_spot_composite~add_enh_spot_child( lv_enh_spot ). ENDLOOP. "Add subsequent composite enhancement spots LOOP AT lt_comp_spots INTO lv_enh_spot. lo_spot_ref->if_enh_spot_composite~add_composite_child( lv_enh_spot ). ENDLOOP. lo_spot_ref->if_enh_object~save( ). lo_spot_ref->if_enh_object~activate( ). lo_spot_ref->if_enh_object~unlock( ). zcl_abapgit_sotr_handler=>create_sotr( iv_package = iv_package io_xml = io_xml ). CATCH cx_enh_root INTO lx_root. lv_message = `Error occurred while deserializing ENSC: ` && lx_root->get_text( ). zcx_abapgit_exception=>raise( lv_message ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_spot_name TYPE enhspotcompositename. lv_spot_name = ms_item-obj_name. TRY. cl_enh_factory=>get_enhancement_spot_comp( lock = '' run_dark = abap_true name = lv_spot_name ). rv_bool = abap_true. CATCH cx_enh_root. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_spot_name TYPE enhspotcompositename, lv_message TYPE string, lv_enh_shtext TYPE string, lt_enh_spots TYPE enhspotname_it, lt_comp_spots TYPE enhspotname_it, lx_root TYPE REF TO cx_root, li_spot_ref TYPE REF TO if_enh_spot_composite, lo_spot_ref TYPE REF TO cl_enh_spot_composite. lv_spot_name = ms_item-obj_name. TRY. li_spot_ref = cl_enh_factory=>get_enhancement_spot_comp( lock = '' run_dark = abap_true name = lv_spot_name ). lo_spot_ref ?= li_spot_ref. lv_enh_shtext = li_spot_ref->if_enh_object_docu~get_shorttext( ). "find subsequent enhancement spots lt_enh_spots = lo_spot_ref->if_enh_spot_composite~get_enh_spot_childs( ). "find subsequent composite enhancement spots lt_comp_spots = lo_spot_ref->if_enh_spot_composite~get_composite_childs( ). io_xml->add( ig_data = lv_enh_shtext iv_name = 'SHORTTEXT' ). io_xml->add( ig_data = lt_enh_spots iv_name = 'ENH_SPOTS' ). "Enhancement spots io_xml->add( ig_data = lt_comp_spots iv_name = 'COMP_ENH_SPOTS' ). "Composite enhancement spots zcl_abapgit_sotr_handler=>read_sotr( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params io_xml = io_xml ). CATCH cx_enh_root INTO lx_root. lv_message = `Error occurred while serializing ENSC: ` && lx_root->get_text( ). zcx_abapgit_exception=>raise( lv_message ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enqu IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. SELECT SINGLE as4user FROM dd25l INTO rv_user WHERE viewname = ms_item-obj_name AND as4local = 'A' AND as4vers = '0000'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. delete_ddic( 'L' ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_name TYPE ddobjname, ls_dd25v TYPE dd25v, lt_dd26e TYPE TABLE OF dd26e, lt_dd27p TYPE ty_dd27p. io_xml->read( EXPORTING iv_name = 'DD25V' CHANGING cg_data = ls_dd25v ). io_xml->read( EXPORTING iv_name = 'DD26E_TABLE' CHANGING cg_data = lt_dd26e ). io_xml->read( EXPORTING iv_name = 'DD27P_TABLE' CHANGING cg_data = lt_dd27p ). corr_insert( iv_package = iv_package ig_object_class = 'DICT' ). lv_name = ms_item-obj_name. CALL FUNCTION 'DDIF_ENQU_PUT' EXPORTING name = lv_name dd25v_wa = ls_dd25v TABLES dd26e_tab = lt_dd26e dd27p_tab = lt_dd27p EXCEPTIONS enqu_not_found = 1 name_inconsistent = 2 enqu_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_viewname TYPE dd25l-viewname. SELECT SINGLE viewname FROM dd25l INTO lv_viewname WHERE viewname = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECT=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_name TYPE ddobjname, lv_state TYPE ddgotstate, ls_dd25v TYPE dd25v, lt_dd26e TYPE TABLE OF dd26e, lt_dd27p TYPE ty_dd27p. lv_name = ms_item-obj_name. CALL FUNCTION 'DDIF_ENQU_GET' EXPORTING name = lv_name state = 'A' langu = mv_language IMPORTING gotstate = lv_state dd25v_wa = ls_dd25v TABLES dd26e_tab = lt_dd26e dd27p_tab = lt_dd27p EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF ls_dd25v IS INITIAL OR lv_state <> 'A'. RETURN. ENDIF. CLEAR: ls_dd25v-as4user, ls_dd25v-as4date, ls_dd25v-as4time, ls_dd25v-as4local, ls_dd25v-as4vers. _clear_dd27p_fields( CHANGING ct_dd27p = lt_dd27p ). io_xml->add( iv_name = 'DD25V' ig_data = ls_dd25v ). io_xml->add( ig_data = lt_dd26e iv_name = 'DD26E_TABLE' ). io_xml->add( ig_data = lt_dd27p iv_name = 'DD27P_TABLE' ). ENDMETHOD. METHOD _clear_dd27p_fields. FIELD-SYMBOLS TYPE dd27p. LOOP AT ct_dd27p ASSIGNING . "taken from table CLEAR -headlen. CLEAR -scrlen1. CLEAR -scrlen2. CLEAR -scrlen3. CLEAR -intlen. CLEAR -outputlen. CLEAR -flength. CLEAR -ddtext. CLEAR -reptext. CLEAR -scrtext_s. CLEAR -scrtext_m. CLEAR -scrtext_l. CLEAR -rollname. CLEAR -rollnamevi. CLEAR -entitytab. CLEAR -datatype. CLEAR -inttype. CLEAR -ddlanguage. CLEAR -domname. CLEAR -signflag. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enhs IMPLEMENTATION. METHOD factory. CASE iv_tool. WHEN cl_enh_tool_badi_def=>tooltype. CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enhs_badi_d. WHEN cl_enh_tool_hook_def=>tool_type. CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enhs_hook_d. WHEN OTHERS. zcx_abapgit_exception=>raise( |ENHS: Unsupported tool { iv_tool }| ). ENDCASE. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_spot_name TYPE enhspotname, li_spot_ref TYPE REF TO if_enh_spot_tool. lv_spot_name = ms_item-obj_name. TRY. li_spot_ref = cl_enh_factory=>get_enhancement_spot( spot_name = lv_spot_name run_dark = abap_true ). li_spot_ref->get_attributes( IMPORTING changedby = rv_user ). CATCH cx_enh_root. rv_user = c_user_unknown. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_spot_name TYPE enhspotname, lx_enh_root TYPE REF TO cx_enh_root, li_enh_object TYPE REF TO if_enh_object. zcl_abapgit_sotr_handler=>delete_sotr( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name ). zcl_abapgit_sots_handler=>delete_sots( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name ). lv_spot_name = ms_item-obj_name. TRY. li_enh_object ?= cl_enh_factory=>get_enhancement_spot( spot_name = lv_spot_name run_dark = abap_true lock = abap_true ). li_enh_object->delete( nevertheless_delete = abap_true run_dark = abap_true ). li_enh_object->unlock( ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_parent TYPE enhspotcompositename, lv_spot_name TYPE enhspotname, lv_tool TYPE enhspottooltype, lv_package LIKE iv_package, lx_enh_root TYPE REF TO cx_enh_root, li_spot_ref TYPE REF TO if_enh_spot_tool, li_enhs TYPE REF TO zif_abapgit_object_enhs. IF zif_abapgit_object~exists( ) = abap_true. zif_abapgit_object~delete( iv_package = iv_package iv_transport = iv_transport ). ENDIF. io_xml->read( EXPORTING iv_name = 'TOOL' CHANGING cg_data = lv_tool ). lv_spot_name = ms_item-obj_name. lv_package = iv_package. TRY. cl_enh_factory=>create_enhancement_spot( EXPORTING spot_name = lv_spot_name tooltype = lv_tool dark = abap_false compositename = lv_parent IMPORTING spot = li_spot_ref CHANGING devclass = lv_package ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. li_enhs = factory( lv_tool ). li_enhs->deserialize( ii_xml = io_xml iv_package = iv_package ii_enh_spot_tool = li_spot_ref ). zcl_abapgit_sotr_handler=>create_sotr( iv_package = iv_package io_xml = io_xml ). zcl_abapgit_sots_handler=>create_sots( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_spot_name TYPE enhspotname, li_spot_ref TYPE REF TO if_enh_spot_tool. lv_spot_name = ms_item-obj_name. TRY. li_spot_ref = cl_enh_factory=>get_enhancement_spot( spot_name = lv_spot_name run_dark = abap_true ). rv_bool = abap_true. CATCH cx_enh_root. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_spot_name TYPE enhspotname, li_spot_ref TYPE REF TO if_enh_spot_tool, li_enhs TYPE REF TO zif_abapgit_object_enhs, lx_enh_root TYPE REF TO cx_enh_root. lv_spot_name = ms_item-obj_name. TRY. li_spot_ref = cl_enh_factory=>get_enhancement_spot( spot_name = lv_spot_name run_dark = abap_true ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. li_enhs = factory( li_spot_ref->get_tool( ) ). li_enhs->serialize( ii_xml = io_xml ii_enh_spot_tool = li_spot_ref ). zcl_abapgit_sotr_handler=>read_sotr( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params io_xml = io_xml ). zcl_abapgit_sots_handler=>read_sots( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params io_xml = io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enho IMPLEMENTATION. METHOD factory. CASE iv_tool. WHEN cl_enh_tool_badi_impl=>tooltype. CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_badi EXPORTING is_item = ms_item. WHEN cl_enh_tool_hook_impl=>tooltype. CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_hook EXPORTING is_item = ms_item io_files = mo_files. WHEN cl_enh_tool_class=>tooltype. CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_class EXPORTING is_item = ms_item io_files = mo_files. WHEN cl_enh_tool_intf=>tooltype. CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_intf EXPORTING is_item = ms_item io_files = mo_files. WHEN cl_wdr_cfg_enhancement=>tooltype. CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_wdyc EXPORTING is_item = ms_item. WHEN 'FUGRENH'. CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_fugr EXPORTING is_item = ms_item io_files = mo_files. WHEN 'WDYENH'. CREATE OBJECT ri_enho TYPE zcl_abapgit_object_enho_wdyn EXPORTING is_item = ms_item. WHEN OTHERS. zcx_abapgit_exception=>raise( |Unsupported ENHO type { iv_tool }| ). ENDCASE. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_enh_id TYPE enhname, lt_log TYPE enh_log_it, li_log_obj TYPE REF TO if_enh_log, ls_enhlog TYPE enhlog, lv_lines TYPE i, lt_enhlog TYPE STANDARD TABLE OF enhlog WITH DEFAULT KEY, li_enh_tool TYPE REF TO if_enh_tool. lv_enh_id = ms_item-obj_name. TRY. li_enh_tool = cl_enh_factory=>get_enhancement( enhancement_id = lv_enh_id run_dark = abap_true bypassing_buffer = abap_true ). CATCH cx_enh_root. rv_user = c_user_unknown. RETURN. ENDTRY. lt_log = li_enh_tool->get_log( ). LOOP AT lt_log INTO li_log_obj. ls_enhlog = li_log_obj->get_enhlog( ). APPEND ls_enhlog TO lt_enhlog. ENDLOOP. lv_lines = lines( lt_enhlog ). READ TABLE lt_enhlog INTO ls_enhlog INDEX lv_lines. IF sy-subrc = 0. rv_user = ls_enhlog-loguser. ELSE. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_enh_id TYPE enhname, li_enh_object TYPE REF TO if_enh_object, lx_enh_root TYPE REF TO cx_enh_root, lv_corrnum TYPE trkorr. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. zcl_abapgit_sotr_handler=>delete_sotr( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name ). zcl_abapgit_sots_handler=>delete_sots( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name ). lv_corrnum = iv_transport. lv_enh_id = ms_item-obj_name. TRY. li_enh_object = cl_enh_factory=>get_enhancement( enhancement_id = lv_enh_id run_dark = abap_true lock = abap_true ). li_enh_object->delete( EXPORTING nevertheless_delete = abap_true run_dark = abap_true CHANGING trkorr = lv_corrnum ). li_enh_object->unlock( ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_tool TYPE enhtooltype, li_enho TYPE REF TO zif_abapgit_object_enho. IF zif_abapgit_object~exists( ) = abap_true. zif_abapgit_object~delete( iv_package = iv_package iv_transport = iv_transport ). ENDIF. io_xml->read( EXPORTING iv_name = 'TOOL' CHANGING cg_data = lv_tool ). li_enho = factory( lv_tool ). li_enho->deserialize( ii_xml = io_xml iv_package = iv_package ). zcl_abapgit_sotr_handler=>create_sotr( iv_package = iv_package io_xml = io_xml ). zcl_abapgit_sots_handler=>create_sots( iv_package = iv_package io_xml = io_xml ). zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_enh_id TYPE enhname. lv_enh_id = ms_item-obj_name. TRY. cl_enh_factory=>get_enhancement( enhancement_id = lv_enh_id run_dark = abap_true bypassing_buffer = abap_true ). rv_bool = abap_true. CATCH cx_enh_root. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_object TYPE seqg3-garg. lv_object = |{ ms_item-obj_type }{ ms_item-obj_name }|. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_ENHANCE' iv_argument = lv_object ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_enh_id TYPE enhname, li_enho TYPE REF TO zif_abapgit_object_enho, li_enh_tool TYPE REF TO if_enh_tool, lx_enh_root TYPE REF TO cx_enh_root. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. lv_enh_id = ms_item-obj_name. TRY. li_enh_tool = cl_enh_factory=>get_enhancement( enhancement_id = lv_enh_id run_dark = abap_true bypassing_buffer = abap_true ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. li_enho = factory( li_enh_tool->get_tool( ) ). li_enho->serialize( ii_xml = io_xml ii_enh_tool = li_enh_tool ). zcl_abapgit_sotr_handler=>read_sotr( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params io_xml = io_xml ). zcl_abapgit_sots_handler=>read_sots( iv_pgmid = 'R3TR' iv_object = ms_item-obj_type iv_obj_name = ms_item-obj_name io_i18n_params = mo_i18n_params io_xml = io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enhc IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_composite_id = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changedby INTO rv_user FROM enhcompheader WHERE enhcomposite = ms_item-obj_name AND version = 'A'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_enh_root TYPE REF TO cx_enh_root, li_enh_object TYPE REF TO if_enh_object. TRY. li_enh_object = cl_enh_factory=>load_enhancement_composite( name = mv_composite_id lock = abap_true ). li_enh_object->delete( nevertheless_delete = abap_true run_dark = abap_true ). li_enh_object->unlock( ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lx_enh_root TYPE REF TO cx_enh_root, li_enh_composite TYPE REF TO if_enh_composite, lv_package TYPE devclass, lt_composite_childs TYPE enhcompositename_it, lt_enh_childs TYPE enhname_it, lv_longtext_id TYPE enhdocuobject, lv_vers TYPE enhcompheader-version, lv_shorttext TYPE string. FIELD-SYMBOLS: TYPE enhcompositename, LIKE LINE OF lt_enh_childs. lv_package = iv_package. io_xml->read( EXPORTING iv_name = 'SHORTTEXT' CHANGING cg_data = lv_shorttext ). io_xml->read( EXPORTING iv_name = 'COMPOSITE_CHILDS' CHANGING cg_data = lt_composite_childs ). io_xml->read( EXPORTING iv_name = 'ENH_CHILDS' CHANGING cg_data = lt_enh_childs ). io_xml->read( EXPORTING iv_name = 'LONGTEXT_ID' CHANGING cg_data = lv_longtext_id ). SELECT SINGLE version FROM enhcompheader INTO lv_vers WHERE enhcomposite = ms_item-obj_name. IF sy-subrc = 0. " If object exists already, then set TADIR entry to deleted " otherwise create_enhancement_composite will fail tadir_delete( ). ENDIF. TRY. cl_enh_factory=>create_enhancement_composite( EXPORTING name = mv_composite_id run_dark = abap_true IMPORTING composite = li_enh_composite CHANGING devclass = lv_package ). li_enh_composite->if_enh_object_docu~set_shorttext( lv_shorttext ). LOOP AT lt_composite_childs ASSIGNING . li_enh_composite->add_composite_child( ). ENDLOOP. LOOP AT lt_enh_childs ASSIGNING . li_enh_composite->add_enh_child( ). ENDLOOP. li_enh_composite->set_longtext_id( lv_longtext_id ). li_enh_composite->if_enh_object~save( ). li_enh_composite->if_enh_object~activate( ). li_enh_composite->if_enh_object~unlock( ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. cl_enh_factory=>load_enhancement_composite( name = mv_composite_id lock = abap_false ). rv_bool = abap_true. CATCH cx_enh_root. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_argument TYPE seqg3-garg. lv_argument = |{ mv_composite_id }|. OVERLAY lv_argument WITH ' '. lv_argument = |{ lv_argument }*|. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = |E_ENHANCE| iv_argument = lv_argument ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lx_enh_root TYPE REF TO cx_enh_root, li_enh_composite TYPE REF TO if_enh_composite, lt_composite_childs TYPE enhcompositename_it, lt_enh_childs TYPE enhname_it, lv_longtext_id TYPE enhdocuobject, lv_shorttext TYPE string. TRY. li_enh_composite = cl_enh_factory=>load_enhancement_composite( name = mv_composite_id lock = abap_false ). lv_shorttext = li_enh_composite->if_enh_object_docu~get_shorttext( ). lt_composite_childs = li_enh_composite->get_composite_childs( ). lt_enh_childs = li_enh_composite->get_enh_childs( ). lv_longtext_id = li_enh_composite->get_longtext_id( ). io_xml->add( iv_name = 'SHORTTEXT' ig_data = lv_shorttext ). io_xml->add( iv_name = 'COMPOSITE_CHILDS' ig_data = lt_composite_childs ). io_xml->add( iv_name = 'ENH_CHILDS' ig_data = lt_enh_childs ). io_xml->add( iv_name = 'LONGTEXT_ID' ig_data = lv_longtext_id ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ecvo IMPLEMENTATION. METHOD get_download. CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_val_obj_down. ENDMETHOD. METHOD get_lock_object. rv_lock_object = 'E_ECATT_TD'. ENDMETHOD. METHOD get_object_type. * constant missing in 702, cl_apl_ecatt_const=>obj_type_ecatt_vo rv_object_type = 'ECVO'. ENDMETHOD. METHOD get_upload. CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_val_obj_upl. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ectd IMPLEMENTATION. METHOD get_download. CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_data_downl. ENDMETHOD. METHOD get_lock_object. rv_lock_object = 'E_ECATT_TD'. ENDMETHOD. METHOD get_object_type. rv_object_type = cl_apl_ecatt_const=>obj_type_test_data. ENDMETHOD. METHOD get_upload. CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_data_upload. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ectc IMPLEMENTATION. METHOD get_download. CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_config_downl. ENDMETHOD. METHOD get_lock_object. rv_lock_object = 'E_ECATT_TC'. ENDMETHOD. METHOD get_object_type. rv_object_type = cl_apl_ecatt_const=>obj_type_test_config. ENDMETHOD. METHOD get_upload. CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_config_upl. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ecsp IMPLEMENTATION. METHOD get_download. CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_sp_download. ENDMETHOD. METHOD get_lock_object. rv_lock_object = 'E_ECATT_SP'. ENDMETHOD. METHOD get_object_type. * constant missing in 702, cl_apl_ecatt_const=>obj_type_start_profile rv_object_type = 'ECSP'. ENDMETHOD. METHOD get_upload. CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_sp_upload. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ecsd IMPLEMENTATION. METHOD get_download. CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_system_downl. ENDMETHOD. METHOD get_lock_object. rv_lock_object = 'E_ECATT_SD'. ENDMETHOD. METHOD get_object_type. rv_object_type = cl_apl_ecatt_const=>obj_type_system_data. ENDMETHOD. METHOD get_upload. CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_system_upl. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ecatt_super IMPLEMENTATION. METHOD clear_attributes. DATA: li_element TYPE REF TO if_ixml_element, lv_object_type TYPE etobj_type. lv_object_type = get_object_type( ). li_element = ci_document->find_from_name( |{ lv_object_type }| ). li_element->remove_attribute( |SAPRL| ). li_element->remove_attribute( |DOWNLOADDATE| ). li_element->remove_attribute( |DOWNLOADTIME| ). ENDMETHOD. METHOD clear_element. DATA: li_element TYPE REF TO if_ixml_element. li_element = ci_document->find_from_name( iv_name ). IF li_element IS BOUND. li_element->set_value( || ). ENDIF. ENDMETHOD. METHOD clear_elements. clear_element( EXPORTING iv_name = |FUSER| CHANGING ci_document = ci_document ). clear_element( EXPORTING iv_name = |FDATE| CHANGING ci_document = ci_document ). clear_element( EXPORTING iv_name = |LUSER| CHANGING ci_document = ci_document ). clear_element( EXPORTING iv_name = |LDATE| CHANGING ci_document = ci_document ). clear_element( EXPORTING iv_name = |LTIME| CHANGING ci_document = ci_document ). clear_element( EXPORTING iv_name = |TWB_RESP| CHANGING ci_document = ci_document ). clear_element( EXPORTING iv_name = |DEVCLASS| CHANGING ci_document = ci_document ). clear_element( EXPORTING iv_name = |TADIR_RESP| CHANGING ci_document = ci_document ). " Clearing just VAR_EXT_PATH will lead to diffs in batch clear_element( EXPORTING iv_name = |ETVAR_EXT| CHANGING ci_document = ci_document ). " SORTLNR is part of ETPAR_VARI and causing diffs " We can clear it since it's automatically filled during deserialize clear_element_collection( EXPORTING iv_name = |SORTLNR| CHANGING ci_document = ci_document ). ENDMETHOD. METHOD clear_element_collection. DATA: lo_node_collection TYPE REF TO if_ixml_node_collection, lo_node TYPE REF TO if_ixml_node, lv_index TYPE i. lo_node_collection = ci_document->get_elements_by_tag_name( iv_name ). lv_index = 0. WHILE lv_index < lo_node_collection->get_length( ). lo_node = lo_node_collection->get_item( lv_index ). lo_node->set_value( '' ). lv_index = lv_index + 1. ENDWHILE. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_object_name = ms_item-obj_name. ENDMETHOD. METHOD deserialize_version. DATA: ls_object TYPE etmobjects, lo_upload TYPE REF TO cl_apl_ecatt_upload, li_upload TYPE REF TO zif_abapgit_ecatt_upload, lv_xml TYPE xstring, li_document TYPE REF TO if_ixml_document, lv_version TYPE string, lx_error TYPE REF TO cx_ecatt. lv_version = get_version_from_node( ii_version_node ). IF lv_version IS INITIAL. RETURN. ENDIF. lo_upload = get_upload( ). li_upload ?= lo_upload. li_document = cl_ixml=>create( )->create_document( ). li_document->append_child( ii_version_node->get_first_child( ) ). lv_xml = cl_ixml_80_20=>render_to_xstring( li_document ). li_upload->set_stream_for_upload( lv_xml ). ls_object-d_obj_name = mv_object_name. ls_object-s_obj_type = get_object_type( ). ls_object-d_devclass = iv_package. ls_object-d_obj_ver = lv_version. ls_object-d_overwrite = abap_true. TRY. lo_upload->upload( CHANGING ch_object = ls_object ). CATCH cx_ecatt INTO lx_error. zcx_abapgit_exception=>raise( lx_error->get_text( ) ). ENDTRY. ENDMETHOD. METHOD get_changed_by_user. rv_changed_by_user = ii_document->find_from_name( 'LUSER' )->get_value( ). ENDMETHOD. METHOD get_changed_date. DATA: lv_changed_date_external TYPE string. lv_changed_date_external = ii_document->find_from_name( 'LDATE' )->get_value( ). REPLACE ALL OCCURRENCES OF '-' IN lv_changed_date_external WITH ''. rv_changed_date = lv_changed_date_external. ENDMETHOD. METHOD get_changed_time. DATA: lv_changed_time_external TYPE string. lv_changed_time_external = ii_document->find_from_name( 'LTIME' )->get_value( ). REPLACE ALL OCCURRENCES OF ':' IN lv_changed_time_external WITH ''. rv_changed_time = lv_changed_time_external. ENDMETHOD. METHOD get_change_information. DATA: li_document TYPE REF TO if_ixml_document, lv_xml TYPE xstring, lo_download TYPE REF TO cl_apl_ecatt_download, lv_object_type TYPE etobj_type. lo_download = get_download( ). lv_object_type = get_object_type( ). lv_xml = zcl_abapgit_ecatt_helper=>build_xml_of_object( iv_object_name = mv_object_name iv_object_version = is_version_info-version iv_object_type = lv_object_type io_download = lo_download ). li_document = cl_ixml_80_20=>parse_to_document( stream_xstring = lv_xml ). rs_change_information-ldate = get_changed_date( li_document ). rs_change_information-ltime = get_changed_time( li_document ). rs_change_information-luser = get_changed_by_user( li_document ). ENDMETHOD. METHOD get_version_from_node. TRY. rv_version = ii_node->get_first_child( )->get_first_child( )->get_first_child( )->get_first_child( )->get_value( ). CATCH cx_sy_ref_is_initial. RETURN. ENDTRY. ENDMETHOD. METHOD is_change_more_recent_than. IF is_currently_changed-ldate > is_last_changed-ldate OR ( is_currently_changed-ldate = is_last_changed-ldate AND is_currently_changed-ltime > is_last_changed-ltime ). rv_is_change_more_recent = abap_true. ENDIF. ENDMETHOD. METHOD serialize_version. DATA: li_document TYPE REF TO if_ixml_document, lv_xml TYPE xstring, li_node TYPE REF TO if_ixml_element, lo_download TYPE REF TO cl_apl_ecatt_download, lv_object_type TYPE etobj_type. lo_download = get_download( ). lv_object_type = get_object_type( ). lv_xml = zcl_abapgit_ecatt_helper=>build_xml_of_object( iv_object_name = mv_object_name iv_object_version = iv_version iv_object_type = lv_object_type io_download = lo_download ). IF lv_xml IS INITIAL. zcx_abapgit_exception=>raise( |ECATT, empty xml, { mv_object_name }| ). ENDIF. li_document = cl_ixml_80_20=>parse_to_document( stream_xstring = lv_xml ). clear_attributes( CHANGING ci_document = li_document ). clear_elements( CHANGING ci_document = li_document ). li_node = li_document->create_element( c_name-version ). li_node->append_child( li_document->get_root_element( ) ). ci_node->append_child( li_node ). ENDMETHOD. METHOD serialize_versions. DATA: li_versions_node TYPE REF TO if_ixml_element. FIELD-SYMBOLS: LIKE LINE OF it_version_info. li_versions_node = ci_document->create_element( c_name-versions ). IF lines( it_version_info ) > 0. LOOP AT it_version_info ASSIGNING . serialize_version( EXPORTING iv_version = -version CHANGING ci_node = li_versions_node ). ENDLOOP. ELSE. serialize_version( EXPORTING iv_version = c_default_version CHANGING ci_node = li_versions_node ). ENDIF. ci_document->append_child( li_versions_node ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: ls_last_changed TYPE ty_last_changed, ls_currently_changed TYPE ty_last_changed, lt_version_info TYPE etversinfo_tabtype, lx_error TYPE REF TO cx_static_check, lv_text TYPE string, lv_object_type TYPE etobj_type. FIELD-SYMBOLS: LIKE LINE OF lt_version_info. TRY. lv_object_type = get_object_type( ). cl_apl_ecatt_object=>get_version_info_object( EXPORTING im_name = mv_object_name im_obj_type = lv_object_type IMPORTING ex_version_info = lt_version_info ). LOOP AT lt_version_info ASSIGNING . ls_currently_changed = get_change_information( ). IF is_change_more_recent_than( is_currently_changed = ls_currently_changed is_last_changed = ls_last_changed ) = abap_true. ls_last_changed = ls_currently_changed. ENDIF. ENDLOOP. CATCH cx_static_check INTO lx_error. lv_text = lx_error->get_text( ). MESSAGE lv_text TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. IF ls_last_changed-luser IS NOT INITIAL. rv_user = ls_last_changed-luser. ELSE. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_error TYPE REF TO cx_ecatt_apl, lv_text TYPE string, lv_object_type TYPE etobj_type. lv_object_type = get_object_type( ). TRY. cl_apl_ecatt_object=>delete_object( im_obj_type = lv_object_type im_name = mv_object_name " we have to supply a version, so let's use the default version " and delete them all im_version = c_default_version im_delete_all_versions = abap_true ). CATCH cx_ecatt_apl INTO lx_error. lv_text = lx_error->get_text( ). zcx_abapgit_exception=>raise( lv_text ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: li_document TYPE REF TO if_ixml_document, li_versions TYPE REF TO if_ixml_node_collection, li_version_iterator TYPE REF TO if_ixml_node_iterator, li_version_node TYPE REF TO if_ixml_node. li_document = io_xml->get_raw( ). li_versions = li_document->get_elements_by_tag_name( depth = 0 name = c_name-version ). li_version_iterator = li_versions->create_iterator( ). DO. li_version_node = li_version_iterator->get_next( ). IF li_version_node IS NOT BOUND. EXIT. ENDIF. deserialize_version( ii_version_node = li_version_node iv_package = iv_package ). ENDDO. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_object_type TYPE etobj_type. lv_object_type = get_object_type( ). TRY. rv_bool = cl_apl_ecatt_object=>existence_check_object( im_name = mv_object_name im_version = c_default_version im_obj_type = lv_object_type im_exists_any_version = abap_true ). CATCH cx_ecatt. RETURN. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA: lv_object TYPE seqg3-garg. lv_object = ms_item-obj_name. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = get_lock_object( ) iv_argument = lv_object ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lt_version_info TYPE etversinfo_tabtype, li_document TYPE REF TO if_ixml_document, lx_error TYPE REF TO cx_ecatt, lv_text TYPE string, lv_object_type TYPE etobj_type. lv_object_type = get_object_type( ). TRY. cl_apl_ecatt_object=>get_version_info_object( EXPORTING im_name = mv_object_name im_obj_type = lv_object_type IMPORTING ex_version_info = lt_version_info ). SORT lt_version_info BY version. li_document = cl_ixml=>create( )->create_document( ). serialize_versions( EXPORTING it_version_info = lt_version_info CHANGING ci_document = li_document ). io_xml->set_raw( li_document->get_root_element( ) ). CATCH cx_ecatt INTO lx_error. lv_text = lx_error->get_text( ). MESSAGE lv_text TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ecat IMPLEMENTATION. METHOD get_download. CREATE OBJECT ro_download TYPE zcl_abapgit_ecatt_script_downl. ENDMETHOD. METHOD get_lock_object. rv_lock_object = 'E_ECATT'. ENDMETHOD. METHOD get_object_type. rv_object_type = cl_apl_ecatt_const=>obj_type_test_script. ENDMETHOD. METHOD get_upload. CREATE OBJECT ro_upload TYPE zcl_abapgit_ecatt_script_upl. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_dtel IMPLEMENTATION. METHOD deserialize_texts. DATA: lv_name TYPE ddobjname, ls_dd04v_tmp TYPE dd04v, lt_i18n_langs TYPE TABLE OF langu, lt_dd04_texts TYPE ty_dd04_texts. FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, LIKE LINE OF lt_dd04_texts. lv_name = ms_item-obj_name. ii_xml->read( EXPORTING iv_name = 'I18N_LANGS' CHANGING cg_data = lt_i18n_langs ). ii_xml->read( EXPORTING iv_name = 'DD04_TEXTS' CHANGING cg_data = lt_dd04_texts ). mo_i18n_params->trim_saplang_list( CHANGING ct_sap_langs = lt_i18n_langs ). SORT lt_i18n_langs. SORT lt_dd04_texts BY ddlanguage. " Optimization LOOP AT lt_i18n_langs ASSIGNING . " Data element description ls_dd04v_tmp = is_dd04v. READ TABLE lt_dd04_texts ASSIGNING WITH KEY ddlanguage = . IF sy-subrc > 0. zcx_abapgit_exception=>raise( |DD04_TEXTS cannot find lang { } in XML| ). ENDIF. MOVE-CORRESPONDING TO ls_dd04v_tmp. CALL FUNCTION 'DDIF_DTEL_PUT' EXPORTING name = lv_name dd04v_wa = ls_dd04v_tmp EXCEPTIONS dtel_not_found = 1 name_inconsistent = 2 dtel_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD serialize_texts. DATA: lv_name TYPE ddobjname, lv_index TYPE i, ls_dd04v TYPE dd04v, lt_dd04_texts TYPE ty_dd04_texts, lt_i18n_langs TYPE TABLE OF langu, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, LIKE LINE OF lt_dd04_texts. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. lv_name = ms_item-obj_name. " Collect additional languages, skip main lang - it was serialized already lt_language_filter = mo_i18n_params->build_language_filter( ). SELECT DISTINCT ddlanguage AS langu INTO TABLE lt_i18n_langs FROM dd04v WHERE rollname = lv_name AND ddlanguage IN lt_language_filter AND ddlanguage <> mv_language ORDER BY langu. "#EC CI_SUBRC LOOP AT lt_i18n_langs ASSIGNING . lv_index = sy-tabix. CALL FUNCTION 'DDIF_DTEL_GET' EXPORTING name = lv_name langu = IMPORTING dd04v_wa = ls_dd04v EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0 OR ls_dd04v-ddlanguage IS INITIAL. DELETE lt_i18n_langs INDEX lv_index. " Don't save this lang CONTINUE. ENDIF. APPEND INITIAL LINE TO lt_dd04_texts ASSIGNING . MOVE-CORRESPONDING ls_dd04v TO . ENDLOOP. SORT lt_i18n_langs ASCENDING. SORT lt_dd04_texts BY ddlanguage ASCENDING. IF lines( lt_i18n_langs ) > 0. ii_xml->add( iv_name = 'I18N_LANGS' ig_data = lt_i18n_langs ). ii_xml->add( iv_name = 'DD04_TEXTS' ig_data = lt_dd04_texts ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE as4user FROM dd04l INTO rv_user WHERE rollname = ms_item-obj_name AND as4local = 'A' AND as4vers = '0000'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. delete_ddic( 'E' ). delete_longtexts( c_longtext_id_dtel ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_dd04v TYPE dd04v, lv_name TYPE ddobjname. io_xml->read( EXPORTING iv_name = 'DD04V' CHANGING cg_data = ls_dd04v ). corr_insert( iv_package = iv_package ig_object_class = 'DICT' ). lv_name = ms_item-obj_name. " type conversion CALL FUNCTION 'DDIF_DTEL_PUT' EXPORTING name = lv_name dd04v_wa = ls_dd04v EXCEPTIONS dtel_not_found = 1 name_inconsistent = 2 dtel_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF mo_i18n_params->is_lxe_applicable( ) = abap_false. deserialize_texts( ii_xml = io_xml is_dd04v = ls_dd04v ). ENDIF. deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_dtel ). deserialize_longtexts( ii_xml = io_xml iv_longtext_name = 'LONGTEXTS_' && c_longtext_id_dtel_suppl iv_longtext_id = c_longtext_id_dtel_suppl ). zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_rollname TYPE dd04l-rollname. lv_rollname = ms_item-obj_name. " Check nametab because it's fast CALL FUNCTION 'DD_GET_NAMETAB_HEADER' EXPORTING tabname = lv_rollname EXCEPTIONS not_found = 1 OTHERS = 2. IF sy-subrc <> 0. " Check for inactive or modified versions SELECT SINGLE rollname FROM dd04l INTO lv_rollname WHERE rollname = lv_rollname. ENDIF. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECT=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. * fm DDIF_DTEL_GET bypasses buffer, so SELECTs are * done directly from here DATA: lv_name TYPE ddobjname, ls_dd04v TYPE dd04v. lv_name = ms_item-obj_name. SELECT SINGLE * FROM dd04l INTO CORRESPONDING FIELDS OF ls_dd04v WHERE rollname = lv_name AND as4local = 'A' AND as4vers = '0000'. IF sy-subrc <> 0 OR ls_dd04v IS INITIAL. RETURN. ENDIF. SELECT SINGLE * FROM dd04t INTO CORRESPONDING FIELDS OF ls_dd04v WHERE rollname = lv_name AND ddlanguage = mv_language AND as4local = 'A' AND as4vers = '0000'. CLEAR: ls_dd04v-as4user, ls_dd04v-as4date, ls_dd04v-as4time. IF ls_dd04v-refkind = 'D'. * clear values inherited from domain CLEAR: ls_dd04v-datatype, ls_dd04v-leng, ls_dd04v-decimals, ls_dd04v-outputlen, ls_dd04v-valexi, ls_dd04v-lowercase, ls_dd04v-signflag, ls_dd04v-convexit, ls_dd04v-entitytab. ENDIF. IF ls_dd04v-routputlen = ''. * numeric field, make sure it is initial or XML serialization will dump CLEAR ls_dd04v-routputlen. ENDIF. IF ls_dd04v-authclass = ''. CLEAR ls_dd04v-authclass. ENDIF. io_xml->add( iv_name = 'DD04V' ig_data = ls_dd04v ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. serialize_texts( io_xml ). ENDIF. serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_dtel ). serialize_longtexts( ii_xml = io_xml iv_longtext_name = 'LONGTEXTS_' && c_longtext_id_dtel_suppl iv_longtext_id = c_longtext_id_dtel_suppl ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_dtdc IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_dynamic_cache TO . IF sy-subrc = 0. CLEAR: . ENDIF. ENDMETHOD. METHOD clear_fields. clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_AT' CHANGING cs_dynamic_cache = cs_dynamic_cache ). clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_BY' CHANGING cs_dynamic_cache = cs_dynamic_cache ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_AT' CHANGING cs_dynamic_cache = cs_dynamic_cache ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_BY' CHANGING cs_dynamic_cache = cs_dynamic_cache ). clear_field( EXPORTING iv_fieldname = 'METADATA-MASTER_LANGUAGE' CHANGING cs_dynamic_cache = cs_dynamic_cache ). clear_field( EXPORTING iv_fieldname = 'METADATA-RESPONSIBLE' CHANGING cs_dynamic_cache = cs_dynamic_cache ). clear_field( EXPORTING iv_fieldname = 'METADATA-PACKAGE_REF' CHANGING cs_dynamic_cache = cs_dynamic_cache ). clear_field( EXPORTING iv_fieldname = 'METADATA-ABAP_LANGUAGE_VERSION' CHANGING cs_dynamic_cache = cs_dynamic_cache ). clear_field( EXPORTING iv_fieldname = 'METADATA-ABAP_LANGU_VERSION' CHANGING cs_dynamic_cache = cs_dynamic_cache ). clear_field( EXPORTING iv_fieldname = 'CONTENT-SOURCE' CHANGING cs_dynamic_cache = cs_dynamic_cache ). ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_dynamic_cache_key = ms_item-obj_name. mv_has_own_wb_data_class = has_own_wb_data_class( ). TRY. IF mv_has_own_wb_data_class = abap_true. CREATE DATA mr_dynamic_cache TYPE ('CL_DTDC_WB_OBJECT_DATA=>TY_DTDC_OBJECT_DATA'). ELSE. CREATE DATA mr_dynamic_cache TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). ENDIF. CREATE OBJECT mi_persistence TYPE ('CL_DTDC_OBJECT_PERSIST'). CATCH cx_sy_create_error. zcx_abapgit_exception=>raise( |DTDC not supported by your NW release| ). ENDTRY. ENDMETHOD. METHOD fill_metadata_from_db. DATA: li_wb_object_operator TYPE REF TO object, lr_dynamic_cache_old TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE xsddatetime_z, TYPE syuname, TYPE xsddatetime_z, TYPE syuname. li_wb_object_operator = get_wb_object_operator( ). IF mv_has_own_wb_data_class = abap_true. CREATE DATA lr_dynamic_cache_old TYPE ('CL_DTDC_WB_OBJECT_DATA=>TY_DTDC_OBJECT_DATA'). ELSE. CREATE DATA lr_dynamic_cache_old TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). ENDIF. ASSIGN lr_dynamic_cache_old->* TO . ASSERT sy-subrc = 0. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING data = . ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE cs_dynamic_cache TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE cs_dynamic_cache TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE TO . ASSERT sy-subrc = 0. = . = . ENDMETHOD. METHOD get_wb_object_operator. DATA: ls_object_type TYPE wbobjtype, lx_error TYPE REF TO cx_root. IF mi_wb_object_operator IS BOUND. ri_wb_object_operator = mi_wb_object_operator. ENDIF. ls_object_type-objtype_tr = 'DTDC'. ls_object_type-subtype_wb = 'DF'. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') EXPORTING object_type = ls_object_type object_key = mv_dynamic_cache_key RECEIVING result = mi_wb_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ri_wb_object_operator = mi_wb_object_operator. ENDMETHOD. METHOD has_own_wb_data_class. DATA: lr_own_type TYPE REF TO data, lx_error TYPE REF TO cx_root. TRY. CREATE DATA lr_own_type TYPE ('CL_DTDC_WB_OBJECT_DATA=>TY_DTDC_OBJECT_DATA'). rv_supported = abap_true. CATCH cx_root INTO lx_error. rv_supported = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root, li_wb_object_operator TYPE REF TO object. TRY. li_wb_object_operator = get_wb_object_operator( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = li_object_data_model. rv_user = li_object_data_model->get_changed_by( ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_error TYPE REF TO cx_root, li_wb_object_operator TYPE REF TO object. TRY. li_wb_object_operator = get_wb_object_operator( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') EXPORTING transport_request = iv_transport. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, li_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE data. ASSIGN mr_dynamic_cache->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'DTDC' CHANGING cg_data = ). li_wb_object_operator = get_wb_object_operator( ). TRY. IF mv_has_own_wb_data_class = abap_true. CREATE OBJECT li_object_data_model TYPE ('CL_DTDC_WB_OBJECT_DATA'). ELSE. CREATE OBJECT li_object_data_model TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). ENDIF. ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. = mo_files->read_string( 'asdtdc' ). tadir_insert( iv_package ). IF zif_abapgit_object~exists( ) = abap_true. " We need to populate created_at, created_by, because otherwise update is not possible fill_metadata_from_db( CHANGING cs_dynamic_cache = ). li_object_data_model->set_data( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = li_object_data_model transport_request = iv_transport. ELSE. li_object_data_model->set_data( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = li_object_data_model data_selection = 'P' " if_wb_object_data_selection_co=>c_properties package = iv_package transport_request = iv_transport. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = li_object_data_model data_selection = 'D' " if_wb_object_data_selection_co=>c_data_content transport_request = iv_transport. ENDIF. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~ACTIVATE'). corr_insert( iv_package ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. mi_persistence->get( p_object_key = mv_dynamic_cache_key p_version = 'A' p_existence_check_only = abap_true ). rv_bool = abap_true. CATCH cx_swb_exception. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: li_wb_object_operator TYPE REF TO object, li_object_data_model TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root, lv_source TYPE string. FIELD-SYMBOLS: TYPE any, TYPE string. ASSIGN mr_dynamic_cache->* TO . ASSERT sy-subrc = 0. TRY. li_wb_object_operator = get_wb_object_operator( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING version = 'A' IMPORTING data = eo_object_data = li_object_data_model. ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. lv_source = . clear_fields( CHANGING cs_dynamic_cache = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. io_xml->add( iv_name = 'DTDC' ig_data = ). mo_files->add_string( iv_ext = 'asdtdc' iv_string = lv_source ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_dsys IMPLEMENTATION. METHOD constructor. DATA: lv_prefix TYPE namespace, lv_bare_name TYPE progname. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). IF ms_item-obj_name(1) = '/'. CALL FUNCTION 'RS_NAME_SPLIT_NAMESPACE' EXPORTING name_with_namespace = ms_item-obj_name IMPORTING namespace = lv_prefix name_without_namespace = lv_bare_name. mv_doc_object = |{ lv_bare_name+0(4) }{ lv_prefix }{ lv_bare_name+4(*) }|. ELSE. mv_doc_object = ms_item-obj_name. ENDIF. ENDMETHOD. METHOD deserialize_dsys. DATA: ls_data TYPE ty_data, ls_docu_info TYPE dokil, lv_version TYPE dokvers, lv_doku_obj TYPE doku_obj. lv_doku_obj = mv_doc_object. ii_xml->read( EXPORTING iv_name = 'DSYS' CHANGING cg_data = ls_data ). CALL FUNCTION 'DOCU_INIT' EXPORTING id = c_id langu = mv_language object = lv_doku_obj typ = c_typ IMPORTING xdokil = ls_docu_info. lv_version = ls_docu_info-version. CALL FUNCTION 'DOCU_UPDATE' EXPORTING head = ls_data-head state = 'A' typ = c_typ version = lv_version TABLES line = ls_data-lines. ENDMETHOD. METHOD get_main_lang. SELECT SINGLE langu FROM dokil INTO rv_language WHERE id = c_id AND object = mv_doc_object AND masterlang = abap_true. "#EC CI_NOORDER IF sy-subrc <> 0. rv_language = mv_language. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = zcl_abapgit_factory=>get_longtexts( )->changed_by( iv_object_name = mv_doc_object iv_longtext_id = c_id ). ENDMETHOD. METHOD zif_abapgit_object~delete. zcl_abapgit_factory=>get_longtexts( )->delete( iv_object_name = mv_doc_object iv_longtext_id = c_id ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_metadata TYPE zif_abapgit_definitions=>ty_metadata. ls_metadata = io_xml->get_metadata( ). CASE ls_metadata-version. WHEN 'v1.0.0'. deserialize_dsys( io_xml ). WHEN 'v2.0.0'. zcl_abapgit_factory=>get_longtexts( )->deserialize( ii_xml = io_xml iv_object_name = mv_doc_object iv_longtext_id = c_id iv_main_language = mv_language ). WHEN OTHERS. zcx_abapgit_exception=>raise( 'unsupported DSYS version' ). ENDCASE. tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_count TYPE i. SELECT SINGLE COUNT( * ) FROM dokil INTO lv_count WHERE id = c_id AND object = mv_doc_object. "#EC CI_GENBUFF "#EC CI_NOORDER rv_bool = boolc( lv_count > 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). rs_metadata-version = 'v2.0.0'. ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA lv_lang TYPE sy-langu. lv_lang = get_main_lang( ). CALL FUNCTION 'DSYS_EDIT' EXPORTING dokclass = mv_doc_object+0(4) dokname = mv_doc_object+4(*) doklangu = lv_lang EXCEPTIONS not_hypertext_class = 1 no_editor = 2 OTHERS = 3. rv_exit = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. zcl_abapgit_factory=>get_longtexts( )->serialize( iv_object_name = mv_doc_object iv_longtext_id = c_id io_i18n_params = mo_i18n_params ii_xml = io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_drul IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_dependency_rule TO . ASSERT sy-subrc = 0. CLEAR: . ENDMETHOD. METHOD clear_fields. clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_AT' CHANGING cs_dependency_rule = cs_dependency_rule ). clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_BY' CHANGING cs_dependency_rule = cs_dependency_rule ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_AT' CHANGING cs_dependency_rule = cs_dependency_rule ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_BY' CHANGING cs_dependency_rule = cs_dependency_rule ). clear_field( EXPORTING iv_fieldname = 'METADATA-MASTER_LANGUAGE' CHANGING cs_dependency_rule = cs_dependency_rule ). clear_field( EXPORTING iv_fieldname = 'METADATA-RESPONSIBLE' CHANGING cs_dependency_rule = cs_dependency_rule ). clear_field( EXPORTING iv_fieldname = 'METADATA-PACKAGE_REF' CHANGING cs_dependency_rule = cs_dependency_rule ). clear_field( EXPORTING iv_fieldname = 'CONTENT-SOURCE' CHANGING cs_dependency_rule = cs_dependency_rule ). ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_dependency_rule_key = ms_item-obj_name. TRY. CREATE DATA mr_dependency_rule TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). CREATE OBJECT mi_persistence TYPE ('CL_DRUL_WB_OBJECT_PERSIST'). CATCH cx_sy_create_error. zcx_abapgit_exception=>raise( |DRUL not supported by your NW release| ). ENDTRY. ENDMETHOD. METHOD fill_metadata_from_db. DATA: li_wb_object_operator TYPE REF TO object, lr_dependency_rule_old TYPE REF TO data, lv_drul_object_data_clas_exist TYPE c LENGTH 1. FIELD-SYMBOLS: TYPE any, TYPE xsddatetime_z, TYPE syuname, TYPE xsddatetime_z, TYPE syuname. li_wb_object_operator = get_wb_object_operator( ). CREATE DATA lr_dependency_rule_old TYPE ('CL_BLUE_SOURCE_OBJECT_DATA2=>TY_OBJECT_DATA'). CALL FUNCTION 'CHECK_EXIST_CLAS' EXPORTING name = 'CL_DRUL_WB_OBJECT_DATA' IMPORTING exist = lv_drul_object_data_clas_exist EXCEPTIONS tr_invalid_type = 1 OTHERS = 2. IF sy-subrc = 0 AND lv_drul_object_data_clas_exist = abap_true. CREATE DATA lr_dependency_rule_old TYPE ('CL_DRUL_WB_OBJECT_DATA=>TY_OBJECT_DATA'). ELSE. CREATE DATA lr_dependency_rule_old TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). ENDIF. ASSIGN lr_dependency_rule_old->* TO . ASSERT sy-subrc = 0. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING data = . ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE cs_dependency_rule TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE cs_dependency_rule TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE TO . ASSERT sy-subrc = 0. = . = . ENDMETHOD. METHOD get_wb_object_operator. DATA: ls_object_type TYPE wbobjtype, lx_error TYPE REF TO cx_root. IF mi_wb_object_operator IS BOUND. ri_wb_object_operator = mi_wb_object_operator. ENDIF. ls_object_type-objtype_tr = 'DRUL'. ls_object_type-subtype_wb = 'DRL'. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') EXPORTING object_type = ls_object_type object_key = mv_dependency_rule_key RECEIVING result = mi_wb_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ri_wb_object_operator = mi_wb_object_operator. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: li_wb_object_operator TYPE REF TO object, li_object_data_model TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root. TRY. li_wb_object_operator = get_wb_object_operator( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = li_object_data_model. rv_user = li_object_data_model->get_changed_by( ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_error TYPE REF TO cx_root, li_wb_object_operator TYPE REF TO object. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') EXPORTING transport_request = iv_transport. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, li_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root, lv_drul_object_data_clas_exist TYPE c LENGTH 1. FIELD-SYMBOLS: TYPE any, TYPE data. ASSIGN mr_dependency_rule->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'DRUL' CHANGING cg_data = ). li_wb_object_operator = get_wb_object_operator( ). TRY. CALL FUNCTION 'CHECK_EXIST_CLAS' EXPORTING name = 'CL_DRUL_WB_OBJECT_DATA' IMPORTING exist = lv_drul_object_data_clas_exist EXCEPTIONS tr_invalid_type = 1 OTHERS = 2. IF sy-subrc = 0 AND lv_drul_object_data_clas_exist = abap_true. CREATE OBJECT li_object_data_model TYPE ('CL_DRUL_WB_OBJECT_DATA'). ELSE. CREATE OBJECT li_object_data_model TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). ENDIF. ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. = mo_files->read_string( 'asdrul' ). tadir_insert( iv_package ). IF zif_abapgit_object~exists( ) = abap_true. " We need to populate created_at, created_by, because otherwise update is not possible fill_metadata_from_db( CHANGING cs_dependency_rule = ). li_object_data_model->set_data( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = li_object_data_model transport_request = iv_transport. ELSE. li_object_data_model->set_data( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = li_object_data_model data_selection = 'P' " if_wb_object_data_selection_co=>c_properties package = iv_package transport_request = iv_transport. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = li_object_data_model data_selection = 'D' " if_wb_object_data_selection_co=>c_data_content transport_request = iv_transport. ENDIF. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~ACTIVATE'). corr_insert( iv_package ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. mi_persistence->get( p_object_key = mv_dependency_rule_key p_version = 'A' p_existence_check_only = abap_true ). rv_bool = abap_true. CATCH cx_swb_exception. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: li_wb_object_operator TYPE REF TO object, li_object_data_model TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root, lv_source TYPE string. FIELD-SYMBOLS: TYPE any, TYPE string. ASSIGN mr_dependency_rule->* TO . ASSERT sy-subrc = 0. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING version = 'A' IMPORTING data = eo_object_data = li_object_data_model. ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. lv_source = . clear_fields( CHANGING cs_dependency_rule = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. io_xml->add( iv_name = 'DRUL' ig_data = ). mo_files->add_string( iv_ext = 'asdrul' iv_string = lv_source ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_doma IMPLEMENTATION. METHOD adjust_exit. DATA lv_function TYPE funcname. IF cv_exit IS NOT INITIAL. lv_function = |CONVERSION_EXIT_{ cv_exit }_INPUT|. " If exit function does not exist, remove it IF zcl_abapgit_factory=>get_function_module( )->function_exists( lv_function ) = abap_false. cv_exit = ''. ENDIF. ENDIF. ENDMETHOD. METHOD check_exit. DATA lv_exit TYPE dd01v-convexit. rv_done = abap_true. IF iv_exit IS NOT INITIAL. " Check if exit function is set correctly SELECT SINGLE convexit FROM dd01v INTO lv_exit WHERE domname = ms_item-obj_name. IF sy-subrc = 0 AND lv_exit <> iv_exit. rv_done = abap_false. ENDIF. ENDIF. ENDMETHOD. METHOD deserialize_texts. DATA: lv_name TYPE ddobjname, lv_valpos TYPE valpos, ls_dd01v_tmp TYPE dd01v, lt_dd07v_tmp TYPE TABLE OF dd07v, lt_i18n_langs TYPE TABLE OF langu, lt_dd01_texts TYPE ty_dd01_texts, lt_dd07_texts TYPE ty_dd07_texts. FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, LIKE LINE OF it_dd07v, LIKE LINE OF lt_dd01_texts, LIKE LINE OF lt_dd07_texts. lv_name = ms_item-obj_name. ii_xml->read( EXPORTING iv_name = 'I18N_LANGS' CHANGING cg_data = lt_i18n_langs ). ii_xml->read( EXPORTING iv_name = 'DD01_TEXTS' CHANGING cg_data = lt_dd01_texts ). ii_xml->read( EXPORTING iv_name = 'DD07_TEXTS' CHANGING cg_data = lt_dd07_texts ). mo_i18n_params->trim_saplang_list( CHANGING ct_sap_langs = lt_i18n_langs ). SORT lt_i18n_langs. SORT lt_dd07_texts BY ddlanguage. " Optimization LOOP AT lt_i18n_langs ASSIGNING . " Domain description ls_dd01v_tmp = is_dd01v. READ TABLE lt_dd01_texts ASSIGNING WITH KEY ddlanguage = . IF sy-subrc > 0. zcx_abapgit_exception=>raise( |DD01_TEXTS cannot find lang { } in XML| ). ENDIF. MOVE-CORRESPONDING TO ls_dd01v_tmp. " Domain values lt_dd07v_tmp = it_dd07v. LOOP AT lt_dd07v_tmp ASSIGNING . lv_valpos = -valpos. " it_dd07v was potentially renumbered so lookup by value READ TABLE lt_dd07_texts ASSIGNING WITH KEY ddlanguage = domvalue_l = -domvalue_l domvalue_h = -domvalue_h. IF sy-subrc = 0. MOVE-CORRESPONDING TO . -valpos = lv_valpos. DELETE lt_dd07_texts INDEX sy-tabix. " Optimization ELSE. " no translation -> keep entry but clear texts -ddlanguage = . CLEAR: -ddtext, -domval_ld, -domval_hd. ENDIF. ENDLOOP. CALL FUNCTION 'DDIF_DOMA_PUT' EXPORTING name = lv_name dd01v_wa = ls_dd01v_tmp TABLES dd07v_tab = lt_dd07v_tmp EXCEPTIONS doma_not_found = 1 name_inconsistent = 2 doma_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD handle_dependencies. " For domains with dependency on conversion exit function, we use two phases: " 1) DDIC phase: " - If function does not exit, remove the exit function " 2) LATE phase " - If function was removed, change it to the correct exit function CASE iv_step. WHEN zif_abapgit_object=>gc_step_id-ddic. adjust_exit( CHANGING cv_exit = cv_exit ). WHEN zif_abapgit_object=>gc_step_id-late. cv_done = check_exit( cv_exit ). WHEN OTHERS. ASSERT 0 = 1. ENDCASE. ENDMETHOD. METHOD serialize_texts. DATA: lv_name TYPE ddobjname, lv_index TYPE i, ls_dd01v TYPE dd01v, lt_dd07v TYPE TABLE OF dd07v, lt_i18n_langs TYPE TABLE OF langu, lt_dd01_texts TYPE ty_dd01_texts, lt_dd07_texts TYPE ty_dd07_texts, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. FIELD-SYMBOLS: LIKE LINE OF lt_i18n_langs, LIKE LINE OF lt_dd07v, LIKE LINE OF lt_dd07v, LIKE LINE OF lt_dd01_texts, LIKE LINE OF lt_dd07_texts. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. lv_name = ms_item-obj_name. " Collect additional languages, skip main lang - it was serialized already lt_language_filter = mo_i18n_params->build_language_filter( ). SELECT DISTINCT ddlanguage AS langu INTO TABLE lt_i18n_langs FROM dd01v WHERE domname = lv_name AND ddlanguage IN lt_language_filter AND ddlanguage <> mv_language ORDER BY langu. "#EC CI_SUBRC SELECT DISTINCT ddlanguage AS langu APPENDING TABLE lt_i18n_langs FROM dd07v WHERE domname = lv_name AND ddlanguage IN lt_language_filter AND ddlanguage <> mv_language ORDER BY langu. "#EC CI_SUBRC SORT lt_i18n_langs. DELETE ADJACENT DUPLICATES FROM lt_i18n_langs. LOOP AT lt_i18n_langs ASSIGNING . lv_index = sy-tabix. CALL FUNCTION 'DDIF_DOMA_GET' EXPORTING name = lv_name langu = IMPORTING dd01v_wa = ls_dd01v TABLES dd07v_tab = lt_dd07v EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. DELETE lt_i18n_langs INDEX lv_index. " Don't save this lang CONTINUE. ENDIF. IF ls_dd01v-ddlanguage IS INITIAL. ls_dd01v-ddlanguage = . ENDIF. APPEND INITIAL LINE TO lt_dd01_texts ASSIGNING . MOVE-CORRESPONDING ls_dd01v TO . " Process main language entries and find corresponding translation LOOP AT it_dd07v ASSIGNING WHERE NOT ddlanguage IS INITIAL. APPEND INITIAL LINE TO lt_dd07_texts ASSIGNING . READ TABLE lt_dd07v ASSIGNING WITH KEY ddlanguage = domvalue_l = -domvalue_l domvalue_h = -domvalue_h. IF sy-subrc = 0. MOVE-CORRESPONDING TO . ELSE. " no translation -> keep entry but clear texts MOVE-CORRESPONDING TO . -ddlanguage = . CLEAR: -ddtext, -domval_ld, -domval_hd. ENDIF. ENDLOOP. ENDLOOP. SORT lt_i18n_langs ASCENDING. SORT lt_dd01_texts BY ddlanguage ASCENDING. SORT lt_dd07_texts BY valpos ASCENDING ddlanguage ASCENDING. IF lines( lt_i18n_langs ) > 0. ii_xml->add( iv_name = 'I18N_LANGS' ig_data = lt_i18n_langs ). ii_xml->add( iv_name = 'DD01_TEXTS' ig_data = lt_dd01_texts ). ii_xml->add( iv_name = 'DD07_TEXTS' ig_data = lt_dd07_texts ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE as4user FROM dd01l INTO rv_user WHERE domname = ms_item-obj_name AND as4local = 'A' AND as4vers = '0000'. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. delete_ddic( iv_objtype = 'D' iv_no_ask_delete_append = abap_true ). delete_longtexts( c_longtext_id_doma ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. * package SEDD * package SDIC DATA: lv_name TYPE ddobjname, lv_done TYPE abap_bool, ls_dd01v TYPE dd01v, lt_dd07v TYPE TABLE OF dd07v. FIELD-SYMBOLS TYPE dd07v. io_xml->read( EXPORTING iv_name = 'DD01V' CHANGING cg_data = ls_dd01v ). io_xml->read( EXPORTING iv_name = 'DD07V_TAB' CHANGING cg_data = lt_dd07v ). handle_dependencies( EXPORTING iv_step = iv_step CHANGING cv_exit = ls_dd01v-convexit cv_done = lv_done ). IF lv_done = abap_true. RETURN. ENDIF. corr_insert( iv_package = iv_package ig_object_class = 'DICT' ). lv_name = ms_item-obj_name. " type conversion LOOP AT lt_dd07v ASSIGNING . -domname = lv_name. -valpos = sy-tabix. ENDLOOP. CALL FUNCTION 'DDIF_DOMA_PUT' EXPORTING name = lv_name dd01v_wa = ls_dd01v TABLES dd07v_tab = lt_dd07v EXCEPTIONS doma_not_found = 1 name_inconsistent = 2 doma_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF mo_i18n_params->is_lxe_applicable( ) = abap_false. deserialize_texts( ii_xml = io_xml is_dd01v = ls_dd01v it_dd07v = lt_dd07v ). ENDIF. deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_doma ). zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA lv_domname TYPE dd01l-domname. SELECT SINGLE domname FROM dd01l INTO lv_domname WHERE domname = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECT=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_name TYPE ddobjname, lv_state TYPE ddgotstate, ls_dd01v TYPE dd01v, lv_masklen TYPE c LENGTH 4, lt_dd07v TYPE TABLE OF dd07v. FIELD-SYMBOLS TYPE dd07v. lv_name = ms_item-obj_name. CALL FUNCTION 'DDIF_DOMA_GET' EXPORTING name = lv_name state = 'A' langu = mv_language IMPORTING gotstate = lv_state dd01v_wa = ls_dd01v TABLES dd07v_tab = lt_dd07v EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF ls_dd01v IS INITIAL OR lv_state <> 'A'. RETURN. ENDIF. CLEAR: ls_dd01v-as4user, ls_dd01v-as4date, ls_dd01v-as4time, ls_dd01v-appexist. * make sure XML serialization does not dump if the field contains invalid data * note that this is a N field, so '' is not valid IF ls_dd01v-authclass = ''. CLEAR ls_dd01v-authclass. ENDIF. lv_masklen = ls_dd01v-masklen. IF lv_masklen = '' OR NOT lv_masklen CO '0123456789'. CLEAR ls_dd01v-masklen. ENDIF. DELETE lt_dd07v WHERE appval = abap_true. SORT lt_dd07v BY valpos ASCENDING ddlanguage ASCENDING. LOOP AT lt_dd07v ASSIGNING . CLEAR -domname. ENDLOOP. io_xml->add( iv_name = 'DD01V' ig_data = ls_dd01v ). io_xml->add( iv_name = 'DD07V_TAB' ig_data = lt_dd07v ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. serialize_texts( ii_xml = io_xml it_dd07v = lt_dd07v ). ENDIF. serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_doma ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_docv IMPLEMENTATION. METHOD constructor. DATA: lv_prefix TYPE namespace, lv_bare_name TYPE progname. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). IF ms_item-obj_name(2) <> 'DT'. " IN, MO, UO, UP mv_id = ms_item-obj_name(2). mv_doc_object = ms_item-obj_name+2. ELSE. " DT CALL FUNCTION 'RS_NAME_SPLIT_NAMESPACE' EXPORTING name_with_namespace = ms_item-obj_name IMPORTING namespace = lv_prefix name_without_namespace = lv_bare_name EXCEPTIONS delimiter_error = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error determining namespace for { ms_item-obj_type } { ms_item-obj_name }| ). ENDIF. mv_id = lv_bare_name(2). mv_doc_object = |{ lv_prefix }{ lv_bare_name+2 }|. ENDIF. ENDMETHOD. METHOD read. CALL FUNCTION 'DOCU_READ' EXPORTING id = mv_id langu = mv_language object = mv_doc_object typ = c_typ version = c_version IMPORTING doktitle = rs_data-doctitle head = rs_data-head TABLES line = rs_data-lines. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = read( )-head-tdluser. IF rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. CALL FUNCTION 'DOCU_DEL' EXPORTING id = mv_id langu = mv_language object = mv_doc_object typ = c_typ EXCEPTIONS ret_code = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_data TYPE ty_data. io_xml->read( EXPORTING iv_name = c_name CHANGING cg_data = ls_data ). CALL FUNCTION 'DOCU_UPDATE' EXPORTING head = ls_data-head state = 'A' typ = c_typ version = c_version TABLES line = ls_data-lines. tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. SELECT SINGLE id FROM dokil INTO mv_id WHERE id = mv_id AND object = mv_doc_object. "#EC CI_GENBUFF "#EC CI_NOORDER rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_data TYPE ty_data. ls_data = read( ). CLEAR: ls_data-head-tdfuser, ls_data-head-tdfreles, ls_data-head-tdfdate, ls_data-head-tdftime, ls_data-head-tdluser, ls_data-head-tdlreles, ls_data-head-tdldate, ls_data-head-tdltime. io_xml->add( iv_name = c_name ig_data = ls_data ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_doct IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mi_longtexts = zcl_abapgit_factory=>get_longtexts( ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = mi_longtexts->changed_by( iv_object_name = ms_item-obj_name iv_longtext_id = c_id ). IF rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. mi_longtexts->delete( iv_object_name = ms_item-obj_name iv_longtext_id = c_id ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. mi_longtexts->deserialize( iv_longtext_name = c_name iv_object_name = ms_item-obj_name iv_longtext_id = c_id ii_xml = io_xml iv_main_language = mv_language ). tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_id TYPE dokil-id, lv_object TYPE dokhl-object. lv_object = ms_item-obj_name. SELECT SINGLE id FROM dokil INTO lv_id WHERE id = c_id AND object = lv_object. "#EC CI_GENBUFF "#EC CI_NOORDER rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: ls_dokentry TYPE dokentry, ls_bcdata TYPE bdcdata, lt_bcdata TYPE STANDARD TABLE OF bdcdata. " We need to modify dokentry directly, otherwise " Batch Input on SE61 wouldn't work because it stores " the last seen Document Class in this table. There's " no standard function to do this. SE61 does this " directly in its dialog modules ls_dokentry-username = sy-uname. ls_dokentry-langu = mv_language. ls_dokentry-class = c_id. MODIFY dokentry FROM ls_dokentry. ls_bcdata-program = 'SAPMSDCU'. ls_bcdata-dynpro = '0100'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'RSDCU-OBJECT7'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=SHOW'. APPEND ls_bcdata TO lt_bcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SE61' it_bdcdata = lt_bcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. mi_longtexts->serialize( iv_longtext_name = c_name iv_object_name = ms_item-obj_name iv_longtext_id = c_id io_i18n_params = mo_i18n_params ii_xml = io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_dial IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " not stored by SAP ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_bcdata TYPE bdcdata, lt_bcdata TYPE STANDARD TABLE OF bdcdata. ls_bcdata-program = 'SAPMSDIA'. ls_bcdata-dynpro = '1010'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'DIAPAR-DNAM'. ls_bcdata-fval = ms_item-obj_name. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'RS38L-PARM'. ls_bcdata-fval = abap_true. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=DELF'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-program = 'SAPLSPO1'. ls_bcdata-dynpro = '0100'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=YES'. APPEND ls_bcdata TO lt_bcdata. ls_bcdata-program = 'SAPMSDIA'. ls_bcdata-dynpro = '1010'. ls_bcdata-dynbegin = 'X'. APPEND ls_bcdata TO lt_bcdata. CLEAR ls_bcdata. ls_bcdata-fnam = 'BDC_OKCODE'. ls_bcdata-fval = '=BACK'. APPEND ls_bcdata TO lt_bcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SE35' it_bdcdata = lt_bcdata iv_new_window = abap_false ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_dialog_module TYPE ty_dialog_module. " Prefill popup asking for package set_default_package( iv_package ). io_xml->read( EXPORTING iv_name = 'DIAL' CHANGING cg_data = ls_dialog_module ). CALL FUNCTION 'RS_DIALOG_CREATE' EXPORTING dialogname = ls_dialog_module-tdct-dnam dynpronumber = ls_dialog_module-tdct-dynr programname = ls_dialog_module-tdct-prog suppress_corr_check = abap_false * It seems that dia_par parameter doesn't do anything, but we can't omit it * Parameters are inserted below TABLES dia_par = ls_dialog_module-dia_pars EXCEPTIONS dialog_already_exists = 1 invalid_name = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error deserializing dialogmodule { ms_item-obj_name }| ). ENDIF. " It seems that there's no API for diapar, therefore we manipulate it directly INSERT diapar FROM TABLE ls_dialog_module-dia_pars. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_tdct TYPE tdct. ls_tdct = _read_tdct( ). rv_bool = boolc( ls_tdct IS NOT INITIAL ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lv_objectname TYPE tdct-dnam. lv_objectname = ms_item-obj_name. CALL FUNCTION 'RS_DIALOG_SHOW' EXPORTING objectname = lv_objectname type = 'VW' EXCEPTIONS object_not_found = 1 OTHERS = 2. rv_exit = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA ls_dialog_module TYPE ty_dialog_module. ls_dialog_module-tdct = _read_tdct( ). SELECT * FROM diapar INTO TABLE ls_dialog_module-dia_pars WHERE dnam = ls_dialog_module-tdct-dnam ORDER BY PRIMARY KEY. io_xml->add( iv_name = 'DIAL' ig_data = ls_dialog_module ). ENDMETHOD. METHOD _read_tdct. DATA: lv_dnam TYPE tdct-dnam. lv_dnam = ms_item-obj_name. SELECT SINGLE * FROM tdct INTO rs_tdct WHERE dnam = lv_dnam. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_devc IMPLEMENTATION. METHOD adjust_sw_component. DATA: lv_namespace TYPE namespace, lv_comp_type TYPE c LENGTH 1. " Keep software component of a package for ABAP add-ons (customer and partner developments)... SELECT SINGLE comp_type FROM cvers INTO lv_comp_type WHERE component = cv_dlvunit. IF sy-subrc = 0 AND lv_comp_type = 'A'. " ... with a matching namespace (typical Add-on Assembly Kit scenario) lv_namespace = |/{ cv_dlvunit }/|. SELECT SINGLE namespace FROM trnspace INTO lv_namespace WHERE namespace = lv_namespace. IF sy-subrc <> 0. CLEAR cv_dlvunit. ENDIF. ELSE. CLEAR cv_dlvunit. ENDIF. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). IF is_item-devclass IS NOT INITIAL. mv_local_devclass = is_item-devclass. ELSE. mv_local_devclass = is_item-obj_name. ENDIF. ENDMETHOD. METHOD get_package. IF zif_abapgit_object~exists( ) = abap_true. ri_package = load_package( mv_local_devclass ). ENDIF. ENDMETHOD. METHOD is_empty. DATA: lv_object_name TYPE tadir-obj_name, lt_subpackages TYPE zif_abapgit_sap_package=>ty_devclass_tt. lt_subpackages = zcl_abapgit_factory=>get_sap_package( iv_package_name )->list_subpackages( ). IF lines( lt_subpackages ) > 0. rv_is_empty = abap_false. RETURN. ENDIF. " Ignore the SOTR if is linked to the current SAP package (DEVC) SELECT SINGLE obj_name FROM tadir INTO lv_object_name WHERE pgmid = 'R3TR' AND NOT ( ( object = 'DEVC' OR object = 'SOTR' ) AND obj_name = iv_package_name ) AND devclass = iv_package_name. rv_is_empty = boolc( sy-subrc <> 0 ). ENDMETHOD. METHOD is_local. DATA lv_dlvunit TYPE tdevc-dlvunit. SELECT SINGLE dlvunit FROM tdevc INTO lv_dlvunit WHERE devclass = iv_package_name AND intsys <> 'SAP'. IF sy-subrc = 0 AND lv_dlvunit = 'LOCAL'. rv_is_local = abap_true. ENDIF. ENDMETHOD. METHOD load_package. cl_package_factory=>load_package( EXPORTING i_package_name = iv_package_name i_force_reload = abap_true IMPORTING e_package = ri_package EXCEPTIONS object_not_existing = 1 unexpected_error = 2 intern_err = 3 no_access = 4 object_locked_and_modified = 5 OTHERS = 6 ). IF sy-subrc = 1. RETURN. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD remove_obsolete_tadir. DATA: lv_pack TYPE devclass, lt_pack TYPE STANDARD TABLE OF devclass, ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, ls_item TYPE zif_abapgit_definitions=>ty_item. " TADIR entries must remain for transportable packages IF is_local( iv_package_name ) = abap_false. RETURN. ENDIF. " Clean-up sub packages first SELECT devclass FROM tdevc INTO TABLE lt_pack WHERE parentcl = iv_package_name ORDER BY PRIMARY KEY. LOOP AT lt_pack INTO lv_pack. remove_obsolete_tadir( lv_pack ). ENDLOOP. " Remove TADIR entries for objects that do not exist anymore SELECT * FROM tadir INTO CORRESPONDING FIELDS OF TABLE lt_tadir WHERE devclass = iv_package_name ORDER BY PRIMARY KEY ##TOO_MANY_ITAB_FIELDS. LOOP AT lt_tadir INTO ls_tadir. ls_item-obj_type = ls_tadir-object. ls_item-obj_name = ls_tadir-obj_name. IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_tadir_pgmid = 'R3TR' wi_tadir_object = ls_tadir-object wi_tadir_obj_name = ls_tadir-obj_name wi_test_modus = abap_false EXCEPTIONS OTHERS = 1 ##FM_SUBRC_OK. ENDIF. ENDLOOP. ENDMETHOD. METHOD set_lock. DATA: lv_changeable TYPE abap_bool. ii_package->get_changeable( IMPORTING e_changeable = lv_changeable ). IF lv_changeable <> iv_lock. TRY. CALL METHOD ii_package->('SET_CHANGEABLE') EXPORTING i_changeable = iv_lock i_suppress_dialog = abap_true " Parameter missing in 702 EXCEPTIONS object_locked_by_other_user = 1 permission_failure = 2 object_already_changeable = 3 object_already_unlocked = 4 object_just_created = 5 object_deleted = 6 object_modified = 7 object_not_existing = 8 object_invalid = 9 unexpected_error = 10 OTHERS = 11. CATCH cx_sy_dyn_call_param_not_found. ii_package->set_changeable( EXPORTING i_changeable = iv_lock EXCEPTIONS object_locked_by_other_user = 1 permission_failure = 2 object_already_changeable = 3 object_already_unlocked = 4 object_just_created = 5 object_deleted = 6 object_modified = 7 object_not_existing = 8 object_invalid = 9 unexpected_error = 10 OTHERS = 11 ). ENDTRY. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. TRY. CALL METHOD ii_package->('SET_PERMISSIONS_CHANGEABLE') EXPORTING i_changeable = iv_lock i_suppress_dialog = abap_true " Parameter missing in 702 EXCEPTIONS object_already_changeable = 1 object_already_unlocked = 2 object_locked_by_other_user = 3 object_modified = 4 object_just_created = 5 object_deleted = 6 permission_failure = 7 object_invalid = 8 unexpected_error = 9 OTHERS = 10. CATCH cx_sy_dyn_call_param_not_found. ii_package->set_permissions_changeable( EXPORTING i_changeable = iv_lock EXCEPTIONS object_already_changeable = 1 object_already_unlocked = 2 object_locked_by_other_user = 3 object_modified = 4 object_just_created = 5 object_deleted = 6 permission_failure = 7 object_invalid = 8 unexpected_error = 9 OTHERS = 10 ). ENDTRY. IF ( sy-subrc = 1 AND iv_lock = abap_true ) OR ( sy-subrc = 2 AND iv_lock = abap_false ). " There's no getter to find out beforehand... ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD unlock_and_raise_error. DATA ls_msg TYPE bal_s_msg. " Remember message since unlock overwrites it (for example with XT465) MOVE-CORRESPONDING sy TO ls_msg. set_lock( ii_package = ii_package iv_lock = abap_false ). zcx_abapgit_exception=>raise_t100( iv_msgid = ls_msg-msgid iv_msgno = ls_msg-msgno iv_msgv1 = ls_msg-msgv1 iv_msgv2 = ls_msg-msgv2 iv_msgv3 = ls_msg-msgv3 iv_msgv4 = ls_msg-msgv4 ). ENDMETHOD. METHOD update_pinf_usages. DATA: lt_current_permissions TYPE tpak_permission_to_use_list, li_usage TYPE REF TO if_package_permission_to_use, ls_data_sign TYPE scomppsign, ls_add_permission_data TYPE pkgpermdat, lt_handled TYPE SORTED TABLE OF i WITH UNIQUE KEY table_line. FIELD-SYMBOLS: LIKE LINE OF it_usage_data. " Get the current permissions ii_package->get_permissions_to_use( IMPORTING e_permissions = lt_current_permissions EXCEPTIONS object_invalid = 1 unexpected_error = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ls_data_sign-err_sever = abap_true. " New permissions LOOP AT it_usage_data ASSIGNING . READ TABLE lt_current_permissions WITH KEY table_line->package_interface_name = -intf_name INTO li_usage. IF sy-subrc = 0 AND li_usage IS BOUND. INSERT sy-tabix INTO TABLE lt_handled. " Permission already exists, update attributes li_usage->set_all_attributes( EXPORTING i_permission_data = i_data_sign = ls_data_sign EXCEPTIONS object_not_changeable = 1 object_invalid = 2 intern_err = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ELSE. " Permission does not exist yet, add it MOVE-CORRESPONDING TO ls_add_permission_data. ii_package->add_permission_to_use( EXPORTING i_pkg_permission_data = ls_add_permission_data EXCEPTIONS object_not_changeable = 1 object_access_error = 2 object_already_existing = 3 object_invalid = 4 unexpected_error = 5 OTHERS = 6 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. FREE li_usage. ENDLOOP. " Delete missing usages LOOP AT lt_current_permissions INTO li_usage. READ TABLE lt_handled WITH TABLE KEY table_line = sy-tabix TRANSPORTING NO FIELDS. IF sy-subrc = 0. CONTINUE. ENDIF. li_usage->delete( EXCEPTIONS object_not_changeable = 1 object_invalid = 2 * deletion_not_allowed = 3 downport, does not exist in 7.30 intern_err = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA li_package TYPE REF TO if_package. li_package = get_package( ). IF li_package IS BOUND. rv_user = li_package->changed_by. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: li_package TYPE REF TO if_package, lv_package TYPE devclass. " Package deletion is a bit tricky. A package can only be deleted if there are no objects " contained in it. This includes subpackages, so first the leaf packages need to be deleted. " Unfortunately deleted objects that are still contained in an unreleased transport request " also count towards the contained objects counter. " -> Currently we delete only empty packages " " If objects are deleted, the TADIR entry is deleted when the transport request is released. " So before we can delete the package, the transport which deletes the objects " in the package has to be released. lv_package = ms_item-obj_name. " Remove remaining OTR entries zcl_abapgit_sotr_handler=>delete_sotr_package( iv_package ). remove_obsolete_tadir( lv_package ). IF is_empty( lv_package ) = abap_true. li_package = load_package( lv_package ). IF li_package IS NOT BOUND. RETURN. ENDIF. IF lv_package(1) = '$'. zcl_abapgit_persist_packages=>get_instance( )->modify( lv_package ). ENDIF. set_lock( ii_package = li_package iv_lock = abap_true ). TRY. CALL METHOD li_package->('DELETE') EXPORTING i_suppress_dialog = abap_true " Parameter missing in 702 EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 intern_err = 4 OTHERS = 5. CATCH cx_sy_dyn_call_param_not_found. li_package->delete( EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 intern_err = 4 OTHERS = 5 ). ENDTRY. IF sy-subrc <> 0. unlock_and_raise_error( li_package ). ENDIF. TRY. CALL METHOD li_package->('SAVE') EXPORTING i_suppress_dialog = abap_true EXCEPTIONS object_invalid = 1 object_not_changeable = 2 cancelled_in_corr = 3 permission_failure = 4 unexpected_error = 5 intern_err = 6 OTHERS = 7. CATCH cx_sy_dyn_call_param_not_found. li_package->save( EXCEPTIONS object_invalid = 1 object_not_changeable = 2 cancelled_in_corr = 3 permission_failure = 4 unexpected_error = 5 intern_err = 6 OTHERS = 7 ). ENDTRY. IF sy-subrc <> 0. unlock_and_raise_error( li_package ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: li_package TYPE REF TO if_package, ls_package_data TYPE scompkdtln, ls_data_sign TYPE scompksign, lt_usage_data TYPE scomppdata, ls_save_sign TYPE paksavsign. FIELD-SYMBOLS: TYPE scomppdtln. FIELD-SYMBOLS: TYPE any. mv_local_devclass = iv_package. io_xml->read( EXPORTING iv_name = 'DEVC' CHANGING cg_data = ls_package_data ). IF mv_local_devclass(1) = '$'. IF ls_package_data-mainpack = 'X'. zcx_abapgit_exception=>raise( |Main package { iv_package } cannot be used in local package| ). ELSEIF ls_package_data-mainpack = 'S'. zcx_abapgit_exception=>raise( |Structure package { iv_package } cannot be used in local package| ). ENDIF. ENDIF. li_package = get_package( ). " Swap out repository package name with the local installation package name ls_package_data-devclass = mv_local_devclass. IF li_package IS BOUND. ls_package_data-pdevclass = li_package->transport_layer. ENDIF. " For local packages store application component IF ls_package_data-devclass(1) = '$'. zcl_abapgit_persist_packages=>get_instance( )->modify( iv_package = ls_package_data-devclass iv_component = ls_package_data-component iv_comp_posid = ls_package_data-comp_posid ). ENDIF. " Parent package is not changed. Assume the folder logic already created the package and set " the hierarchy before. CLEAR ls_package_data-parentcl. ASSIGN COMPONENT 'PACKKIND' OF STRUCTURE ls_package_data TO . IF sy-subrc = 0. set_abap_language_version( CHANGING cv_abap_language_version = ). ENDIF. ASSIGN COMPONENT 'PACKKIND' OF STRUCTURE ls_data_sign TO . IF sy-subrc = 0. = abap_true. ENDIF. * Fields not set: * korrflag * parentcl * cli_check * intprefx IF ls_package_data-dlvunit IS NOT INITIAL. ls_data_sign-dlvunit = abap_true. ENDIF. ls_data_sign-ctext = abap_true. ls_data_sign-as4user = abap_true. ls_data_sign-pdevclass = abap_true. ls_data_sign-comp_posid = abap_true. ls_data_sign-component = abap_true. ls_data_sign-perminher = abap_true. ls_data_sign-packtype = abap_true. ls_data_sign-restricted = abap_true. ls_data_sign-mainpack = abap_true. ls_data_sign-srv_check = abap_true. ls_data_sign-ext_alias = abap_true. ls_data_sign-project_guid = abap_true. ls_data_sign-project_id = abap_true. ls_data_sign-project_passdown = abap_true. IF ls_package_data-ctext IS INITIAL. ls_package_data-ctext = mv_local_devclass. ENDIF. IF ls_package_data-dlvunit IS INITIAL. ls_package_data-dlvunit = 'HOME'. ENDIF. ls_package_data-as4user = sy-uname. IF li_package IS BOUND. " Package already exists, change it set_lock( ii_package = li_package iv_lock = abap_true ). li_package->set_all_attributes( EXPORTING i_package_data = ls_package_data i_data_sign = ls_data_sign EXCEPTIONS object_not_changeable = 1 object_deleted = 2 object_invalid = 3 short_text_missing = 4 author_not_existing = 5 local_package = 6 software_component_invalid = 7 layer_invalid = 8 korrflag_invalid = 9 component_not_existing = 10 component_missing = 11 authorize_failure = 12 prefix_in_use = 13 unexpected_error = 14 intern_err = 15 * wrong_mainpack_value = 16 downport, does not exist in 7.30 * superpackage_invalid = 17 downport, does not exist in 7.30 OTHERS = 18 ). IF sy-subrc <> 0. unlock_and_raise_error( li_package ). ENDIF. ELSE. " Package does not exist yet, create it " This shouldn't really happen, because the folder logic initially creates the packages. cl_package_factory=>create_new_package( IMPORTING e_package = li_package CHANGING c_package_data = ls_package_data EXCEPTIONS object_already_existing = 1 object_just_created = 2 not_authorized = 3 wrong_name_prefix = 4 undefined_name = 5 reserved_local_name = 6 invalid_package_name = 7 short_text_missing = 8 software_component_invalid = 9 layer_invalid = 10 author_not_existing = 11 component_not_existing = 12 component_missing = 13 prefix_in_use = 14 unexpected_error = 15 intern_err = 16 no_access = 17 * invalid_translation_depth = 18 downport, does not exist in 7.30 * wrong_mainpack_value = 19 downport, does not exist in 7.30 * superpackage_invalid = 20 downport, does not exist in 7.30 * error_in_cts_checks = 21 downport, does not exist in 7.31 OTHERS = 22 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. " Load package interface usages TRY. io_xml->read( EXPORTING iv_name = 'PERMISSION' CHANGING cg_data = lt_usage_data ). CATCH zcx_abapgit_exception ##NO_HANDLER. " No permissions saved ENDTRY. LOOP AT lt_usage_data ASSIGNING . -client_pak = mv_local_devclass. ENDLOOP. update_pinf_usages( ii_package = li_package it_usage_data = lt_usage_data ). ls_save_sign-pack = abap_true. ls_save_sign-permis = abap_true. ls_save_sign-elems = abap_true. ls_save_sign-interf = abap_true. li_package->save_generic( EXPORTING i_save_sign = ls_save_sign i_transport_request = iv_transport i_suppress_dialog = abap_true EXCEPTIONS cancelled_in_corr = 1 permission_failure = 2 object_not_changeable = 3 object_invalid = 4 OTHERS = 5 ). IF sy-subrc <> 0. unlock_and_raise_error( li_package ). ENDIF. set_lock( ii_package = li_package iv_lock = abap_false ). ENDMETHOD. METHOD zif_abapgit_object~exists. " Check remote package if deserialize has not been called before this IF mv_local_devclass IS INITIAL. rv_bool = abap_false. ELSE. cl_package_helper=>check_package_existence( EXPORTING i_package_name = mv_local_devclass IMPORTING e_package_exists = rv_bool EXCEPTIONS intern_err = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'EEUDB' iv_argument = ms_item-obj_name iv_prefix = 'DV' ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. IF iv_filename <> zcl_abapgit_filename_logic=>c_package_file. zcx_abapgit_exception=>raise( |Unexpected filename for package { cs_item-obj_name }| ). ENDIF. " Try to get a unique package name for DEVC by using the path cs_item-obj_name = zcl_abapgit_folder_logic=>get_instance( )->path_to_package( iv_top = iv_package io_dot = io_dot iv_create_if_not_exists = abap_false iv_path = iv_path ). ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. " Packages have a fixed filename so that the repository can be installed to a different " package(-hierarchy) on the client and not show up as a different package in the repo. cv_filename = zcl_abapgit_filename_logic=>c_package_file. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_package_data TYPE scompkdtln, ls_package_comp TYPE zcl_abapgit_persist_packages=>ty_package, li_package TYPE REF TO if_package, lt_intf_usages TYPE tpak_permission_to_use_list, lt_usage_data TYPE scomppdata, ls_usage_data TYPE scomppdtln, li_usage TYPE REF TO if_package_permission_to_use. FIELD-SYMBOLS: TYPE any. li_package = get_package( ). IF li_package IS NOT BOUND. zcx_abapgit_exception=>raise( |Could not find package to serialize.| ). ENDIF. li_package->get_all_attributes( IMPORTING e_package_data = ls_package_data EXCEPTIONS object_invalid = 1 package_deleted = 2 intern_err = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. " For local packages get application component IF is_local( ls_package_data-devclass ) = abap_true. ls_package_comp = zcl_abapgit_persist_packages=>get_instance( )->read( ls_package_data-devclass ). ls_package_data-component = ls_package_comp-component. ls_package_data-comp_posid = ls_package_comp-comp_posid. ENDIF. CLEAR: ls_package_data-devclass, ls_package_data-parentcl. " Clear administrative data to prevent diffs CLEAR: ls_package_data-created_by, ls_package_data-created_on, ls_package_data-changed_by, ls_package_data-changed_on, ls_package_data-as4user. " Clear text descriptions that might be localized CLEAR: ls_package_data-comp_text, ls_package_data-dlvu_text, ls_package_data-layer_text. " Clear obsolete fields CLEAR: ls_package_data-intfprefx, ls_package_data-cli_check. " If software component is related to add-on and a valid namespace, then keep it adjust_sw_component( CHANGING cv_dlvunit = ls_package_data-dlvunit ). ASSIGN COMPONENT 'TRANSLATION_DEPTH_TEXT' OF STRUCTURE ls_package_data TO . IF sy-subrc = 0. CLEAR: . ENDIF. ASSIGN COMPONENT 'TRANSLATION_GRAPH_DEPTH_TEXT' OF STRUCTURE ls_package_data TO . IF sy-subrc = 0. CLEAR: . ENDIF. " Clear things related to local installation package CLEAR: ls_package_data-namespace, ls_package_data-dlvunit, ls_package_data-tpclass, ls_package_data-pdevclass. " Not usable on customer systems ASSIGN COMPONENT 'TRANSLATION_DEPTH' OF STRUCTURE ls_package_data TO . IF sy-subrc = 0. CLEAR: . ENDIF. ASSIGN COMPONENT 'TRANSLATION_GRAPH_DEPTH' OF STRUCTURE ls_package_data TO . IF sy-subrc = 0. CLEAR: . ENDIF. CLEAR: ls_package_data-korrflag. ASSIGN COMPONENT 'PACKKIND' OF STRUCTURE ls_package_data TO . IF sy-subrc = 0. clear_abap_language_version( CHANGING cv_abap_language_version = ). ENDIF. io_xml->add( iv_name = 'DEVC' ig_data = ls_package_data ). " Save package interface usages li_package->get_permissions_to_use( IMPORTING e_permissions = lt_intf_usages EXCEPTIONS object_invalid = 1 unexpected_error = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. LOOP AT lt_intf_usages INTO li_usage. li_usage->get_all_attributes( IMPORTING e_permission_data = ls_usage_data EXCEPTIONS object_invalid = 1 intern_err = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CLEAR: ls_usage_data-pack_name, ls_usage_data-client_pak. APPEND ls_usage_data TO lt_usage_data. ENDLOOP. IF lt_usage_data IS NOT INITIAL. io_xml->add( iv_name = 'PERMISSION' ig_data = lt_usage_data ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ddlx IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cg_metadata TO . IF sy-subrc = 0. CLEAR: . ENDIF. ENDMETHOD. METHOD clear_fields. FIELD-SYMBOLS: TYPE any. ASSIGN COMPONENT 'METADATA' OF STRUCTURE cg_data TO . ASSERT sy-subrc = 0. clear_field( EXPORTING iv_fieldname = 'CHANGED_AT' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'CHANGED_BY' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'CREATED_AT' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'CREATED_BY' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'RESPONSIBLE' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'PACKAGE_REF-NAME' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'CONTAINER_REF-PACKAGE_NAME' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'VERSION' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'RESPONSIBLE' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'MASTER_SYSTEM' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'ABAP_LANGUAGE_VERSION' CHANGING cg_metadata = ). clear_field( EXPORTING iv_fieldname = 'ABAP_LANGU_VERSION' CHANGING cg_metadata = ). ENDMETHOD. METHOD get_persistence. DATA: lx_error TYPE REF TO cx_root. TRY. IF mi_persistence IS NOT BOUND. CREATE OBJECT mi_persistence TYPE ('CL_DDLX_ADT_OBJECT_PERSIST'). ENDIF. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ri_persistence = mi_persistence. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lv_object_key TYPE seu_objkey, li_data_model TYPE REF TO if_wb_object_data_model, li_persistence TYPE REF TO if_wb_object_persist, lr_data TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE data. lv_object_key = ms_item-obj_name. TRY. CREATE DATA lr_data TYPE ('CL_DDLX_WB_OBJECT_DATA=>TY_OBJECT_DATA'). ASSIGN lr_data->* TO . CREATE OBJECT li_data_model TYPE ('CL_DDLX_WB_OBJECT_DATA'). li_persistence = get_persistence( ). li_persistence->get( EXPORTING p_object_key = lv_object_key p_version = swbm_version_active CHANGING p_object_data = li_data_model ). CATCH cx_root. rv_user = c_user_unknown. RETURN. ENDTRY. li_data_model->get_data( IMPORTING p_data = ). ASSIGN COMPONENT 'METADATA-CHANGED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. rv_user = . ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. lv_object_key = ms_item-obj_name. TRY. get_persistence( )->delete( p_object_key = lv_object_key p_version = swbm_version_active ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: li_data_model TYPE REF TO if_wb_object_data_model, lr_data TYPE REF TO data, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE data, TYPE data, TYPE data, TYPE syuname, TYPE xsddatetime_z. TRY. CREATE DATA lr_data TYPE ('CL_DDLX_WB_OBJECT_DATA=>TY_OBJECT_DATA'). ASSIGN lr_data->* TO . io_xml->read( EXPORTING iv_name = 'DDLX' CHANGING cg_data = ). ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. TRY. " If the file doesn't exist that's ok, because previously " the source code was stored in the xml. We are downward compatible. = mo_files->read_string( 'asddlxs' ). CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. CREATE OBJECT li_data_model TYPE ('CL_DDLX_WB_OBJECT_DATA'). ASSIGN COMPONENT 'METADATA-VERSION' OF STRUCTURE TO . ASSERT sy-subrc = 0. " We have to always save as inactive. Standard activation below activates then " and also creates transport request entry if necessary = 'inactive'. "package needed to be able to determine ABAP language version ASSIGN COMPONENT 'METADATA-PACKAGE_REF-NAME' OF STRUCTURE TO . IF IS ASSIGNED. = iv_package. ENDIF. ASSIGN COMPONENT 'METADATA-CHANGED_BY' OF STRUCTURE TO . IF IS ASSIGNED. = sy-uname. ENDIF. ASSIGN COMPONENT 'METADATA-CHANGED_AT' OF STRUCTURE TO . IF IS ASSIGNED. GET TIME STAMP FIELD . ENDIF. li_data_model->set_data( ). get_persistence( )->save( li_data_model ). tadir_insert( iv_package ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_object_key TYPE seu_objkey. lv_object_key = ms_item-obj_name. rv_bool = abap_true. TRY. get_persistence( )->get( p_object_key = lv_object_key p_version = swbm_version_active p_existence_check_only = abap_true ). CATCH cx_swb_exception. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_ADT_LINK=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_object_key TYPE seu_objkey, li_data_model TYPE REF TO if_wb_object_data_model, li_persistence TYPE REF TO if_wb_object_persist, lr_data TYPE REF TO data, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE data. lv_object_key = ms_item-obj_name. TRY. CREATE DATA lr_data TYPE ('CL_DDLX_WB_OBJECT_DATA=>TY_OBJECT_DATA'). ASSIGN lr_data->* TO . CREATE OBJECT li_data_model TYPE ('CL_DDLX_WB_OBJECT_DATA'). li_persistence = get_persistence( ). IF zcl_abapgit_factory=>get_environment( )->compare_with_inactive( ) = abap_true. "Retrieve inactive version li_persistence->get( EXPORTING p_object_key = lv_object_key p_version = swbm_version_inactive CHANGING p_object_data = li_data_model ). IF li_data_model->get_object_name( ) IS INITIAL. "Fallback: retrieve active version li_persistence->get( EXPORTING p_object_key = lv_object_key p_version = swbm_version_active CHANGING p_object_data = li_data_model ). ENDIF. ELSE. "Retrieve active version li_persistence->get( EXPORTING p_object_key = lv_object_key p_version = swbm_version_active CHANGING p_object_data = li_data_model ). ENDIF. li_data_model->get_data( IMPORTING p_data = ). clear_fields( CHANGING cg_data = ). ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. mo_files->add_string( iv_ext = 'asddlxs' iv_string = ). CLEAR . io_xml->add( iv_name = 'DDLX' ig_data = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ddls IMPLEMENTATION. METHOD constructor. DATA lo_ddl TYPE REF TO object. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). TRY. CALL METHOD ('CL_DD_DDL_HANDLER_FACTORY')=>('CREATE') RECEIVING handler = lo_ddl. CATCH cx_root. zcx_abapgit_exception=>raise( 'Object type DDLS is not supported by this system' ). ENDTRY. ENDMETHOD. METHOD format_source_before_serialize. DATA: lv_len TYPE i, lv_lastchar1 TYPE c, lv_lastchar2 TYPE c. " New line included in 751+ by CL_DD_DDL_HANDLER=>ADD_BASEOBJS_INFO_TO_DDLS " Change for 750- lv_len = strlen( cv_string ) - 1. IF lv_len < 0. RETURN. ENDIF. lv_lastchar1 = cv_string+lv_len(1). lv_len = strlen( cv_string ) - 2. IF lv_len < 0. RETURN. ENDIF. lv_lastchar2 = cv_string+lv_len(1). " only add a line break, if the last character is unequal to cr_lf and newline ! IF lv_lastchar1 <> cl_abap_char_utilities=>cr_lf AND lv_lastchar1 <> cl_abap_char_utilities=>newline AND lv_lastchar1 <> space OR ( lv_lastchar1 = space AND ( lv_lastchar2 <> cl_abap_char_utilities=>cr_lf AND lv_lastchar2 <> cl_abap_char_utilities=>newline ) ). cv_string = |{ cv_string }{ cl_abap_char_utilities=>cr_lf }|. ENDIF. ENDMETHOD. METHOD is_baseinfo_supported. DATA: lr_data_baseinfo TYPE REF TO data, lx_error TYPE REF TO cx_root. TRY. CREATE DATA lr_data_baseinfo TYPE ('IF_DD_DDL_TYPES=>TY_S_BASEINFO_STRING_SAVE'). rv_supported = abap_true. CATCH cx_root INTO lx_error. rv_supported = abap_false. ENDTRY. ENDMETHOD. METHOD open_adt_stob. DATA: lr_data TYPE REF TO data, lo_ddl TYPE REF TO object, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE any. FIELD-SYMBOLS: TYPE any. FIELD-SYMBOLS: TYPE any. FIELD-SYMBOLS: TYPE any. TRY. CREATE DATA lr_data TYPE ('IF_DD_DDL_TYPES=>TY_T_DDOBJ'). ASSIGN lr_data->* TO . CREATE DATA lr_data LIKE LINE OF . ASSIGN lr_data->* TO . CREATE DATA lr_data TYPE ('IF_DD_DDL_TYPES=>TY_T_ENTITY_OF_VIEW'). ASSIGN lr_data->* TO . CREATE DATA lr_data LIKE LINE OF . ASSIGN lr_data->* TO . CLEAR . ASSIGN COMPONENT 'NAME' OF STRUCTURE TO . = iv_ddls_name. INSERT INTO TABLE . CALL METHOD ('CL_DD_DDL_HANDLER_FACTORY')=>('CREATE') RECEIVING handler = lo_ddl. CALL METHOD lo_ddl->('IF_DD_DDL_HANDLER~GET_VIEWNAME_FROM_ENTITYNAME') EXPORTING ddnames = IMPORTING view_of_entity = . READ TABLE ASSIGNING INDEX 1. IF sy-subrc = 0. ASSIGN COMPONENT 'DDLNAME' OF STRUCTURE TO . zcl_abapgit_adt_link=>jump( iv_obj_name = iv_obj_type = 'DDLS' ). ENDIF. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD read_baseinfo. TRY. rv_baseinfo_string = mo_files->read_string( 'baseinfo' ). CATCH zcx_abapgit_exception. " File not found. That's ok, as the object could have been created in a " system where baseinfo wasn't supported. RETURN. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lo_ddl TYPE REF TO object, lr_data TYPE REF TO data, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE DATA lr_data TYPE ('DDDDLSRCV'). ASSIGN lr_data->* TO . CALL METHOD ('CL_DD_DDL_HANDLER_FACTORY')=>('CREATE') RECEIVING handler = lo_ddl. CALL METHOD lo_ddl->('IF_DD_DDL_HANDLER~READ') EXPORTING name = ms_item-obj_name get_state = 'A' IMPORTING ddddlsrcv_wa = . ASSIGN COMPONENT 'AS4USER' OF STRUCTURE TO . IF sy-subrc = 0. rv_user = . ENDIF. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. IF rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lt_deltab TYPE TABLE OF dcdeltb, ls_deltab TYPE dcdeltb, lt_gentab TYPE TABLE OF dcgentb, lv_rc TYPE sy-subrc. " CL_DD_DDL_HANDLER->DELETE does not work for CDS views that reference other views " To drop any views regardless of reference, we use delnoref = false ls_deltab-objtyp = 'DDLS'. ls_deltab-objname = ms_item-obj_name. APPEND ls_deltab TO lt_deltab. CALL FUNCTION 'DD_MASS_ACT_C3' EXPORTING ddmode = 'O' inactive = abap_true write_log = abap_false delall = abap_true delnoref = abap_false prid = -1 IMPORTING act_rc = lv_rc TABLES gentab = lt_gentab deltab = lt_deltab EXCEPTIONS access_failure = 1 no_objects = 2 locked = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. corr_insert( iv_package ). " rebuild object list to delete remaining TADIR entry CALL FUNCTION 'WB_TREE_UPDATE_OBJECTLIST' EXPORTING p_object_type = 'DF' p_object_name = ms_item-obj_name p_operation = 'DELETE' EXCEPTIONS OTHERS = 0. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_ddl TYPE REF TO object, lr_data TYPE REF TO data, lr_data_baseinfo TYPE REF TO data, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any, TYPE any, TYPE any. TRY. CREATE DATA lr_data TYPE ('DDDDLSRCV'). ASSIGN lr_data->* TO . io_xml->read( EXPORTING iv_name = 'DDLS' CHANGING cg_data = ). ASSIGN COMPONENT 'SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. = mo_files->read_string( 'asddls' ). CALL METHOD ('CL_DD_DDL_HANDLER_FACTORY')=>('CREATE') RECEIVING handler = lo_ddl. IF is_baseinfo_supported( ) = abap_true. CREATE DATA lr_data_baseinfo TYPE ('IF_DD_DDL_TYPES=>TY_S_BASEINFO_STRING_SAVE'). ASSIGN lr_data_baseinfo->* TO . ASSIGN COMPONENT 'BASEINFO_STRING' OF STRUCTURE TO . ASSERT sy-subrc = 0. = read_baseinfo( ). ASSIGN COMPONENT 'DDLNAME' OF STRUCTURE TO . ASSERT sy-subrc = 0. = ms_item-obj_name. CALL METHOD lo_ddl->('IF_DD_DDL_HANDLER~SAVE') EXPORTING name = ms_item-obj_name put_state = 'N' ddddlsrcv_wa = baseinfo_string = . ELSE. CALL METHOD lo_ddl->('IF_DD_DDL_HANDLER~SAVE') EXPORTING name = ms_item-obj_name put_state = 'N' ddddlsrcv_wa = . ENDIF. CALL METHOD lo_ddl->('IF_DD_DDL_HANDLER~WRITE_TADIR') EXPORTING objectname = ms_item-obj_name devclass = iv_package prid = 0. corr_insert( iv_package ). CATCH cx_root INTO lx_error. IF lo_ddl IS NOT INITIAL. " Attempt clean-up but catch error if it doesn't work TRY. CALL METHOD lo_ddl->('IF_DD_DDL_HANDLER~DELETE') EXPORTING name = ms_item-obj_name prid = 0. CATCH cx_root ##NO_HANDLER. ENDTRY. ENDIF. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_state TYPE objstate, lo_ddl TYPE REF TO object. TRY. CALL METHOD ('CL_DD_DDL_HANDLER_FACTORY')=>('CREATE') RECEIVING handler = lo_ddl. CALL METHOD lo_ddl->('IF_DD_DDL_HANDLER~READ') EXPORTING name = ms_item-obj_name IMPORTING got_state = lv_state. rv_bool = boolc( NOT lv_state IS INITIAL ). CATCH cx_root. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lv_typename TYPE typename. DATA: lv_ddtypekind TYPE ddtypekind. lv_typename = ms_item-obj_name. CALL FUNCTION 'DDIF_TYPEINFO_GET' EXPORTING typename = lv_typename IMPORTING typekind = lv_ddtypekind. IF lv_ddtypekind = 'STOB'. open_adt_stob( ms_item-obj_name ). rv_exit = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_ddl TYPE REF TO object, lr_data TYPE REF TO data, lr_data_baseinfo TYPE REF TO data, lt_clr_comps TYPE STANDARD TABLE OF fieldname WITH DEFAULT KEY, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any, LIKE LINE OF lt_clr_comps, TYPE ANY TABLE, TYPE any, TYPE any, TYPE any. TRY. CREATE DATA lr_data TYPE ('DDDDLSRCV'). ASSIGN lr_data->* TO . CALL METHOD ('CL_DD_DDL_HANDLER_FACTORY')=>('CREATE') RECEIVING handler = lo_ddl. IF is_baseinfo_supported( ) = abap_true. CREATE DATA lr_data_baseinfo TYPE ('IF_DD_DDL_TYPES=>TY_T_BASEINFO_STRING'). ASSIGN lr_data_baseinfo->* TO . ASSIGN lr_data_baseinfo->* TO . CALL METHOD lo_ddl->('IF_DD_DDL_HANDLER~READ') EXPORTING name = ms_item-obj_name get_state = 'A' IMPORTING ddddlsrcv_wa = baseinfo_string = . LOOP AT ASSIGNING . ASSIGN COMPONENT 'DDLNAME' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'AS4LOCAL' OF STRUCTURE TO . ASSERT sy-subrc = 0. IF = ms_item-obj_name AND = 'A'. ASSIGN COMPONENT 'BASEINFO_STRING' OF STRUCTURE TO . ASSERT sy-subrc = 0. mo_files->add_string( iv_ext = 'baseinfo' iv_string = ). EXIT. ENDIF. ENDLOOP. ELSE. CALL METHOD lo_ddl->('IF_DD_DDL_HANDLER~READ') EXPORTING name = ms_item-obj_name get_state = 'A' IMPORTING ddddlsrcv_wa = . ENDIF. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. APPEND 'AS4USER' TO lt_clr_comps. APPEND 'AS4DATE' TO lt_clr_comps. APPEND 'AS4TIME' TO lt_clr_comps. APPEND 'ACTFLAG' TO lt_clr_comps. APPEND 'CHGFLAG' TO lt_clr_comps. APPEND 'ABAP_LANGUAGE_VERSION' TO lt_clr_comps. APPEND 'ABAP_LANGU_VERSION' TO lt_clr_comps. LOOP AT lt_clr_comps ASSIGNING . ASSIGN COMPONENT OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ENDLOOP. ASSIGN COMPONENT 'SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. format_source_before_serialize( CHANGING cv_string = ). mo_files->add_string( iv_ext = 'asddls' iv_string = ). CLEAR . io_xml->add( iv_name = 'DDLS' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_dcls IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lr_data TYPE REF TO data, lo_dcl TYPE REF TO object, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. CREATE DATA lr_data TYPE ('ACM_S_DCLSRC'). ASSIGN lr_data->* TO . TRY. CALL METHOD ('CL_ACM_DCL_HANDLER_FACTORY')=>('CREATE') RECEIVING ro_handler = lo_dcl. CALL METHOD lo_dcl->('READ') EXPORTING iv_dclname = ms_item-obj_name IMPORTING es_dclsrc = . ASSIGN COMPONENT 'AS4USER' OF STRUCTURE TO . IF sy-subrc = 0. rv_user = . ELSE. rv_user = c_user_unknown. ENDIF. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_dcl TYPE REF TO object, lx_error TYPE REF TO cx_root. TRY. CALL METHOD ('CL_ACM_DCL_HANDLER_FACTORY')=>('CREATE') RECEIVING ro_handler = lo_dcl. CALL METHOD lo_dcl->('DELETE') EXPORTING iv_dclname = ms_item-obj_name. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lr_data TYPE REF TO data, lo_dcl TYPE REF TO object, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. CREATE DATA lr_data TYPE ('ACM_S_DCLSRC'). ASSIGN lr_data->* TO . io_xml->read( EXPORTING iv_name = 'DCLS' CHANGING cg_data = ). ASSIGN COMPONENT 'SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. = mo_files->read_string( 'asdcls' ). TRY. tadir_insert( iv_package ). CALL METHOD ('CL_ACM_DCL_HANDLER_FACTORY')=>('CREATE') RECEIVING ro_handler = lo_dcl. CALL METHOD lo_dcl->('SAVE') EXPORTING iv_dclname = ms_item-obj_name iv_put_state = 'I' is_dclsrc = iv_devclass = iv_package iv_access_mode = 'INSERT'. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lo_dcl TYPE REF TO object, lx_error TYPE REF TO cx_root. TRY. CALL METHOD ('CL_ACM_DCL_HANDLER_FACTORY')=>('CREATE') RECEIVING ro_handler = lo_dcl. CALL METHOD lo_dcl->('CHECK_EXISTENCE') EXPORTING iv_objectname = ms_item-obj_name RECEIVING rv_exists = rv_bool. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_ACMDCLSRC' iv_argument = |{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_ADT_LINK=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lr_data TYPE REF TO data, lo_dcl TYPE REF TO object, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. CREATE DATA lr_data TYPE ('ACM_S_DCLSRC'). ASSIGN lr_data->* TO . TRY. CALL METHOD ('CL_ACM_DCL_HANDLER_FACTORY')=>('CREATE') RECEIVING ro_handler = lo_dcl. CALL METHOD lo_dcl->('READ') EXPORTING iv_dclname = ms_item-obj_name IMPORTING es_dclsrc = . ASSIGN COMPONENT 'AS4USER' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'AS4DATE' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'AS4TIME' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'CREATED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'CREATED_DATE' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'AS4LOCAL' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR . ASSIGN COMPONENT 'ABAP_LANGUAGE_VERSION' OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. mo_files->add_string( iv_ext = 'asdcls' iv_string = ). CLEAR . io_xml->add( iv_name = 'DCLS' ig_data = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_cus2 IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_img_attribute = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA ls_header TYPE ty_customizing_attribute-header. CALL FUNCTION 'S_CUS_ATTRIBUTES_READ' EXPORTING img_attribute = mv_img_attribute IMPORTING attribute_header = ls_header. rv_user = ls_header-luser. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_message TYPE hier_mess. CALL FUNCTION 'S_CUS_ATTRIBUTES_DELETE' EXPORTING img_attribute = mv_img_attribute IMPORTING message = ls_message. IF ls_message-msgty <> 'S'. zcx_abapgit_exception=>raise( |error from delete CUS2 { mv_img_attribute } S_CUS_ATTRIBUTES_DELETE| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_customizing_attribute TYPE ty_customizing_attribute, ls_message TYPE hier_mess. io_xml->read( EXPORTING iv_name = 'CUS2' CHANGING cg_data = ls_customizing_attribute ). CALL FUNCTION 'S_CUS_ATTRIBUTES_SAVE' EXPORTING img_attribute = ls_customizing_attribute-header IMPORTING message = ls_message TABLES attributes_title = ls_customizing_attribute-titles attributes_countries = ls_customizing_attribute-countries attributes_components = ls_customizing_attribute-components. IF ls_message-msgty <> 'S'. zcx_abapgit_exception=>raise( |error from deserialize CUS2 { mv_img_attribute } S_CUS_ATTRIBUTES_SAVE| ). ENDIF. corr_insert( iv_package ). tadir_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. CALL FUNCTION 'S_CUS_ATTRIBUTES_EXIST' EXPORTING img_attribute = mv_img_attribute EXCEPTIONS attributes_exists_not = 1 OTHERS = 2. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = abap_true. ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_customizing_attribute TYPE ty_customizing_attribute. CALL FUNCTION 'S_CUS_ATTRIBUTES_READ' EXPORTING img_attribute = mv_img_attribute IMPORTING attribute_header = ls_customizing_attribute-header TABLES attribute_title = ls_customizing_attribute-titles attribute_countries = ls_customizing_attribute-countries attribute_components = ls_customizing_attribute-components attribute_components_variants = ls_customizing_attribute-components_variants. CLEAR: ls_customizing_attribute-header-fdatetime, ls_customizing_attribute-header-fuser, ls_customizing_attribute-header-ldatetime, ls_customizing_attribute-header-luser. IF mo_i18n_params->ms_params-main_language_only = abap_true. DELETE ls_customizing_attribute-titles WHERE spras <> mv_language. ENDIF. io_xml->add( iv_name = 'CUS2' ig_data = ls_customizing_attribute ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_cus1 IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_customizing_activity = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA ls_header TYPE ty_customzing_activity-activity_header. CALL FUNCTION 'S_CUS_ACTIVITY_READ' EXPORTING activity = mv_customizing_activity IMPORTING activity_header = ls_header. rv_user = ls_header-luser. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_message TYPE hier_mess. CALL FUNCTION 'S_CUS_ACTIVITY_DELETE' EXPORTING activity = mv_customizing_activity IMPORTING message = ls_message. IF ls_message-msgty <> 'S'. zcx_abapgit_exception=>raise( |error from delete CUS1 { mv_customizing_activity } S_CUS_ACTIVITY_DELETE| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_customzing_activity TYPE ty_customzing_activity, ls_message TYPE hier_mess. io_xml->read( EXPORTING iv_name = 'CUS1' CHANGING cg_data = ls_customzing_activity ). CALL FUNCTION 'S_CUS_ACTIVITY_SAVE' EXPORTING activity = ls_customzing_activity-activity_header-act_id activity_type = ls_customzing_activity-activity_header-act_type tcode = ls_customzing_activity-activity_header-tcode customer_exit = ls_customzing_activity-activity_customer_exit-exit_name customer_exit_enhancement = ls_customzing_activity-activity_customer_exit-enhancement customer_exit_implementation = ls_customzing_activity-activity_customer_exit-impl_name IMPORTING message = ls_message TABLES activity_title = ls_customzing_activity-activity_title objects = ls_customzing_activity-objects objects_texts = ls_customzing_activity-objects_title. IF ls_message-msgty <> 'S'. zcx_abapgit_exception=>raise( |error from deserialize CUS1 { mv_customizing_activity } S_CUS_ACTIVITY_SAVE| ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. CALL FUNCTION 'S_CUS_ACTIVITY_EXIST' EXPORTING activity = mv_customizing_activity EXCEPTIONS activity_exists_not = 1 OTHERS = 2. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = abap_true. ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lt_bdc_data TYPE STANDARD TABLE OF bdcdata. FIELD-SYMBOLS: TYPE bdcdata. APPEND INITIAL LINE TO lt_bdc_data ASSIGNING . -program = 'SAPLS_CUS_ACTIVITY'. -dynpro = '0200'. -dynbegin = 'X'. APPEND INITIAL LINE TO lt_bdc_data ASSIGNING . -fnam = 'CUS_ACTH-ACT_ID'. -fval = mv_customizing_activity. APPEND INITIAL LINE TO lt_bdc_data ASSIGNING . -fnam = 'BDC_OKCODE'. -fval = '=ACT_DISP'. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'S_CUS_ACTIVITY' it_bdcdata = lt_bdc_data ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_customzing_activity TYPE ty_customzing_activity. CALL FUNCTION 'S_CUS_ACTIVITY_READ' EXPORTING activity = mv_customizing_activity IMPORTING activity_header = ls_customzing_activity-activity_header activity_customer_exit = ls_customzing_activity-activity_customer_exit TABLES activity_title = ls_customzing_activity-activity_title objects = ls_customzing_activity-objects objects_title = ls_customzing_activity-objects_title. CLEAR: ls_customzing_activity-activity_header-fdatetime, ls_customzing_activity-activity_header-fuser, ls_customzing_activity-activity_header-ldatetime, ls_customzing_activity-activity_header-luser. IF mo_i18n_params->ms_params-main_language_only = abap_true. DELETE ls_customzing_activity-activity_title WHERE spras <> mv_language. ENDIF. SORT ls_customzing_activity-activity_title. SORT ls_customzing_activity-objects. SORT ls_customzing_activity-objects_title. io_xml->add( iv_name = 'CUS1' ig_data = ls_customzing_activity ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_cus0 IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_img_activity = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA ls_header TYPE ty_img_activity-header. CALL FUNCTION 'S_CUS_IMG_ACTIVITY_READ' EXPORTING img_activity = mv_img_activity IMPORTING img_activity_header = ls_header. rv_user = ls_header-luser. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_message TYPE hier_mess. CALL FUNCTION 'S_CUS_IMG_ACTIVITY_DELETE' EXPORTING img_activity = mv_img_activity IMPORTING message = ls_message. IF ls_message-msgty <> 'S'. zcx_abapgit_exception=>raise( |error from delete CUS0 { mv_img_activity } S_CUS_IMG_ACTIVITY_DELETE| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_img_activity TYPE ty_img_activity, ls_text LIKE LINE OF ls_img_activity-texts. io_xml->read( EXPORTING iv_name = 'CUS0' CHANGING cg_data = ls_img_activity ). READ TABLE ls_img_activity-texts INTO ls_text WITH KEY spras = mv_language. CALL FUNCTION 'S_CUS_IMG_ACTIVITY_SAVE' EXPORTING img_activity = ls_img_activity-header-activity i_docu = ls_img_activity-header-docu_id i_attributes = ls_img_activity-header-attributes i_activity = ls_img_activity-header-c_activity i_description = ls_text i_tcode = ls_img_activity-header-tcode. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: ls_message TYPE hier_mess. CALL FUNCTION 'S_CUS_IMG_ACTIVITY_EXISTS' EXPORTING img_activity = mv_img_activity IMPORTING message = ls_message. rv_bool = boolc( ls_message IS INITIAL ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = abap_true. ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lv_img_activity TYPE cus_img_ac. lv_img_activity = mv_img_activity. CALL FUNCTION 'S_CUS_IMG_ACTIVITY_MAINTAIN' EXPORTING i_display = abap_true CHANGING img_activity = lv_img_activity. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_img_activity TYPE ty_img_activity. CALL FUNCTION 'S_CUS_IMG_ACTIVITY_READ' EXPORTING img_activity = mv_img_activity IMPORTING img_activity_header = ls_img_activity-header TABLES img_activity_texts = ls_img_activity-texts. CLEAR: ls_img_activity-header-fuser, ls_img_activity-header-fdate, ls_img_activity-header-ftime, ls_img_activity-header-luser, ls_img_activity-header-ldate, ls_img_activity-header-ltime. IF mo_i18n_params->ms_params-main_language_only = abap_true. DELETE ls_img_activity-texts WHERE spras <> mv_language. ENDIF. SORT ls_img_activity-texts. io_xml->add( iv_name = 'CUS0' ig_data = ls_img_activity ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_cmpt IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). TRY. CALL METHOD ('CL_CMP_TEMPLATE')=>('S_GET_DB_ACCESS') RECEIVING r_ref_db_access = mo_cmp_db. CATCH cx_root. ENDTRY. mv_name = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lo_cmp_template TYPE REF TO object. TRY. CALL METHOD ('CL_CMP_TEMPLATE')=>('S_CREATE_FROM_DB') EXPORTING i_name = mv_name i_version = 'A' RECEIVING r_ref_template = lo_cmp_template. CALL METHOD lo_cmp_template->('IF_CMP_TEMPLATE_EDIT~GET_CHANGE_USER') RECEIVING r_user = rv_user. CATCH cx_root. zcx_abapgit_exception=>raise( 'CMPT not supported' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_deleted TYPE abap_bool. TRY. CALL METHOD mo_cmp_db->('IF_CMP_TEMPLATE_DB~DELETE_TEMPLATE') EXPORTING i_name = mv_name i_version = 'A' i_flg_header = abap_true i_flg_lines = abap_true RECEIVING r_flg_deleted = lv_deleted. CATCH cx_root. zcx_abapgit_exception=>raise( 'CMPT not supported' ). ENDTRY. IF lv_deleted = abap_false. zcx_abapgit_exception=>raise( |Error deleting CMPT { ms_item-obj_name }| ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lr_template TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any. TRY. CREATE DATA lr_template TYPE ('IF_CMP_TEMPLATE_DB=>TYP_TEMPLATE'). ASSIGN lr_template->* TO . io_xml->read( EXPORTING iv_name = 'CMPT' CHANGING cg_data = ). ASSIGN COMPONENT 'STR_HEADER' OF STRUCTURE TO . IF sy-subrc = 0. ASSIGN COMPONENT 'NAME' OF STRUCTURE TO . IF sy-subrc = 0. = ms_item-obj_name. ENDIF. ASSIGN COMPONENT 'VERSION' OF STRUCTURE TO . IF sy-subrc = 0. = 'A'. ENDIF. ENDIF. CALL METHOD mo_cmp_db->('IF_CMP_TEMPLATE_DB~SAVE_TEMPLATE') EXPORTING i_template_db = i_flg_header = abap_true i_flg_lines = abap_true. CATCH cx_root. zcx_abapgit_exception=>raise( 'CMPT not supported' ). ENDTRY. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. CALL METHOD ('CL_CMP_TEMPLATE')=>('S_TEMPLATE_EXISTS') EXPORTING i_name = mv_name i_version = 'A' RECEIVING r_flg_exists = rv_bool. IF rv_bool = abap_false. CALL METHOD ('CL_CMP_TEMPLATE')=>('S_TEMPLATE_EXISTS') EXPORTING i_name = mv_name i_version = 'I' RECEIVING r_flg_exists = rv_bool. ENDIF. CATCH cx_root. zcx_abapgit_exception=>raise( 'CMPT not supported' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lr_template TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any. TRY. CREATE DATA lr_template TYPE ('IF_CMP_TEMPLATE_DB=>TYP_TEMPLATE'). ASSIGN lr_template->* TO . CALL METHOD mo_cmp_db->('IF_CMP_TEMPLATE_DB~READ_TEMPLATE') EXPORTING i_name = |{ ms_item-obj_name }| i_version = 'A' RECEIVING r_template = . ASSIGN COMPONENT 'STR_HEADER' OF STRUCTURE TO . IF sy-subrc = 0. ASSIGN COMPONENT 'NAME' OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'VERSION' OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'CHANGED_ON' OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ASSIGN COMPONENT 'CHANGED_TS' OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ENDIF. io_xml->add( iv_name = 'CMPT' ig_data = ). CATCH cx_root. zcx_abapgit_exception=>raise( 'CMPT not supported' ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_cmod IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. SELECT SINGLE anam FROM modattr INTO rv_user WHERE name = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA lv_name TYPE modact-name. lv_name = ms_item-obj_name. CALL FUNCTION 'MOD_KUN_ACTIVATE' EXPORTING activate = abap_false deactivate = abap_true modname = lv_name EXCEPTIONS call_error = 1 generate_error = 2 modattr_status = 3 mod_active = 4 mod_enqueued = 5 not_activated = 6 no_modification = 7 permission_failure = 8 OTHERS = 9. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'MOD_KUN_DELETE' EXPORTING modname = lv_name screen = abap_false EXCEPTIONS attr_enqueued = 1 mod_active = 2 mod_enqueued = 3 text_enqueued = 4 permission_failure = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_name TYPE modact-name, lt_modact TYPE TABLE OF modact, lt_modtext TYPE TABLE OF modtext, lt_modattr TYPE TABLE OF modattr. lv_name = ms_item-obj_name. DELETE FROM modact WHERE name = lv_name. DELETE FROM modtext WHERE name = lv_name. DELETE FROM modattr WHERE name = lv_name. io_xml->read( EXPORTING iv_name = 'MODACT' CHANGING cg_data = lt_modact ). io_xml->read( EXPORTING iv_name = 'MODTEXT' CHANGING cg_data = lt_modtext ). io_xml->read( EXPORTING iv_name = 'MODATTR' CHANGING cg_data = lt_modattr ). INSERT modact FROM TABLE lt_modact. INSERT modtext FROM TABLE lt_modtext. INSERT modattr FROM TABLE lt_modattr. tadir_insert( iv_package ). CALL FUNCTION 'MOD_KUN_ACTIVATE' EXPORTING activate = abap_true deactivate = abap_false modname = lv_name EXCEPTIONS call_error = 1 generate_error = 2 modattr_status = 3 mod_active = 4 mod_enqueued = 5 not_activated = 6 no_modification = 7 permission_failure = 8 OTHERS = 9. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_name TYPE modact-name. SELECT SINGLE name FROM modact INTO lv_name WHERE name = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lt_modact TYPE TABLE OF modact, lt_modtext TYPE TABLE OF modtext, lt_modattr TYPE TABLE OF modattr. FIELD-SYMBOLS: TYPE modattr. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. SELECT * FROM modact INTO TABLE lt_modact WHERE name = ms_item-obj_name ORDER BY PRIMARY KEY. IF sy-subrc = 0. io_xml->add( iv_name = 'MODACT' ig_data = lt_modact ). ENDIF. SELECT * FROM modtext INTO TABLE lt_modtext WHERE name = ms_item-obj_name AND sprsl = mv_language ORDER BY PRIMARY KEY. IF sy-subrc = 0. io_xml->add( iv_name = 'MODTEXT' ig_data = lt_modtext ). ENDIF. SELECT * FROM modattr INTO TABLE lt_modattr WHERE name = ms_item-obj_name ORDER BY PRIMARY KEY. IF sy-subrc = 0. LOOP AT lt_modattr ASSIGNING . CLEAR: -cnam, -cdat, -unam, -udat, -anam, -adat, -fnam, -fdat. ENDLOOP. io_xml->add( iv_name = 'MODATTR' ig_data = lt_modattr ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_clas IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mi_object_oriented_object_fct = zcl_abapgit_oo_factory=>get_by_type( ms_item-obj_type ). mv_classpool_name = cl_oo_classname_service=>get_classpool_name( |{ is_item-obj_name }| ). ENDMETHOD. METHOD deserialize_abap. DATA: ls_vseoclass TYPE vseoclass, lt_source TYPE seop_source_string, lt_local_definitions TYPE seop_source_string, lt_local_implementations TYPE seop_source_string, lt_local_macros TYPE seop_source_string, lt_test_classes TYPE seop_source_string, lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, lt_descriptions_sub TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt, ls_class_key TYPE seoclskey, lt_attributes TYPE zif_abapgit_oo_object_fnc=>ty_obj_attribute_tt. lt_source = mo_files->read_abap( ). lt_local_definitions = mo_files->read_abap( iv_extra = zif_abapgit_oo_object_fnc=>c_parts-locals_def iv_error = abap_false ). lt_local_implementations = mo_files->read_abap( iv_extra = zif_abapgit_oo_object_fnc=>c_parts-locals_imp iv_error = abap_false ). lt_local_macros = mo_files->read_abap( iv_extra = zif_abapgit_oo_object_fnc=>c_parts-macros iv_error = abap_false ). lt_test_classes = mo_files->read_abap( iv_extra = zif_abapgit_oo_object_fnc=>c_parts-testclasses iv_error = abap_false ). ls_class_key-clsname = ms_item-obj_name. ii_xml->read( EXPORTING iv_name = 'VSEOCLASS' CHANGING cg_data = ls_vseoclass ). set_abap_language_version( CHANGING cv_abap_language_version = ls_vseoclass-unicode ). ii_xml->read( EXPORTING iv_name = 'ATTRIBUTES' CHANGING cg_data = lt_attributes ). " Remove code for test classes if they have been deleted IF ls_vseoclass-with_unit_tests = abap_false. CLEAR lt_test_classes. ENDIF. mi_object_oriented_object_fct->create( EXPORTING iv_check = abap_true iv_package = iv_package it_attributes = lt_attributes CHANGING cg_properties = ls_vseoclass ). mi_object_oriented_object_fct->generate_locals( is_key = ls_class_key iv_package = iv_package iv_version = ls_vseoclass-unicode it_local_definitions = lt_local_definitions it_local_implementations = lt_local_implementations it_local_macros = lt_local_macros it_local_test_classes = lt_test_classes ). repo_apack_replacement( CHANGING ct_source = lt_source ). mi_object_oriented_object_fct->deserialize_source( is_key = ls_class_key iv_package = iv_package iv_version = ls_vseoclass-unicode it_source = lt_source ). ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS' CHANGING cg_data = lt_descriptions ). mi_object_oriented_object_fct->update_descriptions( is_key = ls_class_key it_descriptions = lt_descriptions ). ii_xml->read( EXPORTING iv_name = 'DESCRIPTIONS_SUB' CHANGING cg_data = lt_descriptions_sub ). mi_object_oriented_object_fct->update_descriptions_sub( is_key = ls_class_key it_descriptions = lt_descriptions_sub ). mi_object_oriented_object_fct->add_to_activation_list( ms_item ). ENDMETHOD. METHOD deserialize_docu. DATA: lt_lines TYPE tlinetab, lv_object TYPE dokhl-object, lt_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_lines, ls_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_line. ii_xml->read( EXPORTING iv_name = 'LINES' CHANGING cg_data = lt_lines ). lv_object = ms_item-obj_name. IF lines( lt_lines ) = 0. mi_object_oriented_object_fct->delete_documentation( iv_id = c_longtext_id-class iv_object_name = lv_object iv_language = mv_language ). RETURN. ENDIF. mi_object_oriented_object_fct->create_documentation( it_lines = lt_lines iv_id = c_longtext_id-class iv_object_name = lv_object iv_language = mv_language ). ii_xml->read( EXPORTING iv_name = 'I18N_LINES' CHANGING cg_data = lt_i18n_lines ). LOOP AT lt_i18n_lines INTO ls_i18n_lines. mi_object_oriented_object_fct->create_documentation( it_lines = ls_i18n_lines-lines iv_id = c_longtext_id-class iv_object_name = lv_object iv_language = ls_i18n_lines-language iv_no_masterlang = abap_true ). ENDLOOP. deserialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-attributes iv_longtext_id = c_longtext_id-attributes ). deserialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-methods iv_longtext_id = c_longtext_id-methods ). deserialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-events iv_longtext_id = c_longtext_id-events ). deserialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-types iv_longtext_id = c_longtext_id-types ). ENDMETHOD. METHOD deserialize_exceptions. DATA: ls_vseoclass TYPE vseoclass. ii_xml->read( EXPORTING iv_name = 'VSEOCLASS' CHANGING cg_data = ls_vseoclass ). " For exceptions that are sub-class of another exception, we need to set the category explicitly (#6490) IF ls_vseoclass-category = '40'. UPDATE seoclassdf SET category = '40' WHERE clsname = ls_vseoclass-clsname. ENDIF. ENDMETHOD. METHOD deserialize_pre_ddic. DATA: ls_vseoclass TYPE vseoclass. ii_xml->read( EXPORTING iv_name = 'VSEOCLASS' CHANGING cg_data = ls_vseoclass ). set_abap_language_version( CHANGING cv_abap_language_version = ls_vseoclass-unicode ). IF ls_vseoclass-category = '40'. " In lower releases, creating exception classes raise a popup asking for package " To avoid this, we set the default package here set_default_package( iv_package ). ENDIF. mi_object_oriented_object_fct->create( EXPORTING iv_check = abap_false iv_package = iv_package CHANGING cg_properties = ls_vseoclass ). ENDMETHOD. METHOD deserialize_sotr. "OTR stands for Online Text Repository mi_object_oriented_object_fct->create_sotr( iv_object_name = ms_item-obj_name iv_package = iv_package ii_xml = ii_xml ). ENDMETHOD. METHOD deserialize_tpool. DATA: lv_clsname TYPE seoclsname, lt_tpool_ext TYPE zif_abapgit_definitions=>ty_tpool_tt, lt_tpool TYPE textpool_table. ii_xml->read( EXPORTING iv_name = 'TPOOL' CHANGING cg_data = lt_tpool_ext ). lt_tpool = read_tpool( lt_tpool_ext ). IF lines( lt_tpool ) = 0. RETURN. ENDIF. lv_clsname = ms_item-obj_name. mi_object_oriented_object_fct->insert_text_pool( iv_class_name = lv_clsname it_text_pool = lt_tpool iv_language = mv_language ). ENDMETHOD. METHOD deserialize_tpool_i18n. DATA: lv_clsname TYPE seoclsname, lt_tpool TYPE textpool_table, lt_i18n_tpool TYPE zif_abapgit_lang_definitions=>ty_i18n_tpools, ls_i18n_tpool TYPE zif_abapgit_lang_definitions=>ty_i18n_tpool. lv_clsname = ms_item-obj_name. ii_xml->read( EXPORTING iv_name = 'I18N_TPOOL' CHANGING cg_data = lt_i18n_tpool ). mo_i18n_params->trim_saplang_keyed_table( EXPORTING iv_lang_field_name = 'LANGUAGE' CHANGING ct_tab = lt_i18n_tpool ). LOOP AT lt_i18n_tpool INTO ls_i18n_tpool. lt_tpool = read_tpool( ls_i18n_tpool-textpool ). mi_object_oriented_object_fct->insert_text_pool( iv_class_name = lv_clsname it_text_pool = lt_tpool iv_language = ls_i18n_tpool-language iv_state = 'A' ). ENDLOOP. ENDMETHOD. METHOD interface_replacement. DATA lv_tabix TYPE sy-tabix. FIELD-SYMBOLS LIKE LINE OF ct_source. FIND REGEX '^\s*INTERFACES(:| )\s*' && iv_from_interface && '\s*.' IN TABLE ct_source MATCH LINE lv_tabix. IF sy-subrc = 0. READ TABLE ct_source ASSIGNING INDEX lv_tabix. ASSERT sy-subrc = 0. REPLACE FIRST OCCURRENCE OF iv_from_interface IN WITH iv_to_interface IGNORING CASE. REPLACE ALL OCCURRENCES OF iv_from_interface && '~descriptor' IN TABLE ct_source WITH iv_to_interface && '~descriptor' IGNORING CASE. REPLACE ALL OCCURRENCES OF iv_from_interface && '=>' IN TABLE ct_source WITH iv_to_interface && '=>' IGNORING CASE. REPLACE ALL OCCURRENCES OF iv_from_interface && '->' IN TABLE ct_source WITH iv_to_interface && '->' IGNORING CASE. ENDIF. ENDMETHOD. METHOD is_class_locked. DATA: lv_argument TYPE seqg3-garg. lv_argument = ms_item-obj_name. OVERLAY lv_argument WITH '=============================='. lv_argument = lv_argument && '*'. rv_is_class_locked = exists_a_lock_entry_for( iv_lock_object = 'ESEOCLASS' iv_argument = lv_argument ). ENDMETHOD. METHOD repo_apack_replacement. DATA lv_apack TYPE seoclsname. " Check if SAP-version of APACK manifest exists SELECT SINGLE clsname INTO lv_apack FROM seoclass WHERE clsname = zif_abapgit_apack_definitions=>c_apack_interface_sap. IF sy-subrc = 0. RETURN. ENDIF. " If not, replace with abapGit version interface_replacement( EXPORTING iv_from_interface = to_lower( zif_abapgit_apack_definitions=>c_apack_interface_sap ) iv_to_interface = to_lower( zif_abapgit_apack_definitions=>c_apack_interface_cust ) CHANGING ct_source = ct_source ). ENDMETHOD. METHOD serialize_attr. DATA: lt_attributes TYPE zif_abapgit_oo_object_fnc=>ty_obj_attribute_tt. lt_attributes = mi_object_oriented_object_fct->read_attributes( iv_clsname ). IF lines( lt_attributes ) = 0. RETURN. ENDIF. ii_xml->add( iv_name = 'ATTRIBUTES' ig_data = lt_attributes ). ENDMETHOD. METHOD serialize_descr. DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seocompotx_tt, lv_language TYPE spras, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. IF mo_i18n_params->ms_params-main_language_only = abap_true. lv_language = mv_language. ENDIF. lt_descriptions = mi_object_oriented_object_fct->read_descriptions( iv_object_name = iv_clsname iv_language = lv_language ). IF lines( lt_descriptions ) = 0. RETURN. ENDIF. " Remove technical languages lt_language_filter = mo_i18n_params->build_language_filter( ). DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. ii_xml->add( iv_name = 'DESCRIPTIONS' ig_data = lt_descriptions ). ENDMETHOD. METHOD serialize_descr_sub. DATA: lt_descriptions TYPE zif_abapgit_oo_object_fnc=>ty_seosubcotx_tt, lv_language TYPE spras, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. IF mo_i18n_params->ms_params-main_language_only = abap_true. lv_language = mv_language. ENDIF. lt_descriptions = mi_object_oriented_object_fct->read_descriptions_sub( iv_object_name = iv_clsname iv_language = lv_language ). IF lines( lt_descriptions ) = 0. RETURN. ENDIF. " Remove technical languages lt_language_filter = mo_i18n_params->build_language_filter( ). DELETE lt_descriptions WHERE NOT langu IN lt_language_filter AND langu <> mv_language. ii_xml->add( iv_name = 'DESCRIPTIONS_SUB' ig_data = lt_descriptions ). ENDMETHOD. METHOD serialize_docu. DATA: lt_lines TYPE tlinetab, lv_object TYPE dokhl-object, lv_langu TYPE sy-langu, lt_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_lines, ls_i18n_lines TYPE zif_abapgit_lang_definitions=>ty_i18n_line. lv_object = iv_clsname. lt_lines = mi_object_oriented_object_fct->read_documentation( iv_id = c_longtext_id-class iv_object_name = lv_object iv_language = mv_language ). IF lines( lt_lines ) > 0. ii_xml->add( iv_name = 'LINES' ig_data = lt_lines ). ENDIF. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. LOOP AT it_langu_additional INTO lv_langu. lt_lines = mi_object_oriented_object_fct->read_documentation( iv_id = c_longtext_id-class iv_object_name = lv_object iv_language = lv_langu ). IF lines( lt_lines ) > 0. CLEAR ls_i18n_lines. ls_i18n_lines-language = lv_langu. ls_i18n_lines-lines = lt_lines. INSERT ls_i18n_lines INTO TABLE lt_i18n_lines. ENDIF. ENDLOOP. IF lines( lt_i18n_lines ) > 0. ii_xml->add( iv_name = 'I18N_LINES' ig_data = lt_i18n_lines ). ENDIF. serialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-attributes iv_longtext_id = c_longtext_id-attributes ). serialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-methods iv_longtext_id = c_longtext_id-methods ). serialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-events iv_longtext_id = c_longtext_id-events ). serialize_longtexts( ii_xml = ii_xml iv_longtext_name = c_longtext_name-types iv_longtext_id = c_longtext_id-types ). ENDMETHOD. METHOD serialize_sotr. mi_object_oriented_object_fct->read_sotr( iv_object_name = ms_item-obj_name io_i18n_params = mo_i18n_params ii_xml = ii_xml ). ENDMETHOD. METHOD serialize_tpool. DATA lt_tpool TYPE textpool_table. lt_tpool = mi_object_oriented_object_fct->read_text_pool( iv_class_name = iv_clsname iv_language = mv_language ). ii_xml->add( iv_name = 'TPOOL' ig_data = add_tpool( lt_tpool ) ). rt_tpool = lt_tpool. ENDMETHOD. METHOD serialize_tpool_i18n. DATA: lt_tpool TYPE textpool_table, lv_index TYPE i, lv_langu TYPE sy-langu, lt_i18n_tpool TYPE zif_abapgit_lang_definitions=>ty_i18n_tpools, ls_i18n_tpool TYPE zif_abapgit_lang_definitions=>ty_i18n_tpool. FIELD-SYMBOLS LIKE LINE OF it_tpool_main. DATA lt_tpool_main LIKE SORTED TABLE OF WITH UNIQUE KEY id key. IF mo_i18n_params->ms_params-main_language_only = abap_true OR lines( it_tpool_main ) = 0. RETURN. ENDIF. " Copy single records to be able to catch duplicate key error LOOP AT it_tpool_main ASSIGNING . INSERT INTO TABLE lt_tpool_main. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Inconsistent textpool in { ms_item-obj_type } { ms_item-obj_name }| ). ENDIF. ENDLOOP. LOOP AT it_langu_additional INTO lv_langu. lt_tpool = mi_object_oriented_object_fct->read_text_pool( iv_class_name = iv_clsname iv_language = lv_langu ). LOOP AT lt_tpool ASSIGNING . lv_index = sy-tabix. READ TABLE lt_tpool_main WITH KEY id = -id key = -key TRANSPORTING NO FIELDS. IF sy-subrc <> 0. DELETE lt_tpool INDEX lv_index. ENDIF. ENDLOOP. IF lines( lt_tpool ) > 0. CLEAR ls_i18n_tpool. ls_i18n_tpool-language = lv_langu. ls_i18n_tpool-textpool = add_tpool( lt_tpool ). INSERT ls_i18n_tpool INTO TABLE lt_i18n_tpool. ENDIF. ENDLOOP. IF lines( lt_i18n_tpool ) > 0. ii_xml->add( iv_name = 'I18N_TPOOL' ig_data = lt_i18n_tpool ). ENDIF. ENDMETHOD. METHOD serialize_xml. DATA: ls_vseoclass TYPE vseoclass, lt_tpool TYPE textpool_table, ls_clskey TYPE seoclskey, lt_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. ls_clskey-clsname = ms_item-obj_name. "If class was deserialized with a previous version of abapGit and current language was different "from main language at this time, this call would return SY-LANGU as main language. To fix "these objects, set SY-LANGU to main language temporarily. zcl_abapgit_language=>set_current_language( mv_language ). TRY. ls_vseoclass = mi_object_oriented_object_fct->get_class_properties( ls_clskey ). clear_abap_language_version( CHANGING cv_abap_language_version = ls_vseoclass-unicode ). CLEANUP. zcl_abapgit_language=>restore_login_language( ). ENDTRY. zcl_abapgit_language=>restore_login_language( ). IF mv_skip_testclass = abap_true. CLEAR ls_vseoclass-with_unit_tests. ENDIF. " Table d010tinf stores info. on languages in which program is maintained " Select all active translations of program texts " Skip main language - it was already serialized lt_language_filter = mo_i18n_params->build_language_filter( ). SELECT DISTINCT language INTO TABLE lt_langu_additional FROM d010tinf WHERE r3state = 'A' AND prog = mv_classpool_name AND language IN lt_language_filter AND language <> mv_language ORDER BY language. ii_xml->add( iv_name = 'VSEOCLASS' ig_data = ls_vseoclass ). lt_tpool = serialize_tpool( ii_xml = ii_xml iv_clsname = ls_clskey-clsname ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. serialize_tpool_i18n( ii_xml = ii_xml it_langu_additional = lt_langu_additional it_tpool_main = lt_tpool iv_clsname = ls_clskey-clsname ). ENDIF. IF ls_vseoclass-category = seoc_category_exception. serialize_sotr( ii_xml ). ENDIF. SELECT DISTINCT langu INTO TABLE lt_langu_additional FROM dokhl WHERE id = 'CL' AND object = ls_clskey-clsname AND langu IN lt_language_filter AND langu <> mv_language ORDER BY langu. serialize_docu( ii_xml = ii_xml iv_clsname = ls_clskey-clsname it_langu_additional = lt_langu_additional ). serialize_descr( ii_xml = ii_xml iv_clsname = ls_clskey-clsname ). serialize_descr_sub( ii_xml = ii_xml iv_clsname = ls_clskey-clsname ). serialize_attr( ii_xml = ii_xml iv_clsname = ls_clskey-clsname ). ENDMETHOD. METHOD source_apack_replacement. DATA lv_clsname TYPE seoclsname. " Check if abapGit version of APACK manifest is used SELECT SINGLE clsname INTO lv_clsname FROM seometarel WHERE clsname = ms_item-obj_name AND refclsname = zif_abapgit_apack_definitions=>c_apack_interface_cust AND version = '1'. IF sy-subrc <> 0. RETURN. ENDIF. " If yes, replace with SAP-version interface_replacement( EXPORTING iv_from_interface = to_lower( zif_abapgit_apack_definitions=>c_apack_interface_cust ) iv_to_interface = to_lower( zif_abapgit_apack_definitions=>c_apack_interface_sap ) CHANGING ct_source = ct_source ). ENDMETHOD. METHOD zif_abapgit_object~changed_by. TYPES: BEGIN OF ty_reposrc, unam TYPE reposrc-unam, udat TYPE reposrc-udat, utime TYPE reposrc-utime, END OF ty_reposrc. DATA: lt_reposrc TYPE STANDARD TABLE OF ty_reposrc, ls_reposrc LIKE LINE OF lt_reposrc, lv_include TYPE syrepid, lt_includes TYPE STANDARD TABLE OF syrepid. CASE iv_extra. WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_def. lv_include = cl_oo_classname_service=>get_ccdef_name( |{ ms_item-obj_name }| ). INSERT lv_include INTO TABLE lt_includes. WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_imp. lv_include = cl_oo_classname_service=>get_ccimp_name( |{ ms_item-obj_name }| ). INSERT lv_include INTO TABLE lt_includes. WHEN zif_abapgit_oo_object_fnc=>c_parts-macros. lv_include = cl_oo_classname_service=>get_ccmac_name( |{ ms_item-obj_name }| ). INSERT lv_include INTO TABLE lt_includes. WHEN zif_abapgit_oo_object_fnc=>c_parts-testclasses. lv_include = cl_oo_classname_service=>get_ccau_name( |{ ms_item-obj_name }| ). INSERT lv_include INTO TABLE lt_includes. WHEN OTHERS. lt_includes = mi_object_oriented_object_fct->get_includes( ms_item-obj_name ). ENDCASE. ASSERT lines( lt_includes ) > 0. SELECT unam udat utime FROM reposrc INTO TABLE lt_reposrc FOR ALL ENTRIES IN lt_includes WHERE progname = lt_includes-table_line AND r3state = 'A'. IF sy-subrc <> 0. rv_user = c_user_unknown. ELSE. SORT lt_reposrc BY udat DESCENDING utime DESCENDING. READ TABLE lt_reposrc INDEX 1 INTO ls_reposrc. ASSERT sy-subrc = 0. rv_user = ls_reposrc-unam. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: ls_clskey TYPE seoclskey. ls_clskey-clsname = ms_item-obj_name. corr_insert( iv_package ). mi_object_oriented_object_fct->delete( ls_clskey ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. IF iv_step = zif_abapgit_object=>gc_step_id-abap. deserialize_abap( ii_xml = io_xml iv_package = iv_package ). deserialize_tpool( io_xml ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. deserialize_tpool_i18n( io_xml ). ENDIF. deserialize_sotr( ii_xml = io_xml iv_package = iv_package ). deserialize_docu( io_xml ). ELSEIF iv_step = zif_abapgit_object=>gc_step_id-early. " If class does not exist, create it " so DDIC that depends on it does not fail activation IF zif_abapgit_object~exists( ) = abap_false. deserialize_pre_ddic( ii_xml = io_xml iv_package = iv_package ). ELSE. corr_insert( iv_package ). ENDIF. ELSEIF iv_step = zif_abapgit_object=>gc_step_id-late. deserialize_exceptions( io_xml ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA ls_class_key TYPE seoclskey. ls_class_key-clsname = ms_item-obj_name. rv_bool = mi_object_oriented_object_fct->exists( ls_class_key ). " Skip classes generated by DDLS (SADL) IF rv_bool = abap_true AND mi_object_oriented_object_fct->read_superclass( ls_class_key-clsname ) = 'CL_SADL_GTK_EXPOSURE_MPC'. rv_bool = abap_false. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-early TO rt_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. IF is_class_locked( ) = abap_true OR is_text_locked( mv_classpool_name ) = abap_true. rv_is_locked = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA ls_item TYPE zif_abapgit_definitions=>ty_item. ls_item-obj_type = 'PROG'. CASE iv_extra. WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_def. ls_item-obj_name = cl_oo_classname_service=>get_ccdef_name( |{ ms_item-obj_name }| ). WHEN zif_abapgit_oo_object_fnc=>c_parts-locals_imp. ls_item-obj_name = cl_oo_classname_service=>get_ccimp_name( |{ ms_item-obj_name }| ). WHEN zif_abapgit_oo_object_fnc=>c_parts-macros. ls_item-obj_name = cl_oo_classname_service=>get_ccmac_name( |{ ms_item-obj_name }| ). WHEN zif_abapgit_oo_object_fnc=>c_parts-testclasses. ls_item-obj_name = cl_oo_classname_service=>get_ccau_name( |{ ms_item-obj_name }| ). ENDCASE. IF ls_item-obj_name IS NOT INITIAL. rv_exit = zcl_abapgit_objects_factory=>get_gui_jumper( )->jump( ls_item ). ENDIF. " Otherwise covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lt_source TYPE seop_source_string, ls_class_key TYPE seoclskey. ls_class_key-clsname = ms_item-obj_name. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. CALL FUNCTION 'SEO_BUFFER_REFRESH' EXPORTING version = seoc_version_active force = abap_true. CALL FUNCTION 'SEO_BUFFER_REFRESH' EXPORTING version = seoc_version_inactive force = abap_true. lt_source = mi_object_oriented_object_fct->serialize_abap( ls_class_key ). source_apack_replacement( CHANGING ct_source = lt_source ). mo_files->add_abap( lt_source ). lt_source = mi_object_oriented_object_fct->serialize_abap( is_class_key = ls_class_key iv_type = seop_ext_class_locals_def ). IF lines( lt_source ) > 0. mo_files->add_abap( iv_extra = zif_abapgit_oo_object_fnc=>c_parts-locals_def it_abap = lt_source ). ENDIF. lt_source = mi_object_oriented_object_fct->serialize_abap( is_class_key = ls_class_key iv_type = seop_ext_class_locals_imp ). IF lines( lt_source ) > 0. mo_files->add_abap( iv_extra = zif_abapgit_oo_object_fnc=>c_parts-locals_imp it_abap = lt_source ). ENDIF. lt_source = mi_object_oriented_object_fct->serialize_abap( is_class_key = ls_class_key iv_type = seop_ext_class_testclasses ). mv_skip_testclass = mi_object_oriented_object_fct->get_skip_test_classes( ). IF lines( lt_source ) > 0 AND mv_skip_testclass = abap_false. mo_files->add_abap( iv_extra = zif_abapgit_oo_object_fnc=>c_parts-testclasses it_abap = lt_source ). ENDIF. lt_source = mi_object_oriented_object_fct->serialize_abap( is_class_key = ls_class_key iv_type = seop_ext_class_macros ). IF lines( lt_source ) > 0. mo_files->add_abap( iv_extra = zif_abapgit_oo_object_fnc=>c_parts-macros it_abap = lt_source ). ENDIF. serialize_xml( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_chdo IMPLEMENTATION. METHOD after_import. DATA: lt_cts_object_entry TYPE STANDARD TABLE OF e071 WITH DEFAULT KEY, ls_cts_object_entry LIKE LINE OF lt_cts_object_entry, lt_errormsg TYPE STANDARD TABLE OF sprot_u WITH DEFAULT KEY. ls_cts_object_entry-pgmid = 'R3TR'. ls_cts_object_entry-object = ms_item-obj_type. ls_cts_object_entry-obj_name = ms_item-obj_name. INSERT ls_cts_object_entry INTO TABLE lt_cts_object_entry. CALL FUNCTION 'AFTER_IMP_CHDO' EXPORTING iv_tarclient = sy-mandt iv_is_upgrade = abap_false TABLES tt_e071 = lt_cts_object_entry tt_errormsg = lt_errormsg. LOOP AT lt_errormsg TRANSPORTING NO FIELDS WHERE severity = 'E' OR severity = 'A'. EXIT. ENDLOOP. IF sy-subrc = 0. zcx_abapgit_exception=>raise( 'Error from AFTER_IMP_CHDO' ). ENDIF. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_object = is_item-obj_name. ENDMETHOD. METHOD delete_tadir_cdnames. DATA: lv_obj_name TYPE sobj_name. IF is_cdnames-repnamec IS NOT INITIAL. lv_obj_name = is_cdnames-repnamec. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_tadir_pgmid = 'R3TR' wi_tadir_object = 'PROG' wi_tadir_obj_name = lv_obj_name wi_test_modus = abap_false EXCEPTIONS tadir_entry_not_existing = 1 OTHERS = 2. IF sy-subrc > 1. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. IF is_cdnames-repnamet IS NOT INITIAL. lv_obj_name = is_cdnames-repnamet. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_tadir_pgmid = 'R3TR' wi_tadir_object = 'PROG' wi_tadir_obj_name = lv_obj_name wi_test_modus = abap_false EXCEPTIONS tadir_entry_not_existing = 1 OTHERS = 2. IF sy-subrc > 1. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. IF is_cdnames-repnamefix IS NOT INITIAL. lv_obj_name = is_cdnames-repnamefix. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_tadir_pgmid = 'R3TR' wi_tadir_object = 'PROG' wi_tadir_obj_name = lv_obj_name wi_test_modus = abap_false EXCEPTIONS tadir_entry_not_existing = 1 OTHERS = 2. IF sy-subrc > 1. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. IF is_cdnames-repnamevar IS NOT INITIAL. lv_obj_name = is_cdnames-repnamevar. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_tadir_pgmid = 'R3TR' wi_tadir_object = 'PROG' wi_tadir_obj_name = lv_obj_name wi_test_modus = abap_false EXCEPTIONS tadir_entry_not_existing = 1 OTHERS = 2. IF sy-subrc > 1. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. IF is_cdnames-fgrp IS NOT INITIAL. lv_obj_name = is_cdnames-fgrp. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_tadir_pgmid = 'R3TR' wi_tadir_object = 'FUGR' wi_tadir_obj_name = lv_obj_name wi_test_modus = abap_false EXCEPTIONS tadir_entry_not_existing = 1 OTHERS = 2. IF sy-subrc > 1. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. ENDMETHOD. METHOD delete_tadir_tabl. DATA: lv_obj_name TYPE sobj_name. IF is_tcdrs-tabname IS NOT INITIAL. lv_obj_name = is_tcdrs-tabname. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_tadir_pgmid = 'R3TR' wi_tadir_object = 'TABL' wi_tadir_obj_name = lv_obj_name wi_test_modus = abap_false EXCEPTIONS tadir_entry_not_existing = 1 OTHERS = 2. IF sy-subrc > 1. zcx_abapgit_exception=>raise( |Error from TR_TADIR_INTERFACE (subrc={ sy-subrc } ).| ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE updname INTO rv_user FROM tcdrp WHERE object = mv_object. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lt_cdnames TYPE STANDARD TABLE OF cdnames, ls_cdnames TYPE cdnames, lt_tcdrs TYPE STANDARD TABLE OF tcdrs, ls_tcdrs TYPE tcdrs, lv_msg TYPE symsgv. CALL FUNCTION 'CDNAMES_GET' EXPORTING iv_object = mv_object TABLES it_tcdrs = lt_tcdrs it_names = lt_cdnames EXCEPTIONS object_space = 1 object_not_found = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'CHDO_DELETE' EXPORTING iv_object = mv_object iv_with_tadir = abap_true EXCEPTIONS object_is_space = 1 object_not_found = 2 other_error = 3 OTHERS = 4. IF sy-subrc <> 0. lv_msg = mv_object. zcx_abapgit_exception=>raise_t100( iv_msgid = 'CD' iv_msgno = '869' iv_msgv1 = lv_msg ). ENDIF. LOOP AT lt_cdnames INTO ls_cdnames. delete_tadir_cdnames( ls_cdnames ). ENDLOOP. LOOP AT lt_tcdrs INTO ls_tcdrs. delete_tadir_tabl( ls_tcdrs ). ENDLOOP. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_change_object TYPE ty_change_document. FIELD-SYMBOLS: LIKE LINE OF ls_change_object-reports_generated. io_xml->read( EXPORTING iv_name = 'CHDO' CHANGING cg_data = ls_change_object ). DELETE FROM tcdobs WHERE object = mv_object. DELETE FROM tcdobts WHERE object = mv_object. DELETE FROM tcdrps WHERE object = mv_object. LOOP AT ls_change_object-reports_generated ASSIGNING . -devclass = iv_package. ENDLOOP. INSERT tcdobs FROM TABLE ls_change_object-objects. INSERT tcdobts FROM TABLE ls_change_object-objects_text. INSERT tcdrps FROM TABLE ls_change_object-reports_generated. tadir_insert( iv_package ). after_import( ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. SELECT COUNT(*) FROM tcdrp WHERE object = mv_object. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA: lt_bdcdata TYPE STANDARD TABLE OF bdcdata, ls_bdcdata LIKE LINE OF lt_bdcdata. CLEAR: ls_bdcdata. ls_bdcdata-program = 'SAPMSCDO_NEW'. ls_bdcdata-dynpro = '0100'. ls_bdcdata-dynbegin = abap_true. APPEND ls_bdcdata TO lt_bdcdata. CLEAR: ls_bdcdata. ls_bdcdata-fnam = 'TCDOB-OBJECT'. ls_bdcdata-fval = mv_object. APPEND ls_bdcdata TO lt_bdcdata. CLEAR: ls_bdcdata. ls_bdcdata-fnam = 'BDC_OKCODE'. ls_bdcdata-fval = '=DISP'. APPEND ls_bdcdata TO lt_bdcdata. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SCDO' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_change_object TYPE ty_change_document, lt_tcdrp TYPE STANDARD TABLE OF tcdrp, lt_tcdob TYPE STANDARD TABLE OF tcdob, lt_tcdobt TYPE STANDARD TABLE OF tcdobt, BEGIN OF ls_nulldatetime, " hack ro reset fields when they exist without syntax errors when they don't udate TYPE sy-datum, utime TYPE sy-uzeit, END OF ls_nulldatetime. FIELD-SYMBOLS: LIKE LINE OF ls_change_object-reports_generated, LIKE LINE OF ls_change_object-objects, LIKE LINE OF ls_change_object-objects_text. CALL FUNCTION 'CDNAMES_GET' EXPORTING iv_object = mv_object TABLES it_tcdrp = lt_tcdrp it_tcdob = lt_tcdob it_tcdobt = lt_tcdobt EXCEPTIONS object_space = 1 object_not_found = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ls_change_object-reports_generated = lt_tcdrp. ls_change_object-objects = lt_tcdob. ls_change_object-objects_text = lt_tcdobt. " At import, when CHDO is generated date & time change, so always detects changes for this fields LOOP AT ls_change_object-reports_generated ASSIGNING . CLEAR: -datum, -uzeit, -author, -updname, -devclass. ENDLOOP. LOOP AT ls_change_object-objects ASSIGNING . MOVE-CORRESPONDING ls_nulldatetime TO . " reset date and time ENDLOOP. LOOP AT ls_change_object-objects_text ASSIGNING . MOVE-CORRESPONDING ls_nulldatetime TO . " reset date and time ENDLOOP. io_xml->add( iv_name = 'CHDO' ig_data = ls_change_object ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_CHAR IMPLEMENTATION. METHOD instantiate_char_and_lock. DATA: lv_new TYPE abap_bool, lv_name TYPE cls_attribute_name. SELECT SINGLE name FROM cls_attribute INTO lv_name WHERE name = ms_item-obj_name. lv_new = boolc( sy-subrc <> 0 ). lv_name = ms_item-obj_name. TRY. CREATE OBJECT ro_char EXPORTING im_name = lv_name im_type_group = iv_type_group im_new = lv_new im_activation_state = iv_activation_state. CATCH cx_pak_invalid_data cx_pak_not_authorized cx_pak_invalid_state cx_pak_wb_object_locked. zcx_abapgit_exception=>raise( 'Error while instantiating CL_CLS_ATTRIBUTE' ). ENDTRY. IF lv_new = abap_false. TRY. ro_char->if_pak_wb_object~lock_and_refresh( ). CATCH cx_pak_invalid_data cx_pak_not_authorized cx_pak_invalid_state cx_pak_wb_object_locked. zcx_abapgit_exception=>raise( |Could not acquire lock, CHAR { lv_name }| ). ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE changed_by FROM cls_attribute INTO rv_user WHERE name = ms_item-obj_name AND activation_state = 'A'. IF rv_user IS INITIAL. SELECT SINGLE created_by FROM cls_attribute INTO rv_user WHERE name = ms_item-obj_name AND activation_state = 'A'. ENDIF. IF rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_char TYPE REF TO cl_cls_attribute, lv_type_group TYPE cls_attribute-type_group, lx_pak_error TYPE REF TO cx_root, lv_text TYPE string. SELECT SINGLE type_group FROM cls_attribute INTO lv_type_group WHERE name = ms_item-obj_name AND activation_state = 'A'. lo_char = instantiate_char_and_lock( iv_type_group = lv_type_group iv_activation_state = cl_pak_wb_domains=>co_activation_state-active ). TRY. lo_char->if_pak_wb_object~delete( ). lo_char->if_pak_wb_object~save( ). lo_char->if_pak_wb_object_internal~unlock( ). CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. lo_char->if_pak_wb_object_internal~unlock( ). lv_text = lx_pak_error->get_text( ). zcx_abapgit_exception=>raise( lv_text ). CLEANUP. lo_char->if_pak_wb_object_internal~unlock( ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_char TYPE ty_char, ls_description LIKE LINE OF ls_char-cls_attributet, lo_char TYPE REF TO cl_cls_attribute, lx_pak_error TYPE REF TO cx_root, lv_text TYPE string. FIELD-SYMBOLS: LIKE LINE OF ls_char-cls_attr_value, TYPE any, LIKE LINE OF ls_char-cls_attr_valuet. io_xml->read( EXPORTING iv_name = 'CHAR' CHANGING cg_data = ls_char ). tadir_insert( iv_package ). lo_char = instantiate_char_and_lock( iv_type_group = ls_char-cls_attribute-type_group iv_activation_state = cl_pak_wb_domains=>co_activation_state-inactive ). TRY. lo_char->if_cls_attribute~set_kind( ls_char-cls_attribute-kind ). lo_char->if_cls_attribute~set_single_valued( ls_char-cls_attribute-is_single_valued ). lo_char->if_cls_attribute~set_aspect( im_aspect_for = ls_char-cls_attribute-is_aspect_for im_aspect_value = ls_char-cls_attribute-aspect_value ). lo_char->if_cls_attribute~set_default_flag( ls_char-cls_attribute-default_flag ). lo_char->if_cls_attribute~set_default_value( ls_char-cls_attribute-default_value ). lo_char->if_cls_attribute~set_sub_object_treatment( ls_char-cls_attribute-sub_obj_treatm ). lo_char->if_cls_attribute~set_automatic_changes_allowed( ls_char-cls_attribute-automatic_change ). lo_char->if_cls_attribute~set_manual_changes_allowed( ls_char-cls_attribute-manu_chag_allow ). lo_char->if_cls_attribute~set_implicit_changes_allowed( ls_char-cls_attribute-implicit_change ). lo_char->if_cls_attribute~set_expl_values_dominate_links( ls_char-cls_attribute-weak_links ). lo_char->if_cls_attribute~set_assignment_package_rule( ls_char-cls_attribute-assignment_devc ). * Method SET_HIDE_ICON does not exist in some releases, not present in 751 ASSIGN COMPONENT 'HIDE_ICONS' OF STRUCTURE ls_char-cls_attribute TO . IF sy-subrc = 0. CALL METHOD lo_char->('IF_CLS_ATTRIBUTE~SET_HIDE_ICON') EXPORTING im_hide_icon = . ENDIF. lo_char->if_cls_attribute~set_hide_remark( ls_char-cls_attribute-hide_remark ). lo_char->if_cls_attribute~set_visible_in_customer_system( ls_char-cls_attribute-visible_for_cust ). lo_char->if_cls_attribute~set_value_table( ls_char-cls_attribute-value_table ). lo_char->if_cls_attribute~set_vtable_field( ls_char-cls_attribute-vtable_field ). lo_char->if_cls_attribute~set_vtable_icon_f( ls_char-cls_attribute-vtable_icon_f ). lo_char->if_cls_attribute~set_vtext_langu_f( ls_char-cls_attribute-vtext_langu_f ). lo_char->if_cls_attribute~set_vtext_table( ls_char-cls_attribute-vtext_table ). lo_char->if_cls_attribute~set_vtext_text_f( ls_char-cls_attribute-vtext_text_f ). lo_char->if_cls_attribute~set_vtext_value_f( ls_char-cls_attribute-vtext_value_f ). lo_char->if_cls_attribute~set_existing_objects_only( ls_char-cls_attribute-existing_objects ). lo_char->if_cls_attribute~set_objs_of_typegr( ls_char-cls_attribute-objs_of_typegr ). lo_char->if_cls_attribute~set_obj_values_have_subtypes( ls_char-cls_attribute-objs_w_subtype ). lo_char->if_cls_attribute~set_arbtry_val_type( ls_char-cls_attribute-arbtry_val_type ). READ TABLE ls_char-cls_attributet INTO ls_description WITH KEY langu = mv_language. IF sy-subrc <> 0. READ TABLE ls_char-cls_attributet INTO ls_description INDEX 1. ENDIF. lo_char->if_cls_attribute~set_description( ls_description-text ). LOOP AT ls_char-cls_attr_value ASSIGNING . -activation_state = 'I'. ENDLOOP. LOOP AT ls_char-cls_attr_valuet ASSIGNING . -activation_state = 'I'. ENDLOOP. lo_char->if_cls_attribute~set_values( im_values = ls_char-cls_attr_value im_values_t = ls_char-cls_attr_valuet ). set_default_package( iv_package ). lo_char->if_pak_wb_object~save( ). lo_char->if_pak_wb_object~activate( ). lo_char->if_pak_wb_object_internal~unlock( ). CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized INTO lx_pak_error. lo_char->if_pak_wb_object_internal~unlock( ). lv_text = lx_pak_error->get_text( ). zcx_abapgit_exception=>raise( lv_text ). CLEANUP. lo_char->if_pak_wb_object_internal~unlock( ). ENDTRY. deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_char ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = cl_cls_attribute=>exists_object_attribute( ms_item-obj_name ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ECLS_ATTRIBUTE' iv_argument = |{ ms_item-obj_name }*| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_char TYPE ty_char. CONSTANTS: lc_active TYPE c LENGTH 1 VALUE 'A'. SELECT SINGLE * FROM cls_attribute INTO ls_char-cls_attribute WHERE name = ms_item-obj_name AND activation_state = lc_active. * todo, ASSIGNMENT_DEVC? CLEAR: ls_char-cls_attribute-created_by, ls_char-cls_attribute-created_on, ls_char-cls_attribute-changed_by, ls_char-cls_attribute-changed_on. SELECT * FROM cls_attributet INTO TABLE ls_char-cls_attributet WHERE name = ms_item-obj_name AND activation_state = lc_active ORDER BY PRIMARY KEY. IF mo_i18n_params->ms_params-main_language_only = abap_true. DELETE ls_char-cls_attributet WHERE langu <> mv_language. ENDIF. SELECT * FROM cls_attr_value INTO TABLE ls_char-cls_attr_value WHERE name = ms_item-obj_name AND activation_state = lc_active ORDER BY PRIMARY KEY. SELECT * FROM cls_attr_valuet INTO TABLE ls_char-cls_attr_valuet WHERE name = ms_item-obj_name AND activation_state = lc_active ORDER BY PRIMARY KEY. IF mo_i18n_params->ms_params-main_language_only = abap_true. DELETE ls_char-cls_attr_valuet WHERE langu <> mv_language. ENDIF. io_xml->add( iv_name = 'CHAR' ig_data = ls_char ). serialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_char ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_bdef IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_metadata TO . ASSERT sy-subrc = 0. CLEAR: . ENDMETHOD. METHOD clear_fields. FIELD-SYMBOLS: TYPE ANY TABLE. FIELD-SYMBOLS: TYPE data. FIELD-SYMBOLS TYPE any. clear_field( EXPORTING iv_fieldname = 'VERSION' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'CREATED_AT' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'CREATED_BY' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'CHANGED_AT' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'CHANGED_BY' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'RESPONSIBLE' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'PACKAGE_REF' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'CONTAINER_REF' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MASTER_SYSTEM' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MAIN_OBJECT-CHANGED_AT' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MAIN_OBJECT-CHANGED_BY' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MAIN_OBJECT-CREATED_AT' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MAIN_OBJECT-CREATED_BY' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MAIN_OBJECT-RESPONSIBLE' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MAIN_OBJECT-PACKAGE_REF' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MAIN_OBJECT-CONTAINER_REF' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'MAIN_OBJECT-MASTER_SYSTEM' CHANGING cs_metadata = cs_metadata ). clear_field( EXPORTING iv_fieldname = 'SYNTAX_CONFIGURATION' CHANGING cs_metadata = cs_metadata ). ASSIGN COMPONENT 'LINKS' OF STRUCTURE cs_metadata TO . ASSERT sy-subrc = 0. LOOP AT ASSIGNING . ASSIGN COMPONENT 'COMMON_ATTRIBUTES' OF STRUCTURE TO . ASSERT sy-subrc = 0. CLEAR: . ENDLOOP. ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_behaviour_definition_key = ms_item-obj_name. TRY. CREATE DATA mr_behaviour_definition TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). CREATE OBJECT mi_persistence TYPE ('CL_BDEF_OBJECT_PERSIST'). CATCH cx_sy_create_error. zcx_abapgit_exception=>raise( |BDEF not supported by your NW release| ). ENDTRY. ENDMETHOD. METHOD get_object_data. DATA: lr_metadata TYPE REF TO data, lr_data TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any, TYPE any. CREATE DATA lr_data TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). ASSIGN lr_data->* TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA' OF STRUCTURE TO . ASSERT sy-subrc = 0. CREATE DATA lr_metadata TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA-METADATA'). ASSIGN lr_metadata->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'BDEF' CHANGING cg_data = ). = . ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. = mo_files->read_string( 'asbdef' ). CREATE OBJECT ro_object_data TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). ro_object_data->set_data( p_data = ). ENDMETHOD. METHOD get_wb_object_operator. DATA: ls_object_type TYPE wbobjtype, lx_error TYPE REF TO cx_root. IF mi_wb_object_operator IS BOUND. ri_wb_object_operator = mi_wb_object_operator. ENDIF. ls_object_type-objtype_tr = 'BDEF'. ls_object_type-subtype_wb = 'BDO'. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') EXPORTING object_type = ls_object_type object_key = mv_behaviour_definition_key RECEIVING result = mi_wb_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ri_wb_object_operator = mi_wb_object_operator. ENDMETHOD. METHOD merge_object_data. DATA: lo_object_data TYPE REF TO object, lo_object_data_old TYPE REF TO if_wb_object_data_model, lr_new TYPE REF TO data, lr_old TYPE REF TO data, lo_wb_object_operator TYPE REF TO object. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any, TYPE any. CREATE OBJECT lo_object_data TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). lo_object_data = io_object_data. CREATE DATA lr_new TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). ASSIGN lr_new->* TO . ASSERT sy-subrc = 0. CREATE DATA lr_old TYPE ('CL_BLUE_SOURCE_OBJECT_DATA=>TY_OBJECT_DATA'). ASSIGN lr_old->* TO . ASSERT sy-subrc = 0. CALL METHOD lo_object_data->('IF_WB_OBJECT_DATA_MODEL~GET_DATA') EXPORTING p_metadata_only = abap_false p_data_selection = 'AL' IMPORTING p_data = . lo_wb_object_operator = get_wb_object_operator( ). CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data IMPORTING eo_object_data = lo_object_data_old. CALL METHOD lo_object_data_old->('GET_DATA') EXPORTING p_metadata_only = abap_false p_data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data IMPORTING p_data = . ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE TO . = . ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . = . CREATE OBJECT ro_object_data_merged TYPE ('CL_BLUE_SOURCE_OBJECT_DATA'). CALL METHOD ro_object_data_merged->('SET_DATA') EXPORTING p_data = . ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, li_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = li_object_data_model. rv_user = li_object_data_model->get_changed_by( ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lx_error TYPE REF TO cx_root, li_wb_object_operator TYPE REF TO object. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') EXPORTING transport_request = iv_transport. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lo_object_data TYPE REF TO if_wb_object_data_model, lo_object_data_merged TYPE REF TO if_wb_object_data_model, lo_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root, lr_wbobjtype TYPE REF TO data, lr_category TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any. TRY. lo_object_data = get_object_data( io_xml ). CREATE DATA lr_wbobjtype TYPE ('WBOBJTYPE'). ASSIGN lr_wbobjtype->* TO . ASSIGN COMPONENT 'OBJTYPE_TR' OF STRUCTURE TO . = 'BDEF'. ASSIGN COMPONENT 'SUBTYPE_WB' OF STRUCTURE TO . = 'BDO'. CREATE DATA lr_category TYPE ('WBADT_RESOURCE_CATEGORY'). ASSIGN lr_category->* TO . CALL METHOD ('CL_BLUE_WB_UTILITY')=>('GET_RESOURCE_CATEGORY') EXPORTING is_object_type = RECEIVING result = . lo_wb_object_operator = get_wb_object_operator( ). tadir_insert( iv_package ). IF zif_abapgit_object~exists( ) = abap_false. CASE . WHEN '1'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = lo_object_data data_selection = 'AL' " if_wb_object_data_selection_co=>c_all_data version = 'I' package = iv_package transport_request = iv_transport. WHEN '2'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_compound_s. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = lo_object_data data_selection = 'P' " if_wb_object_data_selection_co=>c_properties version = 'I' package = iv_package transport_request = iv_transport. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_object_data data_selection = 'D' "if_wb_object_data_selection_co=>c_data_content version = 'I' transport_request = iv_transport. WHEN OTHERS. ENDCASE. ELSE. lo_object_data_merged = merge_object_data( lo_object_data ). CASE . WHEN '1'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_atomic. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_object_data_merged data_selection = 'AL' "if_wb_object_data_selection_co=>c_all_data version = 'I' transport_request = iv_transport. WHEN '2'. "if_wb_adt_plugin_resource_co=>co_sfs_res_category_compound_s. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_object_data_merged data_selection = 'P' "if_wb_object_data_selection_co=>c_properties version = 'I' transport_request = iv_transport. CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = lo_object_data_merged data_selection = 'D' "if_wb_object_data_selection_co=>c_data_content version = 'I' transport_request = iv_transport. WHEN OTHERS. ENDCASE. ENDIF. corr_insert( iv_package ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. zcl_abapgit_objects_activation=>add_item( ms_item ). ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. mi_persistence->get( p_object_key = mv_behaviour_definition_key p_version = 'A' p_existence_check_only = abap_true ). rv_bool = abap_true. CATCH cx_swb_exception. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDIC' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, li_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root, lv_source TYPE string. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE string. ASSIGN mr_behaviour_definition->* TO . ASSERT sy-subrc = 0. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING version = 'A' IMPORTING data = eo_object_data = li_object_data_model. ASSIGN COMPONENT 'METADATA' OF STRUCTURE TO . ASSERT sy-subrc = 0. clear_fields( CHANGING cs_metadata = ). ASSIGN COMPONENT 'CONTENT-SOURCE' OF STRUCTURE TO . ASSERT sy-subrc = 0. lv_source = . CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. io_xml->add( iv_name = 'BDEF' ig_data = ). mo_files->add_string( iv_ext = 'asbdef' iv_string = lv_source ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_avas IMPLEMENTATION. METHOD insert_assignments. DATA: lt_assignment TYPE STANDARD TABLE OF cls_assignment, ls_assignment LIKE LINE OF lt_assignment, ls_value LIKE LINE OF is_avas-values. LOOP AT is_avas-values INTO ls_value. CLEAR ls_assignment. ls_assignment-guid = is_avas-header-guid. ls_assignment-value = ls_value-value. ls_assignment-trobjtype = is_avas-header-object-trobjtype. ls_assignment-sobj_name = is_avas-header-object-sobj_name. ls_assignment-object_type = is_avas-header-object-object_type. ls_assignment-sub_key = is_avas-header-object-sub_key. ls_assignment-attribute = is_avas-header-attribute. ls_assignment-set_by = sy-uname. ls_assignment-changed_on = sy-datum. ls_assignment-remark = ls_value-remark. APPEND ls_assignment TO lt_assignment. ENDLOOP. DELETE FROM cls_assignment WHERE guid = is_avas-header-guid. INSERT cls_assignment FROM TABLE lt_assignment. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error inserting into CLS_ASSIGNMENT| ). ENDIF. ENDMETHOD. METHOD instantiate. DATA: lv_id TYPE guid_32, lx_err TYPE REF TO cx_root. lv_id = ms_item-obj_name. TRY. CREATE OBJECT ro_avas EXPORTING im_assignment_id = lv_id. CATCH cx_pak_wb_object_locked INTO lx_err. zcx_abapgit_exception=>raise( |AVAS { lv_id }: locked: { lx_err->get_longtext( ) }| ). CATCH cx_pak_not_authorized INTO lx_err. zcx_abapgit_exception=>raise( |AVAS { lv_id }: not authorized: { lx_err->get_longtext( ) }| ). CATCH cx_pak_invalid_state INTO lx_err. zcx_abapgit_exception=>raise( |AVAS { lv_id }: invalid state: { lx_err->get_longtext( ) }| ). CATCH cx_pak_invalid_data INTO lx_err. zcx_abapgit_exception=>raise( |AVAS { lv_id }: invalid data: { lx_err->get_longtext( ) }| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lo_avas TYPE REF TO cl_cls_attr_value_assignment. lo_avas = instantiate( ). lo_avas->if_pak_wb_object~get_last_changed( IMPORTING ex_changed_by = rv_user ). IF rv_user IS INITIAL. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_avas TYPE REF TO cl_cls_attr_value_assignment. lo_avas = instantiate( ). TRY. lo_avas->if_cls_attr_value_assignment~lock_and_refresh( im_allow_popups = abap_false ). CATCH cx_pak_invalid_state cx_pak_invalid_data cx_pak_not_authorized cx_pak_wb_object_locked. zcx_abapgit_exception=>raise( |AVAS error| ). ENDTRY. lo_avas->if_pak_wb_object~delete( ). lo_avas->if_pak_wb_object~save( ). lo_avas->if_pak_wb_object_internal~unlock( ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: ls_avas TYPE ty_avas. io_xml->read( EXPORTING iv_name = 'AVAS' CHANGING cg_data = ls_avas ). * The AVAS API cannot be used in this case, as it will always create a new GUID ASSERT NOT ls_avas-header-guid IS INITIAL. tadir_insert( iv_package ). corr_insert( iv_package ). insert_assignments( ls_avas ). * todo, how does links work? ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_guid TYPE cls_assignment-guid. SELECT SINGLE guid FROM cls_assignment INTO lv_guid WHERE guid = ms_item-obj_name. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'CLS_ENQUEUE_STRU' iv_argument = |{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_avas TYPE REF TO cl_cls_attr_value_assignment, ls_avas TYPE ty_avas. FIELD-SYMBOLS: LIKE LINE OF ls_avas-values, LIKE LINE OF ls_avas-links. lo_avas = instantiate( ). ls_avas-header-guid = lo_avas->if_cls_attr_value_assignment~get_guid( ). ls_avas-header-attribute = lo_avas->if_cls_attr_value_assignment~get_attribute( ). ls_avas-header-object = lo_avas->if_cls_attr_value_assignment~get_object( ). lo_avas->if_cls_attr_value_assignment~get_values( IMPORTING ex_values = ls_avas-values ). lo_avas->if_cls_attr_value_assignment~get_links( IMPORTING ex_links = ls_avas-links ). LOOP AT ls_avas-values ASSIGNING . CLEAR: -set_by, -changed_on. ENDLOOP. LOOP AT ls_avas-links ASSIGNING . CLEAR: -set_by, -changed_on. ENDLOOP. io_xml->add( iv_name = 'AVAS' ig_data = ls_avas ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_avar IMPLEMENTATION. METHOD create_object. DATA: lv_name TYPE aab_var_name. lv_name = ms_item-obj_name. CREATE OBJECT ro_aab_var EXPORTING im_name = lv_name im_local = '' EXCEPTIONS name_not_allowed = 1 user_not_valid = 2 no_authorization = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lo_aab TYPE REF TO cl_aab_variant. lo_aab = create_object( ). lo_aab->get_author( IMPORTING ex_author = rv_user ). ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_aab TYPE REF TO cl_aab_variant. lo_aab = create_object( ). lo_aab->enqueue( ). lo_aab->delete( EXCEPTIONS var_not_found = 1 prop_error = 2 propt_error = 3 var_id_error = 4 no_authorization = 5 cts_error = 6 cts_devclass = 7 OTHERS = 8 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error deleting AVAR { ms_item-obj_name }| ). ENDIF. lo_aab->dequeue( ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_possible TYPE abap_bool, lv_description TYPE aab_var_descript, ls_is TYPE aab_var_obj_act, lt_ids TYPE aab_var_obj_act_tab, lo_aab TYPE REF TO cl_aab_variant. " AVAR can only be created in transportable packages lv_possible = zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ). IF lv_possible = abap_false. zcx_abapgit_exception=>raise( |Global activation variants require a transportable package| ). ENDIF. " Create AVAR with description and object (id) list io_xml->read( EXPORTING iv_name = 'DESCRIPTION' CHANGING cg_data = lv_description ). io_xml->read( EXPORTING iv_name = 'IDS' CHANGING cg_data = lt_ids ). lo_aab = create_object( ). lo_aab->enqueue( ). lo_aab->set_descript( EXPORTING im_descript = lv_description EXCEPTIONS no_authorization = 1 ). IF sy-subrc <> 0. lo_aab->dequeue( ). zcx_abapgit_exception=>raise_t100( ). ENDIF. LOOP AT lt_ids INTO ls_is. lo_aab->set_id( EXPORTING im_name = ls_is-name im_object = ls_is-object im_actmode = ls_is-actmode EXCEPTIONS no_authorization = 1 id_not_exists = 2 id_not_transportable = 3 OTHERS = 4 ). IF sy-subrc <> 0. lo_aab->dequeue( ). zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. tadir_insert( iv_package ). lo_aab->save( EXCEPTIONS no_descript_specified = 1 prop_error = 2 propt_error = 3 var_id_error = 4 no_changes_found = 5 cts_error = 6 ). IF sy-subrc <> 0. lo_aab->dequeue( ). zcx_abapgit_exception=>raise_t100( ). ENDIF. lo_aab->dequeue( ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_state TYPE abap_bool, lo_aab TYPE REF TO cl_aab_variant. lo_aab = create_object( ). lo_aab->get_state( IMPORTING ex_state = lv_state ). rv_bool = boolc( lv_state = abap_true ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_aab TYPE REF TO cl_aab_variant, lt_ids TYPE aab_var_obj_act_tab, lv_description TYPE aab_var_descript. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. lo_aab = create_object( ). lo_aab->get_descript( IMPORTING ex_descript = lv_description EXCEPTIONS no_descript_found = 1 ). IF sy-subrc = 0. io_xml->add( iv_name = 'DESCRIPTION' ig_data = lv_description ). ENDIF. lo_aab->get_ids( IMPORTING ex_ids = lt_ids ). io_xml->add( iv_name = 'IDS' ig_data = lt_ids ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_auth IMPLEMENTATION. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_fieldname = ms_item-obj_name. ENDMETHOD. METHOD zif_abapgit_object~changed_by. * looks like "changed by user" is not stored in the database rv_user = c_user_unknown. ENDMETHOD. METHOD zif_abapgit_object~delete. " there is a bug in SAP standard, the TADIR entries are not deleted " when the AUTH object is deleted in transaction SU20 " FM SUSR_AUTF_DELETE_FIELD calls the UI, therefore we reimplement its logic DATA: lt_objlst TYPE susr_t_xuobject, lo_auth TYPE REF TO cl_auth_tools. " authority check CREATE OBJECT lo_auth. IF lo_auth->authority_check_suso( actvt = '06' fieldname = mv_fieldname ) <> 0. MESSAGE e463(01) WITH mv_fieldname INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. " if field is used check lt_objlst = lo_auth->suso_where_used_afield( mv_fieldname ). IF lt_objlst IS NOT INITIAL. MESSAGE i453(01) WITH mv_fieldname INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. " collect fieldname into a transport task IF lo_auth->add_afield_to_trkorr( mv_fieldname ) <> 0. "no transport -> no deletion MESSAGE e507(0m) INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. DELETE FROM authx WHERE fieldname = mv_fieldname. IF sy-subrc <> 0. MESSAGE e507(0m) INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. * see include LSAUT_FIELDF02 DATA: ls_authx TYPE authx, lo_auth TYPE REF TO cl_auth_tools. io_xml->read( EXPORTING iv_name = 'AUTHX' CHANGING cg_data = ls_authx ). tadir_insert( iv_package ). CREATE OBJECT lo_auth. IF lo_auth->add_afield_to_trkorr( ls_authx-fieldname ) <> 0. zcx_abapgit_exception=>raise( 'Error deserializing AUTH' ). ENDIF. MODIFY authx FROM ls_authx. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error deserializing AUTH' ). ENDIF. CALL FUNCTION 'DB_COMMIT'. lo_auth->set_authfld_info_from_db( ls_authx-fieldname ). ENDMETHOD. METHOD zif_abapgit_object~exists. SELECT SINGLE fieldname FROM authx INTO mv_fieldname WHERE fieldname = ms_item-obj_name. "#EC CI_GENBUFF rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. IF zcl_abapgit_factory=>get_function_module( )->function_exists( 'SU20_MAINTAIN_SNGL' ) = abap_true. " this function module does not exist in 740 CALL FUNCTION 'SU20_MAINTAIN_SNGL' EXPORTING id_field = mv_fieldname id_wbo_mode = abap_false. rv_exit = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: ls_authx TYPE authx. SELECT SINGLE * FROM authx INTO ls_authx WHERE fieldname = ms_item-obj_name. "#EC CI_GENBUFF IF sy-subrc <> 0. RETURN. ENDIF. io_xml->add( iv_name = 'AUTHX' ig_data = ls_authx ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_asfc IMPLEMENTATION. METHOD get_generic. CREATE OBJECT ro_generic EXPORTING is_item = ms_item iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. " not stored by SAP ENDMETHOD. METHOD zif_abapgit_object~delete. set_default_transport( iv_transport ). get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. set_default_transport( iv_transport ). get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_area IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lv_user TYPE string. SELECT SINGLE tstpnm FROM ('RSDAREA') INTO lv_user. rv_user = lv_user. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lr_area TYPE REF TO object. CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~DELETE_NODE') EXPORTING i_nodename = ms_item-obj_name i_with_dialog = ''. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error while deleting AREA: { ms_item-obj_name }| ). ENDIF. corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_nodename TYPE c LENGTH 40, lv_parentname TYPE c LENGTH 40, lv_txtsh TYPE c LENGTH 20, lv_txtlg TYPE c LENGTH 60, lr_area TYPE REF TO object. io_xml->read( EXPORTING iv_name = 'NODENAME' CHANGING cg_data = lv_nodename ). io_xml->read( EXPORTING iv_name = 'PARENTNAME' CHANGING cg_data = lv_parentname ). io_xml->read( EXPORTING iv_name = 'TXTSH' CHANGING cg_data = lv_txtsh ). io_xml->read( EXPORTING iv_name = 'TXTLG' CHANGING cg_data = lv_txtlg ). CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~CREATE_NODE') EXPORTING i_parentname = lv_parentname i_nodename = lv_nodename i_txtsh = lv_txtsh i_txtlg = lv_txtlg. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error while creating AREA: { ms_item-obj_name }| ). ENDIF. tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lr_area TYPE REF TO object, lr_tab_tree TYPE REF TO data, lr_str_tee TYPE REF TO data. FIELD-SYMBOLS: TYPE STANDARD TABLE, TYPE any. CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). CREATE DATA lr_tab_tree TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). ASSIGN lr_tab_tree->* TO . CREATE DATA lr_str_tee TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). ASSIGN lr_str_tee->* TO . CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~GET_TREE') EXPORTING i_objvers = '' i_langu = '' IMPORTING e_t_tree = . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error while read AREA tree| ). ENDIF. READ TABLE WITH KEY ('NODENAME') = ms_item-obj_name ASSIGNING . IF sy-subrc = 0. rv_bool = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. DATA: lr_area TYPE REF TO object, lr_tab_tree TYPE REF TO data, lr_str_tee TYPE REF TO data. FIELD-SYMBOLS: TYPE STANDARD TABLE, TYPE any. CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). CREATE DATA lr_tab_tree TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). ASSIGN lr_tab_tree->* TO . CREATE DATA lr_str_tee TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). ASSIGN lr_str_tee->* TO . CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~GET_TREE') EXPORTING i_objvers = 'A' i_langu = mv_language IMPORTING e_t_tree = . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error while read AREA tree| ). ENDIF. READ TABLE WITH KEY ('NODENAME') = ms_item-obj_name ASSIGNING . IF sy-subrc = 0. rv_active = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( 'ERSDAREA' ). ENDMETHOD. METHOD zif_abapgit_object~jump. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lr_area TYPE REF TO object, lr_tab_tree TYPE REF TO data, lr_str_tee TYPE REF TO data, lr_rsdareat TYPE REF TO data, lv_select TYPE string. FIELD-SYMBOLS: TYPE STANDARD TABLE, TYPE any, TYPE any, TYPE any, TYPE any, TYPE any. CREATE OBJECT lr_area TYPE ('CL_NEW_AWB_AREA'). CREATE DATA lr_tab_tree TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). ASSIGN lr_tab_tree->* TO . CREATE DATA lr_str_tee TYPE STANDARD TABLE OF ('RSAWBN_S_TREEORG'). ASSIGN lr_str_tee->* TO . CREATE DATA lr_rsdareat TYPE ('RSDAREAT'). ASSIGN lr_rsdareat->* TO . CALL METHOD lr_area->('IF_RSAWBN_FOLDER_TREE~GET_TREE') EXPORTING i_objvers = 'A' i_langu = mv_language IMPORTING e_t_tree = . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error while read AREA tree| ). ENDIF. READ TABLE WITH KEY ('NODENAME') = ms_item-obj_name ASSIGNING . lv_select = |INFOAREA = '{ ms_item-obj_name }'|. SELECT SINGLE * FROM ('RSDAREAT') INTO WHERE infoarea = ms_item-obj_name. ASSIGN COMPONENT 'TXTSH' OF STRUCTURE TO . ASSIGN COMPONENT 'TXTLG' OF STRUCTURE TO . ASSIGN COMPONENT 'PARENTNAME' OF STRUCTURE TO . io_xml->add( iv_name = 'NODENAME' ig_data = ms_item-obj_name ). io_xml->add( iv_name = 'PARENTNAME' ig_data = ). io_xml->add( iv_name = 'TXTSH' ig_data = ). io_xml->add( iv_name = 'TXTLG' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_aqsg IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). * add rules here if needed ENDMETHOD. METHOD get_generic. " transaction SQ02 CREATE OBJECT ro_generic EXPORTING is_item = ms_item io_field_rules = get_field_rules( ) iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMS38O'. -dynpro = '0050'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'RS38Q-NAME'. -fval = ms_item-obj_name. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SQ02' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_aqqu IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). * add rules here if needed ENDMETHOD. METHOD get_generic. " transaction SQ01 CREATE OBJECT ro_generic EXPORTING is_item = ms_item io_field_rules = get_field_rules( ) iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. rv_user = c_user_unknown. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMS38R'. -dynpro = '0050'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'RS38R-QNUM'. -fval = ms_item-obj_name. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SQ01' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_aqbg IMPLEMENTATION. METHOD get_field_rules. ro_result = zcl_abapgit_field_rules=>create( ). ro_result->add( iv_table = 'AQGDBBG' iv_field = 'BGCNAM' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user )->add( iv_table = 'AQGDBBG' iv_field = 'BGUNAM' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-user ). ro_result->add( iv_table = 'AQGDBBG' iv_field = 'BGCDAT' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date )->add( iv_table = 'AQGDBBG' iv_field = 'BGUDAT' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-date ). ro_result->add( iv_table = 'AQGDBBG' iv_field = 'DEVC' iv_fill_rule = zif_abapgit_field_rules=>c_fill_rule-package ). ENDMETHOD. METHOD get_generic. " transaction SQ03 CREATE OBJECT ro_generic EXPORTING is_item = ms_item io_field_rules = get_field_rules( ) iv_language = mv_language. ENDMETHOD. METHOD zif_abapgit_object~changed_by. SELECT SINGLE bgunam FROM aqgdbbg INTO rv_user WHERE num = ms_item-obj_name. IF sy-subrc <> 0. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. get_generic( )->delete( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. get_generic( )->deserialize( iv_package = iv_package io_xml = io_xml ). ENDMETHOD. METHOD zif_abapgit_object~exists. rv_bool = get_generic( )->exists( ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. DATA lt_bdcdata TYPE TABLE OF bdcdata. FIELD-SYMBOLS LIKE LINE OF lt_bdcdata. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -program = 'SAPMS38S'. -dynpro = '0050'. -dynbegin = abap_true. APPEND INITIAL LINE TO lt_bdcdata ASSIGNING . -fnam = 'RS38S-BGNUM'. -fval = ms_item-obj_name. zcl_abapgit_objects_factory=>get_gui_jumper( )->jump_batch_input( iv_tcode = 'SQ03' it_bdcdata = lt_bdcdata ). rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. get_generic( )->serialize( io_xml ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_apis IMPLEMENTATION. METHOD constructor. DATA lr_data TYPE REF TO data. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). TRY. CREATE DATA lr_data TYPE (c_model). CATCH cx_sy_create_error. zcx_abapgit_exception=>raise( |APIS not supported by your NW release| ). ENDTRY. ENDMETHOD. METHOD initialize. IF mo_handler IS NOT BOUND. CREATE OBJECT mo_handler TYPE ('CL_ARS_API_ABAPGIT') EXPORTING iv_api_object_name = ms_item-obj_name. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. initialize( ). TRY. CALL METHOD mo_handler->('IF_ARS_API_ABAPGIT~GET_CHANGED_BY') RECEIVING rv_changed_by = rv_user. CATCH cx_root. rv_user = c_user_unknown. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. * IF_ARS_API_ABAPGIT~DELETE_API_STATE dumps and checks fail, even though I as a developer can delete it DATA lo_db TYPE REF TO object. DATA lr_data TYPE REF TO data. FIELD-SYMBOLS TYPE any. CREATE DATA lr_data TYPE ('IF_ARS_STATE_DB_ACCESS=>TY_S_API_KEY'). ASSIGN lr_data->* TO . = ms_item-obj_name. ASSERT IS NOT INITIAL. CALL METHOD ('CL_ARS_STATE_DB_ACCESS')=>('GET_INSTANCE') RECEIVING ro_state_db_access = lo_db. CALL METHOD lo_db->('IF_ARS_STATE_DB_ACCESS~DELETE') EXPORTING is_api_key = . ENDMETHOD. METHOD zif_abapgit_object~deserialize. * IF_ARS_API_ABAPGIT~SAVE_API_STATE dumps in some package checks DATA lr_data TYPE REF TO data. DATA lo_db TYPE REF TO object. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE simple. CREATE DATA lr_data TYPE (c_model). ASSIGN lr_data->* TO . CREATE DATA lr_data TYPE ('IF_ARS_STATE_DB_ACCESS=>TY_S_HEADER'). ASSIGN lr_data->* TO . CREATE DATA lr_data TYPE ('IF_ARS_STATE_DB_ACCESS=>TY_T_STATE'). ASSIGN lr_data->* TO . io_xml->read( EXPORTING iv_name = 'APIS' CHANGING cg_data = ). MOVE-CORRESPONDING TO . ASSIGN COMPONENT 'API_STATES' OF STRUCTURE TO . ASSERT sy-subrc = 0. * the state table is sorted, LOOP AT ASSIGNING . CREATE DATA lr_data TYPE ('IF_ARS_STATE_DB_ACCESS=>TY_S_STATE'). ASSIGN lr_data->* TO . MOVE-CORRESPONDING TO . MOVE-CORRESPONDING TO . ASSIGN COMPONENT 'SOFTWARE_RELEASE_NAME' OF STRUCTURE TO . ASSERT sy-subrc = 0. = '1908'. ASSIGN COMPONENT 'CREATED_AT' OF STRUCTURE TO . ASSERT sy-subrc = 0. = sy-datum. ASSIGN COMPONENT 'CREATED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. = sy-uname. ASSIGN COMPONENT 'LAST_CHANGED_AT' OF STRUCTURE TO . ASSERT sy-subrc = 0. = sy-datum. ASSIGN COMPONENT 'LAST_CHANGED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. = sy-uname. INSERT INTO TABLE . ENDLOOP. CALL METHOD ('CL_ARS_STATE_DB_ACCESS')=>('GET_INSTANCE') RECEIVING ro_state_db_access = lo_db. CALL METHOD lo_db->('IF_ARS_STATE_DB_ACCESS~SAVE') EXPORTING is_header = it_release_states = . tadir_insert( iv_package ). corr_insert( iv_package ). ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. initialize( ). CALL METHOD mo_handler->('IF_ARS_API_ABAPGIT~CHECK_EXISTS') RECEIVING rv_api_exists = rv_bool. CATCH cx_root. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-late TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). rs_metadata-version = 'v2.0.0'. ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = zif_abapgit_object~exists( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. * looks like there is no enqueue lock * E_ARS_API ? RETURN. ENDMETHOD. METHOD zif_abapgit_object~jump. " todo ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA lr_data TYPE REF TO data. FIELD-SYMBOLS TYPE any. CREATE DATA lr_data TYPE (c_model). ASSIGN lr_data->* TO . initialize( ). CALL METHOD mo_handler->('IF_ARS_API_ABAPGIT~GET_API_STATE') RECEIVING rs_apis_object = . io_xml->add( iv_name = 'APIS' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_amsd IMPLEMENTATION. METHOD clear_field. FIELD-SYMBOLS: TYPE data. ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_logical_db_schema TO . ASSERT sy-subrc = 0. CLEAR: . ENDMETHOD. METHOD clear_fields. clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_AT' CHANGING cs_logical_db_schema = cs_logical_db_schema ). clear_field( EXPORTING iv_fieldname = 'METADATA-CREATED_BY' CHANGING cs_logical_db_schema = cs_logical_db_schema ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_AT' CHANGING cs_logical_db_schema = cs_logical_db_schema ). clear_field( EXPORTING iv_fieldname = 'METADATA-CHANGED_BY' CHANGING cs_logical_db_schema = cs_logical_db_schema ). ENDMETHOD. METHOD constructor. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). mv_logical_db_schema_key = ms_item-obj_name. TRY. CREATE DATA mr_logical_db_schema TYPE ('CL_AMDP_SCHEMA_OBJECT_DATA=>TY_OBJECT_DATA'). CREATE OBJECT mi_persistence TYPE ('CL_AMDP_SCHEMA_OBJECT_PERSIST'). CATCH cx_sy_create_error. zcx_abapgit_exception=>raise( |AMSD not supported by your NW release| ). ENDTRY. ENDMETHOD. METHOD fill_metadata_from_db. DATA: li_wb_object_operator TYPE REF TO object, lr_logical_db_schema_old TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE xsddatetime_z, TYPE syuname, TYPE xsddatetime_z, TYPE syuname. li_wb_object_operator = get_wb_object_operator( ). CREATE DATA lr_logical_db_schema_old TYPE ('CL_AMDP_SCHEMA_OBJECT_DATA=>TY_OBJECT_DATA'). ASSIGN lr_logical_db_schema_old->* TO . ASSERT sy-subrc = 0. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING data = . ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE cs_logical_db_schema TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE cs_logical_db_schema TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA-CREATED_BY' OF STRUCTURE TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'METADATA-CREATED_AT' OF STRUCTURE TO . ASSERT sy-subrc = 0. = . = . ENDMETHOD. METHOD get_wb_object_operator. DATA: ls_object_type TYPE wbobjtype, lx_error TYPE REF TO cx_root. IF mi_wb_object_operator IS BOUND. ri_wb_object_operator = mi_wb_object_operator. ENDIF. ls_object_type-objtype_tr = 'AMSD'. ls_object_type-subtype_wb = 'TYP'. TRY. CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') EXPORTING object_type = ls_object_type object_key = mv_logical_db_schema_key RECEIVING result = mi_wb_object_operator. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ri_wb_object_operator = mi_wb_object_operator. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: li_wb_object_operator TYPE REF TO object, li_object_data_model TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root. TRY. li_wb_object_operator = get_wb_object_operator( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') IMPORTING eo_object_data = li_object_data_model. rv_user = li_object_data_model->get_changed_by( ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: li_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~DELETE') EXPORTING transport_request = iv_transport. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, li_wb_object_operator TYPE REF TO object, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any. ASSIGN mr_logical_db_schema->* TO . ASSERT sy-subrc = 0. io_xml->read( EXPORTING iv_name = 'AMSD' CHANGING cg_data = ). li_wb_object_operator = get_wb_object_operator( ). TRY. CREATE OBJECT li_object_data_model TYPE ('CL_AMDP_SCHEMA_OBJECT_DATA'). tadir_insert( iv_package ). IF zif_abapgit_object~exists( ) = abap_true. " We need to populate created_at, created_by, because otherwise update is not possible fill_metadata_from_db( CHANGING cs_logical_db_schema = ). li_object_data_model->set_data( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = li_object_data_model transport_request = iv_transport. ELSE. li_object_data_model->set_data( ). CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~CREATE') EXPORTING io_object_data = li_object_data_model data_selection = 'P' " if_wb_object_data_selection_co=>c_properties package = iv_package transport_request = iv_transport. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~UPDATE') EXPORTING io_object_data = li_object_data_model data_selection = 'D' " if_wb_object_data_selection_co=>c_data_content transport_request = iv_transport. ENDIF. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~ACTIVATE'). corr_insert( iv_package ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. TRY. mi_persistence->get( p_object_key = mv_logical_db_schema_key p_version = 'A' p_existence_check_only = abap_true ). rv_bool = abap_true. CATCH cx_swb_exception. rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: li_object_data_model TYPE REF TO if_wb_object_data_model, lx_error TYPE REF TO cx_root, li_wb_object_operator TYPE REF TO object. FIELD-SYMBOLS: TYPE any. ASSIGN mr_logical_db_schema->* TO . ASSERT sy-subrc = 0. li_wb_object_operator = get_wb_object_operator( ). TRY. CALL METHOD li_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING version = 'A' IMPORTING data = eo_object_data = li_object_data_model. clear_fields( CHANGING cs_logical_db_schema = ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. io_xml->add( iv_name = 'AMSD' ig_data = ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_aifc IMPLEMENTATION. METHOD authorization_check. DATA: lx_dyn_call_error TYPE REF TO cx_sy_dyn_call_error. DATA: lx_root TYPE REF TO cx_root. rv_success = abap_false. TRY. CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~AUTHORIZATION_CHECK') RECEIVING rv_success = rv_success. CATCH cx_sy_dyn_call_error INTO lx_dyn_call_error. zcx_abapgit_exception=>raise( iv_text = 'AIFC not supported' ix_previous = lx_dyn_call_error ). CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. METHOD clear_client. DATA: BEGIN OF ls_data_to_clear, mandt TYPE sy-mandt, client TYPE sy-mandt, END OF ls_data_to_clear. FIELD-SYMBOLS: TYPE any. LOOP AT ct_data ASSIGNING . MOVE-CORRESPONDING ls_data_to_clear TO . ENDLOOP. ENDMETHOD. METHOD compress_interface. DATA: lx_dyn_call_error TYPE REF TO cx_sy_dyn_call_error. DATA: lx_root TYPE REF TO cx_root. TRY. CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~COMPRESS_INTERFACE') EXPORTING is_ifkeys = is_ifkeys RECEIVING rv_success = rv_success. CATCH cx_sy_dyn_call_error INTO lx_dyn_call_error. zcx_abapgit_exception=>raise( iv_text = 'AIFC not supported' ix_previous = lx_dyn_call_error ). CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. METHOD constructor. DATA: lx_exc_ref TYPE REF TO cx_sy_dyn_call_error. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). ms_icd_data_key = is_item-obj_name. TRY. CALL METHOD ('/AIF/CL_ABAPGIT_AIFC_UTIL')=>('GET_INSTANCE') RECEIVING rr_abapgit_aifc_util = mo_abapgit_util. CATCH cx_sy_dyn_call_error INTO lx_exc_ref. zcx_abapgit_exception=>raise( 'AIFC not supported' ). ENDTRY. ENDMETHOD. METHOD execute_checks. DATA ls_ifkeys TYPE ty_aif_key_s. DATA lr_tabledescr TYPE REF TO cl_abap_tabledescr. DATA lr_structdescr TYPE REF TO cl_abap_structdescr. DATA lr_table TYPE REF TO data. FIELD-SYMBOLS TYPE STANDARD TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS: TYPE any. DATA: lx_dyn_call_error TYPE REF TO cx_sy_dyn_call_error. DATA: lx_root TYPE REF TO cx_root. lr_structdescr ?= cl_abap_typedescr=>describe_by_name( p_name = '/AIF/T_FINF' ). lr_tabledescr = cl_abap_tabledescr=>create( p_line_type = lr_structdescr ). CREATE DATA lr_table TYPE HANDLE lr_tabledescr. ASSIGN lr_table->* TO . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Field Symbol not assigned' ). ENDIF. TRY. io_xml->read( EXPORTING iv_name = '/AIF/T_FINF' CHANGING cg_data = ). READ TABLE ASSIGNING INDEX 1. IF sy-subrc = 0. ASSIGN COMPONENT 'NS' OF STRUCTURE TO . IF sy-subrc = 0. ls_ifkeys-ns = . ENDIF. ASSIGN COMPONENT 'IFNAME' OF STRUCTURE TO . IF sy-subrc = 0. ls_ifkeys-ifname = . ENDIF. ASSIGN COMPONENT 'IFVERSION' OF STRUCTURE TO . IF sy-subrc = 0. ls_ifkeys-ifver = . ENDIF. CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~EXECUTE_CHECKS') EXPORTING is_ifkeys = ls_ifkeys is_finf = RECEIVING rv_success = rv_success. ENDIF. CATCH cx_sy_dyn_call_error INTO lx_dyn_call_error. zcx_abapgit_exception=>raise( iv_text = 'AIFC not supported' ix_previous = lx_dyn_call_error ). CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. METHOD get_content_compress. DATA: lx_dyn_call_error TYPE REF TO cx_sy_dyn_call_error. DATA: lx_root TYPE REF TO cx_root. DATA: lo_log TYPE REF TO object. TRY. CREATE OBJECT lo_log TYPE ('/AIF/CL_ABAPGIT_BAL_LOG') EXPORTING ir_git_log = io_log is_item = ms_item. CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~INITIALIZE_CONTENT_COMPRESS') EXPORTING ir_bal = lo_log is_ifkey = is_ifkeys iv_package = iv_package iv_depl_id = ms_icd_data_key-depl_scenario. CATCH cx_sy_dyn_call_error INTO lx_dyn_call_error. zcx_abapgit_exception=>raise( iv_text = 'AIFC not supported' ix_previous = lx_dyn_call_error ). CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. METHOD handle_table_data. DATA: lx_dyn_call_error TYPE REF TO cx_sy_dyn_call_error. DATA: lx_root TYPE REF TO cx_root. TRY. CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~HANDLE_TABLE_DATA') EXPORTING iv_tabname = iv_tabname it_data = it_data. CATCH cx_sy_dyn_call_error INTO lx_dyn_call_error. zcx_abapgit_exception=>raise( iv_text = 'AIFC not supported' ix_previous = lx_dyn_call_error ). CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. METHOD validate_interface. DATA: lx_dyn_call_error TYPE REF TO cx_sy_dyn_call_error. DATA: lx_root TYPE REF TO cx_root. rv_success = abap_false. TRY. CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~VALIDATE_INTERFACE') EXPORTING is_ifkeys = is_ifkeys RECEIVING rv_success = rv_success. CATCH cx_sy_dyn_call_error INTO lx_dyn_call_error. zcx_abapgit_exception=>raise( iv_text = 'AIFC not supported' ix_previous = lx_dyn_call_error ). CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA lx_dyn_call_error TYPE REF TO cx_sy_dyn_call_error. DATA ls_icd_data_key TYPE ty_icd_data_key. ls_icd_data_key-depl_scenario = ms_icd_data_key-depl_scenario. ls_icd_data_key-ns = ms_icd_data_key-ns. ls_icd_data_key-ifname = ms_icd_data_key-ifname. ls_icd_data_key-ifver2 = ms_icd_data_key-ifver2. TRY. CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~CHANGED_BY') EXPORTING is_key = ls_icd_data_key RECEIVING rv_user = rv_user. CATCH cx_sy_dyn_call_error INTO lx_dyn_call_error. zcx_abapgit_exception=>raise( iv_text = 'AIFC not supported' ix_previous = lx_dyn_call_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. zcx_abapgit_exception=>raise( 'Delete not supported.' ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lx_root TYPE REF TO cx_root. DATA: lt_content TYPE ty_content_t. DATA lr_tabledescr TYPE REF TO cl_abap_tabledescr. DATA lr_structdescr TYPE REF TO cl_abap_structdescr. DATA lr_table TYPE REF TO data. FIELD-SYMBOLS TYPE STANDARD TABLE. FIELD-SYMBOLS TYPE any. DATA ls_ifkey TYPE ty_aif_key_s. DATA lr_content TYPE REF TO ty_content_s. DATA lx_abap_not_a_table TYPE REF TO cx_abap_not_a_table. DATA lv_tablename TYPE string. FIELD-SYMBOLS: TYPE any. IF iv_step <> zif_abapgit_object=>gc_step_id-abap. RETURN. ENDIF. TRY. IF execute_checks( io_xml ) = abap_false. zcx_abapgit_exception=>raise( 'AIF interface checks failed' ). ENDIF. io_xml->read( EXPORTING iv_name = `Content_table` CHANGING cg_data = lt_content ). LOOP AT lt_content REFERENCE INTO lr_content. TRY. lv_tablename = cl_abap_dyn_prg=>check_table_name_str( val = lr_content->tabname packages = '' ). CATCH cx_abap_not_a_table INTO lx_abap_not_a_table. zcx_abapgit_exception=>raise_with_text( lx_abap_not_a_table ). CATCH cx_abap_not_in_package. "that's fine ENDTRY. CLEAR lr_tabledescr. lr_structdescr ?= cl_abap_typedescr=>describe_by_name( p_name = lr_content->tabname ). lr_tabledescr = cl_abap_tabledescr=>create( p_line_type = lr_structdescr ). CREATE DATA lr_table TYPE HANDLE lr_tabledescr. ASSIGN lr_table->* TO . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Field Symbol not assigned' ). ENDIF. io_xml->read( EXPORTING iv_name = lr_content->tabname CHANGING cg_data = ). handle_table_data( iv_tabname = lr_content->tabname it_data = ). IF lr_content->tabname = '/AIF/T_FINF'. READ TABLE ASSIGNING INDEX 1. ASSIGN COMPONENT 'NS' OF STRUCTURE TO . IF IS ASSIGNED. ls_ifkey-ns = . UNASSIGN . ENDIF. ASSIGN COMPONENT 'IFNAME' OF STRUCTURE TO . IF IS ASSIGNED. ls_ifkey-ifname = . UNASSIGN . ENDIF. ASSIGN COMPONENT 'IFVERSION' OF STRUCTURE TO . IF IS ASSIGNED. ls_ifkey-ifver = . UNASSIGN . ENDIF. ENDIF. ENDLOOP. IF ls_ifkey IS INITIAL. RETURN. ENDIF. get_content_compress( io_log = ii_log is_ifkeys = ls_ifkey iv_package = iv_package ). IF authorization_check( ) = abap_false. RETURN. ENDIF. IF validate_interface( ls_ifkey ) = abap_false. RETURN. ENDIF. IF compress_interface( ls_ifkey ) = abap_false. RETURN. ENDIF. CATCH cx_root INTO lx_root. ii_log->add_exception( ix_exc = lx_root is_item = ms_item ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lx_dyn_call_error TYPE REF TO cx_sy_dyn_call_error. DATA ls_icd_data_key TYPE ty_icd_data_key. ls_icd_data_key-depl_scenario = ms_icd_data_key-depl_scenario. ls_icd_data_key-ns = ms_icd_data_key-ns. ls_icd_data_key-ifname = ms_icd_data_key-ifname. ls_icd_data_key-ifver2 = ms_icd_data_key-ifver2. rv_bool = abap_false. TRY. CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~EXISTS') EXPORTING is_key = ls_icd_data_key RECEIVING rv_bool = rv_bool. CATCH cx_sy_dyn_call_error INTO lx_dyn_call_error. zcx_abapgit_exception=>raise( iv_text = 'AIFC not supported' ix_previous = lx_dyn_call_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. RETURN. ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = abap_false. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. rv_active = abap_true. ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. TYPES: ty_rsparamsl_255_t TYPE STANDARD TABLE OF rsparamsl_255 WITH NON-UNIQUE DEFAULT KEY. DATA lv_report TYPE progname VALUE '/AIF/CONTENT_DISPLAY'. DATA lt_params TYPE ty_rsparamsl_255_t. DATA ls_param LIKE LINE OF lt_params. ls_param-selname = 'P_DEPL'. ls_param-kind = 'P'. ls_param-sign = 'I'. ls_param-option = 'EQ'. ls_param-low = ms_icd_data_key-depl_scenario. APPEND ls_param TO lt_params. SUBMIT (lv_report) WITH SELECTION-TABLE lt_params AND RETURN. rv_exit = abap_true. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lx_root TYPE REF TO cx_root. DATA: lx_dyn_call_error TYPE REF TO cx_sy_dyn_call_error. DATA ls_icd_data_key TYPE ty_icd_data_key. DATA lt_ifdata TYPE ty_table_data_t. DATA lr_data TYPE REF TO data. FIELD-SYMBOLS TYPE any. DATA lt_content TYPE ty_content_t. DATA ls_content TYPE ty_content_s. DATA lr_ifdata TYPE REF TO ty_table_data_s. FIELD-SYMBOLS TYPE ANY TABLE. TRY. ASSIGN lr_data TO . IF NOT IS ASSIGNED. RETURN. ENDIF. ls_icd_data_key-depl_scenario = ms_icd_data_key-depl_scenario. ls_icd_data_key-ns = ms_icd_data_key-ns. ls_icd_data_key-ifname = ms_icd_data_key-ifname. ls_icd_data_key-ifver2 = ms_icd_data_key-ifver2. TRY. CALL METHOD mo_abapgit_util->('/AIF/IF_ABAPGIT_AIFC_UTIL~GET_IF_DATA') EXPORTING is_key = ls_icd_data_key RECEIVING rt_ifdata = lt_ifdata. CATCH cx_sy_dyn_call_error INTO lx_dyn_call_error. zcx_abapgit_exception=>raise( iv_text = 'AIFC not supported' ix_previous = lx_dyn_call_error ). ENDTRY. LOOP AT lt_ifdata REFERENCE INTO lr_ifdata. UNASSIGN . ASSIGN lr_ifdata->table_data->* TO . IF IS NOT ASSIGNED. CONTINUE. ENDIF. clear_client( CHANGING ct_data = ). io_xml->add( iv_name = lr_ifdata->tabname ig_data = ). ls_content-tabname = lr_ifdata->tabname. APPEND ls_content TO lt_content. ENDLOOP. io_xml->add( iv_name = `Content_table` ig_data = lt_content ). CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise( iv_text = 'Serialize not possible' ix_previous = lx_dyn_call_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_acid IMPLEMENTATION. METHOD create_object. DATA: lv_name TYPE aab_id_name. lv_name = ms_item-obj_name. CREATE OBJECT ro_aab EXPORTING im_name = lv_name EXCEPTIONS name_not_allowed = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. * looks like "changed by user" is not stored in the database rv_user = c_user_unknown. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lo_aab TYPE REF TO cl_aab_id. lo_aab = create_object( ). lo_aab->enqueue( EXCEPTIONS foreign_lock = 1 system_error = 2 cts_error = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. lo_aab->delete( EXCEPTIONS prop_error = 1 propt_error = 2 act_error = 3 cts_error = 4 cts_devclass = 5 id_not_found = 6 no_authorization = 7 id_still_used = 8 where_used_error = 9 OTHERS = 10 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. lo_aab->dequeue( ). ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_description TYPE aab_id_descript, lo_aab TYPE REF TO cl_aab_id. io_xml->read( EXPORTING iv_name = 'DESCRIPTION' CHANGING cg_data = lv_description ). lo_aab = create_object( ). lo_aab->enqueue( EXCEPTIONS foreign_lock = 1 system_error = 2 cts_error = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. lo_aab->set_descript( EXPORTING im_descript = lv_description EXCEPTIONS no_authorization = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. tadir_insert( iv_package ). lo_aab->save( EXCEPTIONS no_descript_specified = 1 no_changes_found = 2 prop_error = 3 propt_error = 4 act_error = 5 cts_error = 6 sync_attributes_error = 7 action_canceled = 8 OTHERS = 9 ). IF sy-subrc >= 3. zcx_abapgit_exception=>raise_t100( ). ENDIF. lo_aab->dequeue( ). ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_state TYPE abap_bool, lo_aab TYPE REF TO cl_aab_id. lo_aab = create_object( ). lo_aab->get_state( IMPORTING ex_state = lv_state ). rv_bool = boolc( lv_state = abap_true ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = abap_false. ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECTS=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lo_aab TYPE REF TO cl_aab_id, lv_description TYPE aab_id_descript. IF zif_abapgit_object~exists( ) = abap_false. RETURN. ENDIF. lo_aab = create_object( ). lo_aab->get_descript( IMPORTING ex_descript = lv_description EXCEPTIONS no_description_found = 1 ). io_xml->add( iv_name = 'DESCRIPTION' ig_data = lv_description ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_SOTS_HANDLER IMPLEMENTATION. METHOD create_sots. DATA: lt_sots TYPE ty_sots_tt, lt_sots_use TYPE ty_sots_use_tt. io_xml->read( EXPORTING iv_name = 'SOTS' CHANGING cg_data = lt_sots ). io_xml->read( EXPORTING iv_name = 'SOTS_USE' CHANGING cg_data = lt_sots_use ). create_sots_from_data( iv_package = iv_package it_sots = lt_sots it_sots_use = lt_sots_use ). ENDMETHOD. METHOD create_sots_from_data. DATA: lt_objects TYPE sotr_objects, lv_object LIKE LINE OF lt_objects, lv_subrc TYPE sy-subrc, ls_header TYPE btfr_head, lt_text_tab TYPE sotr_text_tt, lt_string_tab TYPE sotr_textl_tt, ls_entry LIKE LINE OF lt_string_tab, lv_concept TYPE sotr_conc, lv_concept_default TYPE sotr_conc. FIELD-SYMBOLS LIKE LINE OF it_sots. LOOP AT it_sots ASSIGNING . CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' EXPORTING object_vector = -header-objid_vec IMPORTING objects = lt_objects EXCEPTIONS object_not_found = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. READ TABLE lt_objects INDEX 1 INTO lv_object. ASSERT sy-subrc = 0. " Reimplementation of SOTR_STRING_CREATE_CONCEPT because we can't supply " concept and it would then be generated. LOOP AT -entries INTO ls_entry. ls_entry-langu = -header-crea_lan. ls_entry-concept = -header-concept. INSERT ls_entry INTO TABLE lt_string_tab. ENDLOOP. MOVE-CORRESPONDING -header TO ls_header. ls_header-paket = iv_package. lv_concept = -header-concept. PERFORM btfr_create IN PROGRAM saplsotr_db_string USING lv_object sy-langu abap_false abap_true CHANGING lt_text_tab lt_string_tab ls_header lv_concept lv_concept_default lv_subrc. CASE lv_subrc. WHEN 1. MESSAGE e100(sotr_mess) INTO zcx_abapgit_exception=>null. WHEN 2. MESSAGE e101(sotr_mess) INTO zcx_abapgit_exception=>null. WHEN 3. MESSAGE i305(sotr_mess) INTO zcx_abapgit_exception=>null. WHEN 4. " The concept will be created in the non-original system (not an error) WHEN 5. MESSAGE e504(sotr_mess) INTO zcx_abapgit_exception=>null. WHEN 6. MESSAGE e035(sotr_mess) INTO zcx_abapgit_exception=>null. WHEN 7. MESSAGE e170(sotr_mess) INTO zcx_abapgit_exception=>null. WHEN 9. MESSAGE e102(sotr_mess) INTO zcx_abapgit_exception=>null. ENDCASE. IF lv_subrc <> 0 AND lv_subrc <> 4. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. CALL FUNCTION 'SOTR_USAGE_STRING_MODIFY' EXPORTING sotr_usage = it_sots_use. ENDMETHOD. METHOD delete_sots. DATA lt_sots_use TYPE ty_sots_use_tt. FIELD-SYMBOLS LIKE LINE OF lt_sots_use. lt_sots_use = get_sots_usage( iv_pgmid = iv_pgmid iv_object = iv_object iv_obj_name = iv_obj_name ). " Remove any usage to ensure deletion, see function module BTFR_CHECK DELETE sotr_useu FROM TABLE lt_sots_use ##SUBRC_OK. LOOP AT lt_sots_use ASSIGNING WHERE concept IS NOT INITIAL. CALL FUNCTION 'BTFR_DELETE_SINGLE_TEXT' EXPORTING concept = -concept flag_string = abap_true EXCEPTIONS text_not_found = 1 "ok invalid_package = 3 text_not_changeable = 4 text_enqueued = 5 no_correction = 6 parameter_error = 7 OTHERS = 8. IF sy-subrc > 2. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD get_sots_4_concept. DATA: ls_header TYPE ty_sots-header, lt_entries TYPE ty_sots-entries. FIELD-SYMBOLS LIKE LINE OF lt_entries. CALL FUNCTION 'SOTR_STRING_GET_CONCEPT' EXPORTING concept = iv_concept IMPORTING header = ls_header entries = lt_entries EXCEPTIONS no_entry_found = 1 OTHERS = 2. IF sy-subrc <> 0. RETURN. ENDIF. CLEAR: ls_header-paket, ls_header-crea_name, ls_header-crea_tstut, ls_header-chan_name, ls_header-chan_tstut, ls_header-system_id. LOOP AT lt_entries ASSIGNING . CLEAR: -version, -crea_name, -crea_tstut, -chan_name, -chan_tstut. ENDLOOP. rs_sots-header = ls_header. rs_sots-entries = lt_entries. ENDMETHOD. METHOD get_sots_usage. DATA: lv_obj_name TYPE trobj_name. lv_obj_name = iv_obj_name. " Objects with multiple components IF iv_pgmid = 'LIMU' AND ( iv_object CP 'WDY*' OR iv_object = 'WAPP' ). lv_obj_name+30 = '%'. ENDIF. CALL FUNCTION 'SOTR_USAGE_STRING_READ' EXPORTING pgmid = iv_pgmid object = iv_object obj_name = lv_obj_name IMPORTING sotr_usage = rt_sots_use EXCEPTIONS no_entry_found = 1 error_in_pgmid = 2 OTHERS = 3. IF sy-subrc = 0. SORT rt_sots_use. ENDIF. ENDMETHOD. METHOD read_sots. FIELD-SYMBOLS LIKE LINE OF et_sots_use. DATA ls_sots TYPE ty_sots. " OTR long text (string) usage: see TABLE BTFR_OBJ_IDS " LIMU: CPUB, WAPP " R3TR: ENHO, ENHS, SICF, SMIF, WEBI, XSLT et_sots_use = get_sots_usage( iv_pgmid = iv_pgmid iv_object = iv_object iv_obj_name = iv_obj_name ). LOOP AT et_sots_use ASSIGNING WHERE concept IS NOT INITIAL. ls_sots = get_sots_4_concept( -concept ). IF io_i18n_params->ms_params-main_language_only = abap_true. DELETE ls_sots-entries WHERE langu <> io_i18n_params->ms_params-main_language. CHECK ls_sots-entries IS NOT INITIAL. ENDIF. INSERT ls_sots INTO TABLE et_sots. ENDLOOP. IF io_xml IS BOUND. io_xml->add( iv_name = 'SOTS' ig_data = et_sots ). io_xml->add( iv_name = 'SOTS_USE' ig_data = et_sots_use ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_sotr_handler IMPLEMENTATION. METHOD create_sotr. DATA: lt_sotr TYPE ty_sotr_tt, lt_sotr_use TYPE ty_sotr_use_tt. io_xml->read( EXPORTING iv_name = 'SOTR' CHANGING cg_data = lt_sotr ). io_xml->read( EXPORTING iv_name = 'SOTR_USE' CHANGING cg_data = lt_sotr_use ). create_sotr_from_data( iv_package = iv_package it_sotr = lt_sotr it_sotr_use = lt_sotr_use ). ENDMETHOD. METHOD create_sotr_from_data. DATA: lt_objects TYPE sotr_objects, ls_paket TYPE sotr_pack, lv_alias TYPE sotr_head-alias_name, lv_object LIKE LINE OF lt_objects. FIELD-SYMBOLS: LIKE LINE OF it_sotr. LOOP AT it_sotr ASSIGNING . CALL FUNCTION 'SOTR_OBJECT_GET_OBJECTS' EXPORTING object_vector = -header-objid_vec IMPORTING objects = lt_objects EXCEPTIONS object_not_found = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. READ TABLE lt_objects INDEX 1 INTO lv_object. ASSERT sy-subrc = 0. ls_paket-paket = iv_package. " Replace package in alias with new package lv_alias = -header-alias_name. IF lv_alias CS '/'. lv_alias = iv_package && lv_alias+sy-fdpos(*). ENDIF. CALL FUNCTION 'SOTR_CREATE_CONCEPT' EXPORTING paket = ls_paket crea_lan = -header-crea_lan alias_name = lv_alias object = lv_object entries = -entries concept_default = -header-concept EXCEPTIONS package_missing = 1 crea_lan_missing = 2 object_missing = 3 paket_does_not_exist = 4 alias_already_exist = 5 object_type_not_found = 6 langu_missing = 7 identical_context_not_allowed = 8 text_too_long = 9 error_in_update = 10 no_master_langu = 11 error_in_concept_id = 12 alias_not_allowed = 13 tadir_entry_creation_failed = 14 internal_error = 15 error_in_correction = 16 user_cancelled = 17 no_entry_found = 18 OTHERS = 19. IF sy-subrc <> 0 AND sy-subrc <> 5. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. CALL FUNCTION 'SOTR_USAGE_MODIFY' EXPORTING sotr_usage = it_sotr_use. ENDMETHOD. METHOD delete_sotr. DATA lt_sotr_use TYPE ty_sotr_use_tt. FIELD-SYMBOLS LIKE LINE OF lt_sotr_use. lt_sotr_use = get_sotr_usage( iv_pgmid = iv_pgmid iv_object = iv_object iv_obj_name = iv_obj_name ). " Remove any usage to ensure deletion, see function module BTFR_CHECK DELETE sotr_use FROM TABLE lt_sotr_use ##SUBRC_OK. LOOP AT lt_sotr_use ASSIGNING WHERE concept IS NOT INITIAL. CALL FUNCTION 'SOTR_DELETE_CONCEPT' EXPORTING concept = -concept EXCEPTIONS no_entry_found = 1 text_not_found = 2 invalid_package = 3 text_not_changeable = 4 text_enqueued = 5 no_correction = 6 parameter_error = 7 OTHERS = 8. IF sy-subrc > 2. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD delete_sotr_package. DATA lt_sotr_head TYPE STANDARD TABLE OF sotr_head WITH DEFAULT KEY. DATA lv_obj_name TYPE tadir-obj_name. FIELD-SYMBOLS LIKE LINE OF lt_sotr_head. SELECT * FROM sotr_head INTO TABLE lt_sotr_head WHERE paket = iv_package ORDER BY PRIMARY KEY. LOOP AT lt_sotr_head ASSIGNING WHERE concept IS NOT INITIAL. CALL FUNCTION 'SOTR_DELETE_CONCEPT' EXPORTING concept = -concept EXCEPTIONS no_entry_found = 1 text_not_found = 2 invalid_package = 3 text_not_changeable = 4 text_enqueued = 5 no_correction = 6 parameter_error = 7 OTHERS = 8. IF sy-subrc > 2. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. " Nothing left, then delete SOTR from TADIR SELECT * FROM sotr_head INTO TABLE lt_sotr_head WHERE paket = iv_package ORDER BY PRIMARY KEY. IF sy-subrc <> 0. SELECT SINGLE obj_name FROM tadir INTO lv_obj_name WHERE pgmid = 'R3TR' AND object = 'SOTR' AND obj_name = iv_package. IF sy-subrc = 0. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_delete_tadir_entry = abap_true wi_test_modus = abap_false wi_tadir_pgmid = 'R3TR' wi_tadir_object = 'SOTR' wi_tadir_obj_name = lv_obj_name EXCEPTIONS OTHERS = 1 ##FM_SUBRC_OK. IF zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ) = abap_true. zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( iv_object = 'SOTR' iv_obj_name = lv_obj_name iv_package = iv_package iv_mode = zif_abapgit_cts_api=>c_transport_mode-delete ). ENDIF. ENDIF. ENDIF. ENDMETHOD. METHOD get_sotr_4_concept. DATA: ls_header TYPE ty_sotr-header, lv_paket LIKE ls_header-alias_name, lt_entries TYPE ty_sotr-entries. FIELD-SYMBOLS: LIKE LINE OF lt_entries. CALL FUNCTION 'SOTR_GET_CONCEPT' EXPORTING concept = iv_concept IMPORTING header = ls_header TABLES entries = lt_entries EXCEPTIONS no_entry_found = 1 OTHERS = 2. IF sy-subrc <> 0. RETURN. ENDIF. " If alias contains package, remove it lv_paket = ls_header-paket && '/'. IF ls_header-alias_name CS lv_paket. ls_header-alias_name = replace( val = ls_header-alias_name sub = lv_paket with = '/' occ = 1 ). ENDIF. CLEAR: ls_header-paket, ls_header-crea_name, ls_header-crea_tstut, ls_header-chan_name, ls_header-chan_tstut, ls_header-system_id. LOOP AT lt_entries ASSIGNING . CLEAR: -version, -crea_name, -crea_tstut, -chan_name, -chan_tstut. ENDLOOP. rs_sotr-header = ls_header. rs_sotr-entries = lt_entries. ENDMETHOD. METHOD get_sotr_usage. DATA: lv_obj_name TYPE trobj_name. lv_obj_name = iv_obj_name. " Objects with multiple components IF iv_pgmid = 'LIMU' AND ( iv_object CP 'WDY*' OR iv_object = 'WAPP' ). lv_obj_name+30 = '%'. ENDIF. CALL FUNCTION 'SOTR_USAGE_READ' EXPORTING pgmid = iv_pgmid object = iv_object obj_name = lv_obj_name IMPORTING sotr_usage = rt_sotr_use EXCEPTIONS no_entry_found = 1 error_in_pgmid = 2 OTHERS = 3. IF sy-subrc = 0. SORT rt_sotr_use. ENDIF. ENDMETHOD. METHOD read_sotr. FIELD-SYMBOLS LIKE LINE OF et_sotr_use. DATA: lv_sotr TYPE ty_sotr, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. " OTR short text usage: see TABLE BTFR_OBJ_IDS " LIMU: CPUB, WAPP, WDYC, WDYD, WDYV " R3TR: ENHC, ENHO, ENHS, ENSC, SCGR, SMIF, WDCA, WDCC, WEBI, WEBS et_sotr_use = get_sotr_usage( iv_pgmid = iv_pgmid iv_object = iv_object iv_obj_name = iv_obj_name ). LOOP AT et_sotr_use ASSIGNING WHERE concept IS NOT INITIAL. lv_sotr = get_sotr_4_concept( -concept ). IF io_xml IS BOUND AND io_i18n_params->ms_params-main_language_only = abap_true. DELETE lv_sotr-entries WHERE langu <> io_i18n_params->ms_params-main_language. CHECK lv_sotr-entries IS NOT INITIAL. ENDIF. lt_language_filter = io_i18n_params->build_language_filter( ). DELETE lv_sotr-entries WHERE NOT langu IN lt_language_filter AND langu <> io_i18n_params->ms_params-main_language. CHECK lv_sotr-entries IS NOT INITIAL. INSERT lv_sotr INTO TABLE et_sotr. ENDLOOP. IF io_xml IS BOUND. io_xml->add( iv_name = 'SOTR' ig_data = et_sotr ). io_xml->add( iv_name = 'SOTR_USE' ig_data = et_sotr_use ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_properties_file IMPLEMENTATION. METHOD constructor. mv_lang = to_lower( iv_lang ). ENDMETHOD. METHOD get_translations. DATA: lv_translation TYPE string, lo_ajson TYPE REF TO zcl_abapgit_json_handler, lo_json_path TYPE REF TO zcl_abapgit_json_path, lx_exception TYPE REF TO cx_static_check. CREATE OBJECT lo_ajson. CREATE OBJECT lo_json_path. TRY. lv_translation = lo_json_path->deserialize( mt_translation ). lo_ajson->deserialize( EXPORTING iv_content = lv_translation IMPORTING ev_data = ev_data ). CATCH cx_static_check INTO lx_exception. zcx_abapgit_exception=>raise_with_text( lx_exception ). ENDTRY. ENDMETHOD. METHOD parse. DATA lv_data TYPE string. lv_data = zcl_abapgit_convert=>xstring_to_string_utf8( iv_xdata ). SPLIT lv_data AT cl_abap_char_utilities=>newline INTO TABLE mt_translation. ENDMETHOD. METHOD push_text_pairs. mt_translation = it_translation. ENDMETHOD. METHOD zif_abapgit_i18n_file~ext. rv_ext = 'properties'. ENDMETHOD. METHOD zif_abapgit_i18n_file~lang. rv_lang = mv_lang. ENDMETHOD. METHOD zif_abapgit_i18n_file~render. DATA lv_translation TYPE string. lv_translation = concat_lines_of( table = mt_translation sep = cl_abap_char_utilities=>newline ) && cl_abap_char_utilities=>newline. rv_data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_translation ). ENDMETHOD. METHOD zif_abapgit_i18n_file~translate. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_po_file IMPLEMENTATION. METHOD build_po_body. FIELD-SYMBOLS LIKE LINE OF mt_pairs. FIELD-SYMBOLS LIKE LINE OF -comments. CREATE OBJECT ro_buf. LOOP AT mt_pairs ASSIGNING . IF sy-tabix <> 1. ro_buf->add( '' ). ENDIF. " TODO integrate translator comments ? SORT -comments BY kind. LOOP AT -comments ASSIGNING . ro_buf->add( |#{ get_comment_marker( -kind ) } { -text }| ). ENDLOOP. ro_buf->add( |msgid { quote( -source ) }| ). ro_buf->add( |msgstr { quote( -target ) }| ). ENDLOOP. ENDMETHOD. METHOD build_po_head. CREATE OBJECT ro_buf. " TODO, more headers ? sample: https://www.gnu.org/software/trans-coord/manual/gnun/html_node/PO-Header.html " TODO, does \n really necessary ? check editors support for non-\n " TODO, should be unfuzzy for final version, and potentially should have more fields ro_buf->add( '#, fuzzy' ). ro_buf->add( 'msgid ""' ). ro_buf->add( 'msgstr ""' ). ro_buf->add( '"MIME-Version: 1.0\n"' ). ro_buf->add( '"Content-Type: text/plain; charset=UTF-8\n"' ). ro_buf->add( '"Content-Transfer-Encoding: 8bit\n"' ). ro_buf->add( '' ). ENDMETHOD. METHOD constructor. mv_lang = to_lower( iv_lang ). ENDMETHOD. METHOD get_comment_marker. CASE iv_comment_kind. WHEN c_comment-translator. rv_marker = ''. WHEN c_comment-extracted. rv_marker = '.'. WHEN c_comment-reference. rv_marker = ':'. WHEN c_comment-flag. rv_marker = ','. WHEN c_comment-previous. rv_marker = '|'. ENDCASE. ENDMETHOD. METHOD parse. DATA lv_xdata TYPE xstring. DATA lv_data TYPE string. IF xstrlen( iv_xdata ) > 3 AND iv_xdata(3) = cl_abap_char_utilities=>byte_order_mark_utf8. lv_xdata = iv_xdata+3. ELSE. lv_xdata = iv_xdata. ENDIF. lv_data = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xdata ). parse_po( lv_data ). ENDMETHOD. METHOD parse_po. CONSTANTS: BEGIN OF c_state, wait_id TYPE i VALUE 0, wait_str TYPE i VALUE 1, wait_eos TYPE i VALUE 2, " TODO msgctx END OF c_state. DATA lv_state TYPE i VALUE c_state-wait_id. DATA lt_lines TYPE string_table. DATA ls_pair LIKE LINE OF mt_pairs. DATA lv_whitespace TYPE c LENGTH 2. FIELD-SYMBOLS TYPE string. lv_whitespace = ` ` && cl_abap_char_utilities=>horizontal_tab. SPLIT iv_data AT cl_abap_char_utilities=>newline INTO TABLE lt_lines. APPEND '' TO lt_lines. " terminator LOOP AT lt_lines ASSIGNING . IF lv_state = c_state-wait_eos. IF strlen( ) >= 1 AND +0(1) = '"'. ls_pair-target = ls_pair-target && unquote( ). CONTINUE. ELSE. lv_state = c_state-wait_id. IF ls_pair-source IS NOT INITIAL. " skip header entry for now INSERT ls_pair INTO TABLE mt_pairs. " Sorted, duplicates will not be inserted ENDIF. CLEAR ls_pair. ENDIF. ENDIF. CASE lv_state. WHEN c_state-wait_id. IF IS INITIAL OR +0(1) = '#' " TODO, potentially parse comments in future, to re-integrate OR CO lv_whitespace. CONTINUE. ENDIF. IF strlen( ) >= 6 AND +0(6) = `msgid `. " w/trailing space ls_pair-source = unquote( substring( val = off = 6 ) ). lv_state = c_state-wait_str. ELSE. zcx_abapgit_exception=>raise( 'PO file format error: expected msgid' ). ENDIF. WHEN c_state-wait_str. IF strlen( ) >= 7 AND +0(7) = `msgstr `. " w/trailing space ls_pair-target = unquote( substring( val = off = 7 ) ). lv_state = c_state-wait_eos. ELSE. zcx_abapgit_exception=>raise( 'PO file format error: expected msgstr' ). ENDIF. ENDCASE. ENDLOOP. ENDMETHOD. METHOD push_text_pairs. DATA ls_out LIKE LINE OF mt_pairs. FIELD-SYMBOLS LIKE LINE OF it_text_pairs. FIELD-SYMBOLS LIKE LINE OF mt_pairs. DATA ls_comment LIKE LINE OF -comments. LOOP AT it_text_pairs ASSIGNING . CHECK -s_text IS NOT INITIAL. READ TABLE mt_pairs ASSIGNING WITH KEY source = -s_text. IF sy-subrc <> 0. ls_out-source = -s_text. INSERT ls_out INTO TABLE mt_pairs ASSIGNING . ASSERT sy-subrc = 0. ENDIF. IF -target IS INITIAL. " For a case of orig text duplication -target = -t_text. ENDIF. ls_comment-kind = c_comment-reference. ls_comment-text = condense( |{ iv_objtype }/{ iv_objname }/{ -textkey }| ) && |, maxlen={ -unitmlt }|. APPEND ls_comment TO -comments. ASSERT sy-subrc = 0. ENDLOOP. ENDMETHOD. METHOD quote. rv_text = '"' && replace( val = iv_text sub = '"' with = '\"' occ = 0 ) && '"'. ENDMETHOD. METHOD unquote. DATA lv_len TYPE i. DATA lv_prev_char TYPE i. rv_text = iv_text. SHIFT rv_text RIGHT DELETING TRAILING space. " Measure perf ? Could be slowish, maybe use find SHIFT rv_text LEFT DELETING LEADING space. lv_len = strlen( rv_text ). IF lv_len < 2. zcx_abapgit_exception=>raise( 'PO file format error: bad quoting' ). ENDIF. lv_prev_char = lv_len - 1. IF rv_text+0(1) <> '"' OR rv_text+lv_prev_char(1) <> '"'. zcx_abapgit_exception=>raise( 'PO file format error: bad quoting' ). ENDIF. lv_prev_char = lv_prev_char - 1. IF lv_len >= 3 AND rv_text+lv_prev_char(1) = '\'. " escaped quote zcx_abapgit_exception=>raise( 'PO file format error: bad quoting' ). ENDIF. rv_text = substring( val = rv_text off = 1 len = lv_len - 2 ). rv_text = replace( val = rv_text sub = '\"' with = '"' occ = 0 ). rv_text = replace( val = rv_text sub = '\n' with = cl_abap_char_utilities=>newline occ = 0 ). " TODO: theoretically there can be unescaped " - is it a problem ? check standard ENDMETHOD. METHOD zif_abapgit_i18n_file~ext. rv_ext = 'po'. ENDMETHOD. METHOD zif_abapgit_i18n_file~lang. rv_lang = mv_lang. ENDMETHOD. METHOD zif_abapgit_i18n_file~render. DATA lv_str TYPE string. lv_str = build_po_body( )->join_w_newline_and_flush( ). IF lv_str IS NOT INITIAL. lv_str = build_po_head( )->join_w_newline_and_flush( ) && cl_abap_char_utilities=>newline && lv_str && cl_abap_char_utilities=>newline. " Trailing LF rv_data = zcl_abapgit_convert=>string_to_xstring_utf8_bom( lv_str ). ENDIF. ENDMETHOD. METHOD zif_abapgit_i18n_file~translate. FIELD-SYMBOLS LIKE LINE OF ct_text_pairs. FIELD-SYMBOLS LIKE LINE OF mt_pairs. DATA lv_idx TYPE i. LOOP AT ct_text_pairs ASSIGNING . CHECK -s_text IS NOT INITIAL. lv_idx = sy-tabix. READ TABLE mt_pairs ASSIGNING WITH KEY source = -s_text. IF sy-subrc = 0 AND -target IS NOT INITIAL. -t_text = -target. ELSE. DELETE ct_text_pairs INDEX lv_idx. " Otherwise error in LXE FMs for empty translation ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_lxe_texts IMPLEMENTATION. METHOD check_langs_versus_installed. DATA lt_installed_hash TYPE HASHED TABLE OF laiso WITH UNIQUE KEY table_line. FIELD-SYMBOLS LIKE LINE OF it_languages. CLEAR: et_intersection, et_missfits. lt_installed_hash = it_installed. LOOP AT it_languages ASSIGNING . READ TABLE lt_installed_hash WITH KEY table_line = TRANSPORTING NO FIELDS. IF sy-subrc = 0. APPEND TO et_intersection. ELSE. APPEND TO et_missfits. ENDIF. ENDLOOP. ENDMETHOD. METHOD class_constructor. APPEND 'CLAS' TO gt_supported_obj_types. APPEND 'DOMA' TO gt_supported_obj_types. APPEND 'DTEL' TO gt_supported_obj_types. APPEND 'FUGR' TO gt_supported_obj_types. APPEND 'MSAG' TO gt_supported_obj_types. APPEND 'PARA' TO gt_supported_obj_types. APPEND 'PROG' TO gt_supported_obj_types. APPEND 'SHI3' TO gt_supported_obj_types. APPEND 'TABL' TO gt_supported_obj_types. APPEND 'TRAN' TO gt_supported_obj_types. APPEND 'VIEW' TO gt_supported_obj_types. ENDMETHOD. METHOD convert_lang_string_to_table. DATA: lt_langs_str TYPE string_table, lv_laiso TYPE laiso, lv_skip_main_lang_iso TYPE laiso. FIELD-SYMBOLS: LIKE LINE OF lt_langs_str. " Keep * as indicator for 'all installed languages' IF iv_langs = '*'. APPEND iv_langs TO rt_languages. RETURN. ENDIF. " Convert string of 2-letter ISO languages into table of sy-langu codes SPLIT iv_langs AT ',' INTO TABLE lt_langs_str. LOOP AT lt_langs_str ASSIGNING . lv_laiso = condense( to_upper( ) ). APPEND lv_laiso TO rt_languages. ENDLOOP. IF iv_skip_main_language IS NOT INITIAL. lv_skip_main_lang_iso = langu_to_laiso_safe( iv_skip_main_language ). DELETE rt_languages WHERE table_line = lv_skip_main_lang_iso. ENDIF. SORT rt_languages. DELETE ADJACENT DUPLICATES FROM rt_languages. ENDMETHOD. METHOD convert_table_to_lang_string. DATA: lt_langs_str TYPE string_table. FIELD-SYMBOLS: LIKE LINE OF it_languages, TYPE string. " Convert table of sy-langu codes into string of 2-letter ISO languages LOOP AT it_languages ASSIGNING . " Keep * as indicator for 'all installed languages' IF = '*'. CLEAR lt_langs_str. APPEND '*' TO lt_langs_str. EXIT. ENDIF. APPEND INITIAL LINE TO lt_langs_str ASSIGNING . = . ENDLOOP. CONCATENATE LINES OF lt_langs_str INTO rv_langs SEPARATED BY ','. ENDMETHOD. METHOD deserialize_from_po. DATA lv_lang LIKE LINE OF mo_i18n_params->ms_params-translation_languages. DATA lt_po_files TYPE zif_abapgit_i18n_file=>ty_table_of. DATA li_po LIKE LINE OF lt_po_files. DATA lt_text_pairs_tmp TYPE ty_lxe_translation-text_pairs. DATA lt_obj_list TYPE lxe_tt_colob. DATA lv_main_lang TYPE lxeisolang. DATA lv_target_lang TYPE lxeisolang. FIELD-SYMBOLS LIKE LINE OF lt_obj_list. lt_obj_list = get_lxe_object_list( iv_object_name = iv_object_name iv_object_type = iv_object_type ). IF lt_obj_list IS INITIAL. RETURN. ENDIF. lt_po_files = mo_files->read_i18n_files( ). lv_main_lang = get_lang_iso4( langu_to_laiso_safe( mo_i18n_params->ms_params-main_language ) ). LOOP AT mo_i18n_params->ms_params-translation_languages INTO lv_lang. lv_target_lang = get_lang_iso4( lv_lang ). LOOP AT lt_po_files INTO li_po. IF li_po->lang( ) = to_lower( lv_lang ). " Not quite efficient but the list is presumably very short EXIT. ELSE. CLEAR li_po. ENDIF. ENDLOOP. CHECK li_po IS BOUND. " Ignore missing files, missing translation is not a crime LOOP AT lt_obj_list ASSIGNING . lt_text_pairs_tmp = read_lxe_object_text_pair( iv_s_lang = lv_main_lang iv_t_lang = lv_target_lang iv_custmnr = -custmnr iv_objtype = -objtype iv_objname = -objname iv_read_only = abap_false ). li_po->translate( CHANGING ct_text_pairs = lt_text_pairs_tmp ). " TODO maybe optimize, check if values have changed write_lxe_object_text_pair( iv_s_lang = lv_main_lang iv_t_lang = lv_target_lang iv_custmnr = -custmnr iv_objtype = -objtype iv_objname = -objname it_pcx_s1 = lt_text_pairs_tmp ). ENDLOOP. ENDLOOP. ENDMETHOD. METHOD deserialize_xml. DATA: lt_lxe_texts TYPE ty_lxe_translations, ls_lxe_item LIKE LINE OF lt_lxe_texts, lt_text_pairs_tmp LIKE ls_lxe_item-text_pairs. mi_xml_in->read( EXPORTING iv_name = iv_lxe_text_name CHANGING cg_data = lt_lxe_texts ). LOOP AT lt_lxe_texts INTO ls_lxe_item. " Call Read first for buffer prefill lt_text_pairs_tmp = read_lxe_object_text_pair( iv_s_lang = ls_lxe_item-source_lang iv_t_lang = ls_lxe_item-target_lang iv_custmnr = ls_lxe_item-custmnr iv_objtype = ls_lxe_item-objtype iv_objname = ls_lxe_item-objname iv_read_only = abap_false ). "Call actual Write FM write_lxe_object_text_pair( iv_s_lang = ls_lxe_item-source_lang iv_t_lang = ls_lxe_item-target_lang iv_custmnr = ls_lxe_item-custmnr iv_objtype = ls_lxe_item-objtype iv_objname = ls_lxe_item-objname it_pcx_s1 = ls_lxe_item-text_pairs ). ENDLOOP. ENDMETHOD. METHOD detect_unsupported_languages. check_langs_versus_installed( EXPORTING it_languages = it_languages it_installed = get_installed_languages( ) IMPORTING et_missfits = rt_unsupported_languages ). ENDMETHOD. METHOD get_installed_languages. DATA: lv_index TYPE i, lv_langu TYPE sy-langu, lv_laiso TYPE laiso, lv_installed_languages TYPE string, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. IF gt_installed_languages_cache IS INITIAL. CALL FUNCTION 'SYSTEM_INSTALLED_LANGUAGES' IMPORTING languages = lv_installed_languages EXCEPTIONS sapgparam_error = 1 " Error requesting profile parameter OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Fail to get system SYSTEM_INSTALLED_LANGUAGES' ). ENDIF. lt_language_filter = zcl_abapgit_factory=>get_environment( )->get_system_language_filter( ). DO strlen( lv_installed_languages ) TIMES. lv_index = sy-index - 1. lv_langu = lv_installed_languages+lv_index(1). IF lv_langu NOT IN lt_language_filter. CONTINUE. ENDIF. lv_laiso = langu_to_laiso_safe( lv_langu ). APPEND lv_laiso TO gt_installed_languages_cache. ENDDO. ENDIF. rt_languages = gt_installed_languages_cache. ENDMETHOD. METHOD get_lang_iso4. DATA lv_lang_iso639 TYPE laiso. DATA lv_country TYPE land1. DATA lv_class TYPE string. lv_class = 'CL_I18N_LANGUAGES'. " cannot find a way to do this in Steampunk, so dynamic for now, CALL METHOD (lv_class)=>sap2_to_iso639_1 EXPORTING im_lang_sap2 = iv_src IMPORTING ex_lang_iso639 = lv_lang_iso639 ex_country = lv_country EXCEPTIONS no_assignment = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Failed to convert [{ iv_src }] lang to iso639| ). ENDIF. CONCATENATE lv_lang_iso639 lv_country INTO rv_iso4. ENDMETHOD. METHOD get_lxe_object_list. DATA lv_object_name TYPE trobj_name. lv_object_name = iv_object_name. CALL FUNCTION 'LXE_OBJ_EXPAND_TRANSPORT_OBJ' EXPORTING pgmid = 'R3TR' object = iv_object_type obj_name = lv_object_name TABLES ex_colob = rt_obj_list EXCEPTIONS unknown_object = 1 unknown_ta_type = 2 OTHERS = 3. IF sy-subrc <> 0. RETURN. " Ignore error and return empty list ENDIF. ENDMETHOD. METHOD get_translation_languages. " Returns a list of translation languages for serialization " If the setting is initial, no translations shall be serialized " If the setting is `*`, all installed system languages shall be serialized " Else, the setting shall contain all languages to be serialized DATA lv_main_lang_laiso TYPE laiso. IF it_i18n_languages IS NOT INITIAL. READ TABLE it_i18n_languages TRANSPORTING NO FIELDS WITH KEY table_line = '*'. IF sy-subrc = 0. rt_languages = get_installed_languages( ). ELSE. check_langs_versus_installed( EXPORTING it_languages = it_i18n_languages it_installed = get_installed_languages( ) IMPORTING et_intersection = rt_languages ). ENDIF. ENDIF. " Remove main language from translation languages lv_main_lang_laiso = langu_to_laiso_safe( iv_main_language ). DELETE rt_languages WHERE table_line = lv_main_lang_laiso. ENDMETHOD. METHOD iso4_to_iso2. rv_laiso = iv_lxe_lang+0(2). ENDMETHOD. METHOD is_object_supported. READ TABLE gt_supported_obj_types TRANSPORTING NO FIELDS WITH KEY table_line = iv_object_type. rv_yes = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD langu_to_laiso_safe. zcl_abapgit_convert=>language_sap1_to_sap2( EXPORTING im_lang_sap1 = iv_langu RECEIVING re_lang_sap2 = rv_laiso EXCEPTIONS no_assignment = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Could not convert lang [{ iv_langu }] to ISO| ). ENDIF. ENDMETHOD. METHOD read_lxe_object_text_pair. DATA: lv_error TYPE lxestring. TRY. CALL FUNCTION 'LXE_OBJ_TEXT_PAIR_READ' EXPORTING s_lang = iv_s_lang t_lang = iv_t_lang custmnr = iv_custmnr objtype = iv_objtype objname = iv_objname read_only = iv_read_only IMPORTING err_msg = lv_error " doesn't exist in NW <= 750 TABLES lt_pcx_s1 = rt_text_pairs_tmp. IF lv_error IS NOT INITIAL. zcx_abapgit_exception=>raise( lv_error ). ENDIF. CATCH cx_sy_dyn_call_param_not_found. CALL FUNCTION 'LXE_OBJ_TEXT_PAIR_READ' EXPORTING s_lang = iv_s_lang t_lang = iv_t_lang custmnr = iv_custmnr objtype = iv_objtype objname = iv_objname read_only = iv_read_only TABLES lt_pcx_s1 = rt_text_pairs_tmp. ENDTRY. ENDMETHOD. METHOD read_text_items. DATA: lt_obj_list TYPE lxe_tt_colob, lv_main_lang TYPE lxeisolang, ls_lxe_text_item LIKE LINE OF rt_text_items. FIELD-SYMBOLS: LIKE LINE OF mo_i18n_params->ms_params-translation_languages, LIKE LINE OF lt_obj_list. lt_obj_list = get_lxe_object_list( iv_object_name = iv_object_name iv_object_type = iv_object_type ). IF lt_obj_list IS INITIAL. RETURN. ENDIF. " Get list of languages that need to be serialized (already resolves * and installed languages) lv_main_lang = get_lang_iso4( langu_to_laiso_safe( mo_i18n_params->ms_params-main_language ) ). LOOP AT lt_obj_list ASSIGNING . CLEAR ls_lxe_text_item. ls_lxe_text_item-custmnr = -custmnr. ls_lxe_text_item-objtype = -objtype. ls_lxe_text_item-objname = -objname. LOOP AT mo_i18n_params->ms_params-translation_languages ASSIGNING . ls_lxe_text_item-source_lang = lv_main_lang. ls_lxe_text_item-target_lang = get_lang_iso4( ). IF ls_lxe_text_item-source_lang = ls_lxe_text_item-target_lang. CONTINUE. " if source = target -> skip ENDIF. ls_lxe_text_item-text_pairs = read_lxe_object_text_pair( iv_s_lang = ls_lxe_text_item-source_lang iv_t_lang = ls_lxe_text_item-target_lang iv_custmnr = ls_lxe_text_item-custmnr iv_objtype = ls_lxe_text_item-objtype iv_objname = ls_lxe_text_item-objname ). IF ls_lxe_text_item-text_pairs IS NOT INITIAL. APPEND ls_lxe_text_item TO rt_text_items. ENDIF. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD serialize_as_po. DATA lt_lxe_texts TYPE ty_lxe_translations. DATA lo_po_file TYPE REF TO zcl_abapgit_po_file. DATA lv_lang LIKE LINE OF mo_i18n_params->ms_params-translation_languages. FIELD-SYMBOLS LIKE LINE OF lt_lxe_texts. lt_lxe_texts = read_text_items( iv_object_name = iv_object_name iv_object_type = iv_object_type ). LOOP AT mo_i18n_params->ms_params-translation_languages INTO lv_lang. lv_lang = to_lower( lv_lang ). CREATE OBJECT lo_po_file EXPORTING iv_lang = lv_lang. LOOP AT lt_lxe_texts ASSIGNING . IF iso4_to_iso2( -target_lang ) = lv_lang. lo_po_file->push_text_pairs( iv_objtype = -objtype iv_objname = -objname it_text_pairs = -text_pairs ). ENDIF. ENDLOOP. mo_files->add_i18n_file( lo_po_file ). ENDLOOP. ENDMETHOD. METHOD serialize_xml. DATA lt_lxe_texts TYPE ty_lxe_translations. lt_lxe_texts = read_text_items( iv_object_name = iv_object_name iv_object_type = iv_object_type ). IF lines( lt_lxe_texts ) > 0. mi_xml_out->add( iv_name = iv_lxe_text_name ig_data = lt_lxe_texts ). ENDIF. ENDMETHOD. METHOD write_lxe_object_text_pair. DATA: lv_error TYPE lxestring. TRY. CALL FUNCTION 'LXE_OBJ_TEXT_PAIR_WRITE' EXPORTING s_lang = iv_s_lang t_lang = iv_t_lang custmnr = iv_custmnr objtype = iv_objtype objname = iv_objname IMPORTING err_msg = lv_error " doesn't exist in NW <= 750 TABLES lt_pcx_s1 = it_pcx_s1. IF lv_error IS NOT INITIAL. zcx_abapgit_exception=>raise( lv_error ). ENDIF. CATCH cx_sy_dyn_call_param_not_found. CALL FUNCTION 'LXE_OBJ_TEXT_PAIR_WRITE' EXPORTING s_lang = iv_s_lang t_lang = iv_t_lang custmnr = iv_custmnr objtype = iv_objtype objname = iv_objname TABLES lt_pcx_s1 = it_pcx_s1. ENDTRY. ENDMETHOD. METHOD zif_abapgit_lxe_texts~deserialize. IF is_object_supported( iv_object_type ) = abap_false. RETURN. ENDIF. mo_i18n_params = io_i18n_params. mi_xml_in = ii_xml. mo_files = io_files. " MAYBE TODO: see comment in serialize IF 1 = 1. deserialize_from_po( iv_object_type = iv_object_type iv_object_name = iv_object_name ). ELSE. deserialize_xml( iv_object_type = iv_object_type iv_object_name = iv_object_name ). ENDIF. ENDMETHOD. METHOD zif_abapgit_lxe_texts~serialize. IF is_object_supported( iv_object_type ) = abap_false. RETURN. ENDIF. mo_i18n_params = io_i18n_params. mi_xml_out = ii_xml. mo_files = io_files. " MAYBE TODO " if other formats are needed, including the old in-XML approach " here is the place to implement it. Supposed architecture: " I18N_PARAMS should contain an option which format to use " The option should be originally maintained in dot_abapgit structures (e.g. `translation_storage_format`) " Consequently it comes here " The serialize method can read it and call a corresponding submethod, " e.g. serialize_xml or serialize_as_po or ... " both ii_xml and io_files are accessible intentionally to enable both XML based or file based formats " access to json can be easily added too, " or maybe (maybe) some kind of zif_ag_object_ctl with all DAO instead IF 1 = 1. serialize_as_po( iv_object_type = iv_object_type iv_object_name = iv_object_name ). ELSE. serialize_xml( iv_object_type = iv_object_type iv_object_name = iv_object_name ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_longtexts IMPLEMENTATION. METHOD escape_name. " Prepare name for SQL LIKE condition rv_object = iv_object_name. IF 'CA,CE,CO,CT,IA,IE,IO,WC,FU,FX,DI,IS,PS' CS iv_longtext_id. " Document types of objects with sub-objects rv_object+30 = '%'. ELSEIF 'OD' CS iv_longtext_id. rv_object+10 = '%'. ENDIF. rv_object = replace( val = rv_object sub = '_' with = '#_' occ = 0 ). ENDMETHOD. METHOD read. DATA: ls_longtext TYPE zif_abapgit_longtexts=>ty_longtext, lv_object TYPE dokil-object, lt_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt. FIELD-SYMBOLS: LIKE LINE OF lt_dokil. lv_object = escape_name( iv_longtext_id = iv_longtext_id iv_object_name = iv_object_name ). IF lines( it_dokil ) > 0. lt_dokil = it_dokil. IF iv_main_lang_only = abap_true. DELETE lt_dokil WHERE masterlang <> abap_true. ENDIF. ELSEIF iv_longtext_id IS NOT INITIAL. IF iv_main_lang_only = abap_true. SELECT * FROM dokil INTO TABLE lt_dokil WHERE id = iv_longtext_id AND object LIKE lv_object ESCAPE '#' AND masterlang = abap_true ORDER BY PRIMARY KEY. ELSE. SELECT * FROM dokil INTO TABLE lt_dokil WHERE id = iv_longtext_id AND object LIKE lv_object ESCAPE '#' ORDER BY PRIMARY KEY. ENDIF. ELSE. zcx_abapgit_exception=>raise( |serialize_longtexts parameter error| ). ENDIF. LOOP AT lt_dokil ASSIGNING WHERE txtlines > 0. CLEAR: ls_longtext. ls_longtext-dokil = . CALL FUNCTION 'DOCU_READ' EXPORTING id = -id langu = -langu object = -object typ = -typ version = -version IMPORTING head = ls_longtext-head TABLES line = ls_longtext-lines. IF iv_clear_fields = abap_true. CLEAR: ls_longtext-head-tdfuser, ls_longtext-head-tdfreles, ls_longtext-head-tdfdate, ls_longtext-head-tdftime, ls_longtext-head-tdluser, ls_longtext-head-tdlreles, ls_longtext-head-tdldate, ls_longtext-head-tdltime. ENDIF. INSERT ls_longtext INTO TABLE rt_longtexts. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_longtexts~changed_by. DATA: lt_longtexts TYPE zif_abapgit_longtexts=>ty_longtexts. FIELD-SYMBOLS: TYPE zif_abapgit_longtexts=>ty_longtext. lt_longtexts = read( iv_object_name = iv_object_name iv_longtext_id = iv_longtext_id it_dokil = it_dokil iv_clear_fields = abap_false ). READ TABLE lt_longtexts INDEX 1 ASSIGNING . IF sy-subrc = 0. rv_user = -head-tdluser. IF rv_user IS INITIAL. rv_user = -head-tdfuser. ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_longtexts~delete. DATA: lt_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt, lv_object TYPE dokil-object. FIELD-SYMBOLS: TYPE dokil. lv_object = escape_name( iv_longtext_id = iv_longtext_id iv_object_name = iv_object_name ). SELECT * FROM dokil INTO TABLE lt_dokil WHERE id = iv_longtext_id AND object LIKE lv_object ESCAPE '#' ORDER BY PRIMARY KEY. LOOP AT lt_dokil ASSIGNING . CALL FUNCTION 'DOCU_DEL' EXPORTING id = -id langu = -langu object = -object typ = -typ EXCEPTIONS ret_code = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_longtexts~deserialize. DATA: lt_longtexts TYPE zif_abapgit_longtexts=>ty_longtexts, lv_object TYPE dokil-object, lt_dokil TYPE zif_abapgit_definitions=>ty_dokil_tt, lv_no_main_lang TYPE dokil-masterlang. FIELD-SYMBOLS: TYPE zif_abapgit_longtexts=>ty_longtext, TYPE dokil. lv_object = escape_name( iv_longtext_id = iv_longtext_id iv_object_name = iv_object_name ). ii_xml->read( EXPORTING iv_name = iv_longtext_name CHANGING cg_data = lt_longtexts ). LOOP AT lt_longtexts ASSIGNING . lv_no_main_lang = boolc( iv_main_language <> -dokil-langu ). CALL FUNCTION 'DOCU_UPDATE' EXPORTING head = -head state = c_docu_state_active typ = -dokil-typ version = -dokil-version no_masterlang = lv_no_main_lang TABLES line = -lines. ENDLOOP. " Read existing texts and check if they were deserialized above " If not, delete the texts SELECT * FROM dokil INTO TABLE lt_dokil WHERE id = iv_longtext_id AND object LIKE lv_object ESCAPE '#' ORDER BY PRIMARY KEY. LOOP AT lt_dokil ASSIGNING . READ TABLE lt_longtexts TRANSPORTING NO FIELDS WITH KEY dokil-id = -id dokil-langu = -langu dokil-object = -object dokil-typ = -typ. IF sy-subrc <> 0. CALL FUNCTION 'DOCU_DEL' EXPORTING id = -id langu = -langu object = -object typ = -typ EXCEPTIONS ret_code = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_longtexts~serialize. rt_longtexts = read( iv_object_name = iv_object_name iv_longtext_id = iv_longtext_id it_dokil = it_dokil iv_main_lang_only = io_i18n_params->ms_params-main_language_only ). IF rt_longtexts IS SUPPLIED. RETURN. ENDIF. ii_xml->add( iv_name = iv_longtext_name ig_data = rt_longtexts ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_i18n_params IMPLEMENTATION. METHOD build_language_filter. IF mt_language_filter IS INITIAL. " translation_languages are includes, system langs are excludes, so the do not interfere IF ms_params-translation_languages IS NOT INITIAL. mt_language_filter = iso_langs_to_lang_filter( ms_params-translation_languages ). ELSE. mt_language_filter = zcl_abapgit_factory=>get_environment( )->get_system_language_filter( ). ENDIF. ENDIF. rt_language_filter = mt_language_filter. ENDMETHOD. METHOD constructor. IF is_params IS NOT INITIAL. ms_params = is_params. ELSE. ms_params-main_language = iv_main_language. ms_params-main_language_only = iv_main_language_only. ms_params-translation_languages = it_translation_langs. ms_params-use_lxe = iv_use_lxe. ENDIF. ASSERT ms_params-main_language IS NOT INITIAL. ENDMETHOD. METHOD iso_langs_to_lang_filter. DATA lv_laiso LIKE LINE OF it_iso_filter. DATA lv_langu TYPE sy-langu. DATA ls_range LIKE LINE OF rt_language_filter. ls_range-sign = 'I'. ls_range-option = 'EQ'. LOOP AT it_iso_filter INTO lv_laiso. zcl_abapgit_convert=>language_sap2_to_sap1( EXPORTING im_lang_sap2 = lv_laiso RECEIVING re_lang_sap1 = lv_langu EXCEPTIONS no_assignment = 1 OTHERS = 2 ). IF sy-subrc <> 0. CONTINUE. ENDIF. ls_range-low = lv_langu. APPEND ls_range TO rt_language_filter. ENDLOOP. ENDMETHOD. METHOD is_lxe_applicable. rv_yes = boolc( ms_params-main_language_only = abap_false AND ms_params-use_lxe = abap_true AND ms_params-translation_languages IS NOT INITIAL ). ENDMETHOD. METHOD new. CREATE OBJECT ro_instance EXPORTING iv_main_language = iv_main_language iv_main_language_only = iv_main_language_only it_translation_langs = it_translation_langs iv_use_lxe = iv_use_lxe is_params = is_params. ENDMETHOD. METHOD trim_saplang_keyed_table. DATA lv_laiso TYPE laiso. DATA lv_index TYPE i. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE sy-langu. IF ms_params-translation_languages IS INITIAL OR iv_lang_field_name IS INITIAL. RETURN. " Nothing to filter ENDIF. LOOP AT ct_tab ASSIGNING . lv_index = sy-tabix. ASSIGN COMPONENT iv_lang_field_name OF STRUCTURE TO . ASSERT sy-subrc = 0. IF iv_keep_master_lang = abap_true AND = ms_params-main_language. CONTINUE. " Just keep it ENDIF. zcl_abapgit_convert=>language_sap1_to_sap2( EXPORTING im_lang_sap1 = RECEIVING re_lang_sap2 = lv_laiso EXCEPTIONS no_assignment = 1 OTHERS = 2 ). IF sy-subrc <> 0. DELETE ct_tab INDEX lv_index. " Not in the list anyway ... CONTINUE. ENDIF. " Not a sorted table, but presumably the list is small, so no significant performance flow READ TABLE ms_params-translation_languages TRANSPORTING NO FIELDS WITH KEY table_line = lv_laiso. IF sy-subrc <> 0. DELETE ct_tab INDEX lv_index. ENDIF. ENDLOOP. ENDMETHOD. METHOD trim_saplang_list. DATA lv_langu TYPE sy-langu. DATA lv_laiso TYPE laiso. DATA lv_index TYPE i. IF ms_params-translation_languages IS INITIAL. RETURN. " Nothing to filter ENDIF. LOOP AT ct_sap_langs INTO lv_langu. lv_index = sy-tabix. zcl_abapgit_convert=>language_sap1_to_sap2( EXPORTING im_lang_sap1 = lv_langu RECEIVING re_lang_sap2 = lv_laiso EXCEPTIONS no_assignment = 1 OTHERS = 2 ). IF sy-subrc <> 0. DELETE ct_sap_langs INDEX lv_index. " Not in the list anyway ... CONTINUE. ENDIF. " Not a sorted table, but presumably the list is small, so no significant performance flow READ TABLE ms_params-translation_languages TRANSPORTING NO FIELDS WITH KEY table_line = lv_laiso. IF sy-subrc <> 0. DELETE ct_sap_langs INDEX lv_index. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_TABL_DDL IMPLEMENTATION. METHOD deserialize. * https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/abenddicddl_define_table.htm * CL_SBD_STRUCTURE_OBJDATA has serializer in local class DATA lv_ddl TYPE string. DATA lv_fields TYPE string. DATA lv_start TYPE i. DATA lv_length TYPE i. DATA lv_end TYPE i. DATA lt_fields TYPE STANDARD TABLE OF string WITH DEFAULT KEY. DATA lv_field TYPE string. lv_ddl = iv_ddl. parse_top_annotations( CHANGING cs_data = rs_data cv_ddl = lv_ddl ). FIND FIRST OCCURRENCE OF '{' IN lv_ddl MATCH OFFSET lv_start. ASSERT lv_start > 0. FIND FIRST OCCURRENCE OF '}' IN lv_ddl MATCH OFFSET lv_end. ASSERT lv_end > 0. lv_start = lv_start + 1. lv_length = lv_end - lv_start - 1. lv_fields = lv_ddl+lv_start(lv_length). SPLIT lv_fields AT |;| INTO TABLE lt_fields. LOOP AT lt_fields INTO lv_field WHERE table_line IS NOT INITIAL. parse_field( EXPORTING iv_field = lv_field CHANGING cs_data = rs_data ). ENDLOOP. ENDMETHOD. METHOD escape_string. rv_string = |'{ replace( val = iv_string sub = |'| with = |''| occ = 0 ) }'|. ENDMETHOD. METHOD parse_field. CONSTANTS: BEGIN OF lc_mode, start TYPE i VALUE 0, colon TYPE i VALUE 1, type TYPE i VALUE 2, aftertype TYPE i VALUE 2, null TYPE i VALUE 2, afternull TYPE i VALUE 2, END OF lc_mode. DATA lv_field TYPE string. DATA lv_mode TYPE i. DATA lt_tokens TYPE STANDARD TABLE OF string WITH DEFAULT KEY. DATA lv_token TYPE string. DATA ls_dd08v TYPE dd08v. FIELD-SYMBOLS LIKE LINE OF cs_data-dd03p. lv_field = iv_field. parse_field_annotations( IMPORTING es_dd08v = ls_dd08v CHANGING cv_ddl = lv_field ). SPLIT lv_field AT space INTO TABLE lt_tokens. APPEND INITIAL LINE TO cs_data-dd03p ASSIGNING . LOOP AT lt_tokens INTO lv_token WHERE table_line IS NOT INITIAL. CASE lv_mode. WHEN lc_mode-start. * todo, is it possible to have a key field named "key" ? IF lv_token = 'key'. -keyflag = abap_true. ELSE. -fieldname = to_upper( lv_token ). lv_mode = lc_mode-colon. ENDIF. WHEN lc_mode-colon. ASSERT lv_token = ':'. lv_mode = lc_mode-type. WHEN lc_mode-type. parse_type( EXPORTING iv_token = lv_token CHANGING cs_dd03p = ). RETURN. WHEN lc_mode-aftertype. IF lv_token = 'not'. -notnull = abap_true. lv_mode = lc_mode-null. ENDIF. WHEN lc_mode-null. ASSERT lv_token = 'null'. lv_mode = lc_mode-afternull. WHEN lc_mode-afternull. ASSERT lv_token = 'with'. RETURN. " todo WHEN OTHERS. ASSERT 1 = 'todo'. ENDCASE. ENDLOOP. ENDMETHOD. METHOD parse_field_annotations. DATA lv_annotation TYPE string. DATA lv_name TYPE string. DATA lv_value TYPE string. REPLACE FIRST OCCURRENCE OF REGEX '^[\n ]*' IN cv_ddl WITH ||. WHILE cv_ddl CP '@*'. SPLIT cv_ddl AT |\n| INTO lv_annotation cv_ddl. CONDENSE cv_ddl. SPLIT lv_annotation AT ':' INTO lv_name lv_value. CONDENSE lv_name. CONDENSE lv_value. ASSERT lv_name IS NOT INITIAL. ASSERT lv_value IS NOT INITIAL. CASE lv_name. WHEN '@AbapCatalog.foreignKey.label'. es_dd08v-ddtext = unescape_string( lv_value ). WHEN '@AbapCatalog.foreignKey.keyType'. ASSERT lv_value(1) = '#'. es_dd08v-frkart = lv_value+1. WHEN '@AbapCatalog.foreignKey.screenCheck'. ASSERT lv_value = 'true'. WHEN OTHERS. WRITE: / 'todo:', lv_name, lv_value. ASSERT 1 = 'todo'. ENDCASE. ENDWHILE. ENDMETHOD. METHOD parse_top_annotations. DATA lv_annotation TYPE string. DATA lv_name TYPE string. DATA lv_value TYPE string. WHILE cv_ddl CP '@*'. SPLIT cv_ddl AT |\n| INTO lv_annotation cv_ddl. SPLIT lv_annotation AT ':' INTO lv_name lv_value. CONDENSE lv_name. CONDENSE lv_value. ASSERT lv_name IS NOT INITIAL. ASSERT lv_value IS NOT INITIAL. CASE lv_name. WHEN '@EndUserText.label'. cs_data-dd02v-ddtext = unescape_string( lv_value ). WHEN '@AbapCatalog.enhancementCategory'. CASE lv_value. WHEN '#NOT_EXTENSIBLE'. cs_data-dd02v-contflag = '1'. WHEN OTHERS. ASSERT 1 = 'todo'. ENDCASE. WHEN '@AbapCatalog.tableCategory'. CASE lv_value. WHEN '#TRANSPARENT'. cs_data-dd02v-tabclass = 'TRANSP'. WHEN OTHERS. ASSERT 1 = 'todo'. ENDCASE. WHEN '@AbapCatalog.deliveryClass'. ASSERT lv_value(1) = '#'. cs_data-dd02v-contflag = lv_value+1. WHEN '@AbapCatalog.dataMaintenance'. CASE lv_value. WHEN '#ALLOWED'. cs_data-dd02v-mainflag = abap_true. WHEN '#LIMITED'. cs_data-dd02v-mainflag = abap_false. WHEN OTHERS. ASSERT 1 = 'todo'. ENDCASE. WHEN OTHERS. WRITE: / 'todo:', lv_name, lv_value. ASSERT 1 = 'todo'. ENDCASE. ENDWHILE. ENDMETHOD. METHOD parse_type. DATA lv_token TYPE string. lv_token = iv_token. IF lv_token CP 'abap.*'. lv_token = lv_token+5. IF lv_token(4) = 'char'. * todo, length cs_dd03p-datatype = 'CHAR'. ELSEIF lv_token(6) = 'string'. cs_dd03p-intlen = 8. cs_dd03p-inttype = 'g'. cs_dd03p-datatype = 'STRG'. ELSE. ASSERT 1 = 'todo'. ENDIF. ELSE. cs_dd03p-rollname = to_upper( lv_token ). ENDIF. ENDMETHOD. METHOD read_data. * temporary method for testing DATA lv_name TYPE ddobjname. lv_name = iv_name. CALL FUNCTION 'DDIF_TABL_GET' EXPORTING name = lv_name langu = 'E' IMPORTING dd02v_wa = rs_data-dd02v dd09l_wa = rs_data-dd09l TABLES dd03p_tab = rs_data-dd03p dd05m_tab = rs_data-dd05m dd08v_tab = rs_data-dd08v dd12v_tab = rs_data-dd12v dd17v_tab = rs_data-dd17v dd35v_tab = rs_data-dd35v dd36m_tab = rs_data-dd36m EXCEPTIONS illegal_input = 1 OTHERS = 2. ASSERT sy-subrc = 0. ENDMETHOD. METHOD serialize. DATA ls_dd03p LIKE LINE OF is_data-dd03p. DATA lv_key TYPE string. DATA lv_type TYPE string. DATA lv_pre TYPE string. DATA lv_int TYPE i. DATA lv_suffix TYPE string. DATA lv_notnull TYPE string. DATA lv_colon TYPE i. rv_ddl = rv_ddl && serialize_top( is_data ). rv_ddl = rv_ddl && |define table { to_lower( is_data-dd02v-tabname ) } \{\n|. LOOP AT is_data-dd03p INTO ls_dd03p WHERE ( fieldname NP '.INCLU*' OR groupname IS NOT INITIAL ) AND adminfield = '0'. lv_int = 0. IF ls_dd03p-keyflag = abap_true. lv_int = 4. ENDIF. IF ls_dd03p-groupname IS INITIAL. lv_int = lv_int + strlen( ls_dd03p-fieldname ). ELSE. lv_int = lv_int + strlen( ls_dd03p-groupname ). ENDIF. IF lv_int > lv_colon. lv_colon = lv_int. ENDIF. ENDLOOP. * ADMINFIELD: skip fields inside .INCLUDEs LOOP AT is_data-dd03p INTO ls_dd03p WHERE adminfield = '0'. CLEAR lv_key. CLEAR lv_notnull. IF ls_dd03p-keyflag = abap_true. lv_key = |key |. ENDIF. lv_pre = |{ lv_key }{ to_lower( ls_dd03p-fieldname ) }|. IF ls_dd03p-groupname IS NOT INITIAL. lv_pre = |{ lv_key }{ to_lower( ls_dd03p-groupname ) }|. ENDIF. IF strlen( lv_pre ) < lv_colon. lv_pre = lv_pre && repeat( val = | | occ = lv_colon - strlen( lv_pre ) ). ENDIF. IF ls_dd03p-fieldname = '.INCLU--AP'. CONTINUE. ELSEIF ls_dd03p-fieldname CP '.INCLU*'. IF ls_dd03p-notnull = abap_true. lv_notnull = | not null|. ENDIF. CLEAR lv_suffix. IF ls_dd03p-fieldname CA '-'. SPLIT ls_dd03p-fieldname AT '-' INTO lv_suffix lv_suffix. lv_suffix = | with suffix { to_lower( lv_suffix ) }|. ENDIF. IF ls_dd03p-groupname IS INITIAL. rv_ddl = rv_ddl && | { lv_key }include { to_lower( ls_dd03p-precfield ) }{ lv_suffix }{ lv_notnull }|. ELSE. rv_ddl = rv_ddl && | { lv_pre } : include { to_lower( ls_dd03p-precfield ) }{ lv_suffix }{ lv_notnull }|. ENDIF. rv_ddl = rv_ddl && serialize_extend( is_dd03p = ls_dd03p is_data = is_data ). rv_ddl = rv_ddl && |;\n|. CONTINUE. ENDIF. rv_ddl = rv_ddl && serialize_field_annotations( iv_fieldname = ls_dd03p-fieldname is_data = is_data ). rv_ddl = rv_ddl && serialize_fkey_annotations( iv_fieldname = ls_dd03p-fieldname is_data = is_data ). lv_type = serialize_type( ls_dd03p ). rv_ddl = rv_ddl && | { lv_pre } : { lv_type }|. rv_ddl = rv_ddl && serialize_field_foreign_key( iv_fieldname = ls_dd03p-fieldname is_data = is_data ). rv_ddl = rv_ddl && serialize_value_help( iv_fieldname = ls_dd03p-fieldname is_data = is_data ). rv_ddl = rv_ddl && |;\n|. ENDLOOP. rv_ddl = rv_ddl && |\n|. rv_ddl = rv_ddl && |\}|. ENDMETHOD. METHOD serialize_adt. DATA ls_object_type TYPE wbobjtype. DATA lv_object_key TYPE seu_objkey. DATA li_object_data TYPE REF TO if_wb_object_data_model. DATA lo_operator TYPE REF TO object. ls_object_type-objtype_tr = 'TABL'. ls_object_type-subtype_wb = 'DT'. lv_object_key = iv_name. CALL METHOD ('CL_WB_OBJECT_OPERATOR')=>('CREATE_INSTANCE') EXPORTING object_type = ls_object_type object_key = lv_object_key RECEIVING result = lo_operator. CALL METHOD lo_operator->('IF_WB_OBJECT_OPERATOR~READ') EXPORTING version = 'A' IMPORTING eo_object_data = li_object_data. CALL METHOD li_object_data->('GET_CONTENT') IMPORTING p_data = rv_ddl. ENDMETHOD. METHOD serialize_extend. DATA lv_index TYPE i. DATA ls_dd03p LIKE LINE OF is_data-dd03p. DATA lt_fields TYPE STANDARD TABLE OF string WITH DEFAULT KEY. DATA lv_field LIKE LINE OF lt_fields. DATA ls_dd08v LIKE LINE OF is_data-dd08v. DATA ls_dd35v LIKE LINE OF is_data-dd35v. READ TABLE is_data-dd03p TRANSPORTING NO FIELDS WITH KEY fieldname = is_dd03p-fieldname precfield = is_dd03p-precfield. ASSERT sy-subrc = 0. lv_index = sy-tabix + 1. * the extended keys are not sorted by the fieldname positions LOOP AT is_data-dd03p FROM lv_index INTO ls_dd03p. IF ls_dd03p-adminfield = '0'. EXIT. ENDIF. APPEND ls_dd03p-fieldname TO lt_fields. ENDLOOP. CLEAR ls_dd03p. LOOP AT is_data-dd08v INTO ls_dd08v WHERE ( noinherit = 'Y' OR checktable = '*' ) AND noinherit <> 'N'. READ TABLE lt_fields TRANSPORTING NO FIELDS WITH KEY table_line = ls_dd08v-fieldname. IF sy-subrc <> 0. CONTINUE. ENDIF. DELETE lt_fields WHERE table_line = ls_dd08v-fieldname. rv_ddl = rv_ddl && |\n|. IF ls_dd08v-checktable <> '*'. rv_ddl = rv_ddl && serialize_fkey_annotations( iv_fieldname = ls_dd08v-fieldname is_data = is_data ). ENDIF. rv_ddl = rv_ddl && | extend { to_lower( ls_dd08v-fieldname ) } :|. IF ls_dd08v-checktable = '*'. rv_ddl = rv_ddl && |\n remove foreign key|. ELSE. rv_ddl = rv_ddl && serialize_field_foreign_key( iv_fieldname = ls_dd08v-fieldname is_data = is_data ). ENDIF. READ TABLE is_data-dd35v INTO ls_dd35v WITH KEY fieldname = ls_dd08v-fieldname. IF sy-subrc = 0. IF ls_dd35v-shlpname = '*'. rv_ddl = rv_ddl && |\n remove value help|. ELSEIF ls_dd35v-shlpinher <> abap_true. rv_ddl = rv_ddl && serialize_value_help( iv_fieldname = ls_dd08v-fieldname is_data = is_data ). ENDIF. ENDIF. ENDLOOP. LOOP AT is_data-dd35v INTO ls_dd35v. READ TABLE lt_fields INTO lv_field WITH KEY table_line = ls_dd35v-fieldname. IF sy-subrc <> 0. CONTINUE. ENDIF. IF ls_dd35v-shlpname = '*'. rv_ddl = rv_ddl && |\n|. rv_ddl = rv_ddl && | extend { to_lower( lv_field ) } :|. rv_ddl = rv_ddl && |\n remove value help|. ELSEIF ls_dd35v-shlpinher <> abap_true. rv_ddl = rv_ddl && |\n|. rv_ddl = rv_ddl && | extend { to_lower( lv_field ) } :|. rv_ddl = rv_ddl && serialize_value_help( iv_fieldname = lv_field is_data = is_data ). ENDIF. ENDLOOP. REPLACE ALL OCCURRENCES OF |\n | IN rv_ddl WITH |\n |. ENDMETHOD. METHOD serialize_field_annotations. DATA ls_dd03p LIKE LINE OF is_data-dd03p. READ TABLE is_data-dd03p INTO ls_dd03p WITH KEY fieldname = iv_fieldname. IF sy-subrc = 0. IF ( ls_dd03p-rollname IS INITIAL AND ls_dd03p-precfield IS INITIAL OR ls_dd03p-comptype = 'R' AND ls_dd03p-reftype = 'B' ) AND ls_dd03p-ddtext IS NOT INITIAL. rv_ddl = rv_ddl && | @EndUserText.label : { escape_string( ls_dd03p-ddtext ) }\n|. ENDIF. IF ls_dd03p-languflag = abap_true. rv_ddl = rv_ddl && | @AbapCatalog.textLanguage\n|. ENDIF. IF ls_dd03p-reftable IS NOT INITIAL AND ls_dd03p-reffield IS NOT INITIAL. * this is not completely correct, it must lookup the type of the field in REFTABLE? IF ls_dd03p-datatype = 'CURR' OR ls_dd03p-reffield = 'WAERS'. rv_ddl = rv_ddl && | @Semantics.amount.currencyCode : '{ to_lower( ls_dd03p-reftable ) }.{ to_lower( ls_dd03p-reffield ) }'\n|. ELSE. rv_ddl = rv_ddl && | @Semantics.quantity.unitOfMeasure : '{ to_lower( ls_dd03p-reftable ) }.{ to_lower( ls_dd03p-reffield ) }'\n|. ENDIF. ENDIF. IF ls_dd03p-rollname IS INITIAL AND ( ls_dd03p-datatype(3) = 'D16' OR ls_dd03p-datatype(3) = 'D34' ). * ls_dd03p-outputstyle rv_ddl = rv_ddl && | @AbapCatalog.decfloat.outputStyle : #NORMAL\n|. ENDIF. ENDIF. ENDMETHOD. METHOD serialize_field_foreign_key. DATA ls_dd08v LIKE LINE OF is_data-dd08v. DATA ls_dd05m LIKE LINE OF is_data-dd05m. DATA lv_pre TYPE string. DATA lv_cardinality TYPE string. READ TABLE is_data-dd08v INTO ls_dd08v WITH KEY fieldname = iv_fieldname. IF sy-subrc <> 0. RETURN. ENDIF. IF ls_dd08v-cardleft = 'C' AND ls_dd08v-card = '1'. lv_cardinality = | [1,0..1] |. ELSEIF ls_dd08v-cardleft = '1' AND ls_dd08v-card = 'C'. lv_cardinality = | [0..1,1] |. ELSEIF ls_dd08v-cardleft = '1' AND ls_dd08v-card = '1'. lv_cardinality = | [1,1] |. ELSEIF ls_dd08v-cardleft = '1' AND ls_dd08v-card = 'N'. lv_cardinality = | [1..*,1] |. ELSEIF ls_dd08v-cardleft = '1' AND ls_dd08v-card = 'CN'. lv_cardinality = | [0..*,1] |. ELSEIF ls_dd08v-cardleft = 'C' AND ls_dd08v-card = 'CN'. lv_cardinality = | [0..*,0..1] |. ELSEIF ls_dd08v-cardleft = 'C' AND ls_dd08v-card = 'C'. lv_cardinality = | [0..1,0..1] |. ELSEIF ls_dd08v-cardleft = 'N' AND ls_dd08v-card = 'N'. lv_cardinality = | [1..*,] |. ELSEIF ls_dd08v-cardleft = 'C' AND ls_dd08v-card = 'N'. lv_cardinality = | [1..*,0..1] |. ELSEIF ls_dd08v-cardleft IS INITIAL OR ls_dd08v-card IS INITIAL. lv_cardinality = | |. ELSE. ASSERT 1 = 'todo'. ENDIF. rv_ddl = rv_ddl && |\n with foreign key{ lv_cardinality }{ to_lower( ls_dd08v-checktable ) }|. * assumption: dd05m table is sorted by PRIMPOS ascending LOOP AT is_data-dd05m INTO ls_dd05m WHERE fieldname = iv_fieldname AND fortable <> '*'. IF lv_pre IS INITIAL. lv_pre = |\n where |. ELSE. lv_pre = |\n and |. ENDIF. IF ls_dd05m-fortable(1) = |'|. rv_ddl = rv_ddl && |{ lv_pre }{ to_lower( ls_dd05m-checkfield ) } = { ls_dd05m-fortable }|. ELSE. rv_ddl = rv_ddl && |{ lv_pre }{ to_lower( ls_dd05m-checkfield ) } = { to_lower( ls_dd05m-fortable ) }.{ to_lower( ls_dd05m-forkey ) }|. ENDIF. ENDLOOP. ENDMETHOD. METHOD serialize_fkey_annotations. DATA ls_dd08v LIKE LINE OF is_data-dd08v. READ TABLE is_data-dd08v INTO ls_dd08v WITH KEY fieldname = iv_fieldname. IF sy-subrc = 0. IF ls_dd08v-ddtext IS NOT INITIAL. rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.label : { escape_string( ls_dd08v-ddtext ) }\n|. ENDIF. IF ls_dd08v-frkart IS NOT INITIAL. CASE ls_dd08v-frkart. WHEN 'TEXT'. rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.keyType : #TEXT_KEY\n|. WHEN 'REF'. rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.keyType : #NON_KEY\n|. WHEN OTHERS. rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.keyType : #{ ls_dd08v-frkart }\n|. ENDCASE. ENDIF. IF ls_dd08v-checkflag = abap_false OR ls_dd08v-checkflag = 'N'. rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.screenCheck : true\n|. ELSE. rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.screenCheck : false\n|. ENDIF. IF ls_dd08v-arbgb IS NOT INITIAL. rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.messageClass : '{ ls_dd08v-arbgb }'\n|. ENDIF. IF ls_dd08v-msgnr IS NOT INITIAL. rv_ddl = rv_ddl && | @AbapCatalog.foreignKey.messageNumber : '{ ls_dd08v-msgnr }'\n|. ENDIF. ENDIF. ENDMETHOD. METHOD serialize_top. FIELD-SYMBOLS: TYPE c, " ddpk_is_invhash TYPE abap_bool. rv_ddl = rv_ddl && |@EndUserText.label : { escape_string( is_data-dd02v-ddtext ) }\n|. CASE is_data-dd02v-exclass. WHEN '0'. rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #NOT_CLASSIFIED\n|. WHEN '1'. rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE\n|. WHEN '2'. rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #EXTENSIBLE_CHARACTER\n|. WHEN '3'. rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #EXTENSIBLE_CHARACTER_NUMERIC\n|. WHEN '4'. rv_ddl = rv_ddl && |@AbapCatalog.enhancementCategory : #EXTENSIBLE_ANY\n|. WHEN OTHERS. ASSERT 1 = 'todo'. ENDCASE. CASE is_data-dd02v-tabclass. WHEN 'TRANSP'. " doesn't exist on NW < 750 ASSIGN COMPONENT 'IS_GTT' OF STRUCTURE is_data-dd02v TO . IF sy-subrc = 0 AND = abap_true. rv_ddl = rv_ddl && |@AbapCatalog.tableCategory : #GLOBAL_TEMPORARY\n|. ELSE. rv_ddl = rv_ddl && |@AbapCatalog.tableCategory : #TRANSPARENT\n|. ENDIF. WHEN OTHERS. ASSERT 1 = 'todo'. ENDCASE. IF is_data-dd02v-authclass = '01'. rv_ddl = rv_ddl && |@AbapCatalog.activationType : #NAMETAB_GENERATION_OFFLINE\n|. ELSEIF is_data-dd02v-authclass = '02'. rv_ddl = rv_ddl && |@AbapCatalog.activationType : #ADAPT_C_STRUCTURES\n|. ENDIF. rv_ddl = rv_ddl && |@AbapCatalog.deliveryClass : #{ is_data-dd02v-contflag }\n|. IF is_data-dd02v-mainflag = abap_true. rv_ddl = rv_ddl && |@AbapCatalog.dataMaintenance : #ALLOWED\n|. ELSEIF is_data-dd02v-mainflag = 'N'. rv_ddl = rv_ddl && |@AbapCatalog.dataMaintenance : #NOT_ALLOWED\n|. ELSEIF is_data-dd02v-mainflag IS INITIAL. rv_ddl = rv_ddl && |@AbapCatalog.dataMaintenance : #LIMITED\n|. ELSE. rv_ddl = rv_ddl && |@AbapCatalog.dataMaintenance : \n|. ENDIF. " doesn't exist on NW <= 750 ASSIGN COMPONENT 'PK_IS_INVHASH' OF STRUCTURE is_data-dd02v TO . IF sy-subrc = 0 AND = abap_true. rv_ddl = rv_ddl && |@AbapCatalog.primaryKey.invertedHashIndex : true\n|. ENDIF. ENDMETHOD. METHOD serialize_type. DATA lv_notnull TYPE string. DATA lv_leng TYPE i. DATA lv_decimals TYPE i. IF is_dd03p-notnull = abap_true. lv_notnull = | not null|. ENDIF. IF is_dd03p-rollname IS NOT INITIAL. rv_type = |{ to_lower( is_dd03p-rollname ) }{ lv_notnull }|. ELSE. lv_leng = is_dd03p-leng. lv_decimals = is_dd03p-decimals. CASE is_dd03p-datatype. WHEN 'STRG'. rv_type = |abap.string({ lv_leng }){ lv_notnull }|. WHEN 'RSTR'. rv_type = |abap.rawstring({ lv_leng }){ lv_notnull }|. WHEN 'INT4'. rv_type = |abap.int4{ lv_notnull }|. WHEN 'ACCP'. rv_type = |abap.accp{ lv_notnull }|. WHEN 'LANG'. rv_type = |abap.lang{ lv_notnull }|. WHEN 'DATN'. rv_type = |abap.datn{ lv_notnull }|. WHEN 'TIMN'. rv_type = |abap.timn{ lv_notnull }|. WHEN 'UTCL'. rv_type = |abap.utcl{ lv_notnull }|. WHEN 'INT8'. rv_type = |abap.int8{ lv_notnull }|. WHEN 'D16D'. rv_type = |abap.df16_dec({ lv_leng },{ lv_decimals }){ lv_notnull }|. WHEN 'D16R'. rv_type = |abap.df16_raw{ lv_notnull }|. WHEN 'D16S'. rv_type = |abap.df16_scl{ lv_notnull }|. WHEN 'D16N'. rv_type = |abap.d16n{ lv_notnull }|. WHEN 'D34S'. rv_type = |abap.df34_scl{ lv_notnull }|. WHEN 'D34D'. rv_type = |abap.df34_dec({ lv_leng },{ lv_decimals }){ lv_notnull }|. WHEN 'D34R'. rv_type = |abap.df34_raw{ lv_notnull }|. WHEN 'D34N'. rv_type = |abap.d34n{ lv_notnull }|. WHEN 'INT2'. rv_type = |abap.int2{ lv_notnull }|. WHEN 'INT1'. rv_type = |abap.int1{ lv_notnull }|. WHEN 'CUKY'. rv_type = |abap.cuky{ lv_notnull }|. WHEN 'DATS'. rv_type = |abap.dats{ lv_notnull }|. WHEN 'TIMS'. rv_type = |abap.tims{ lv_notnull }|. WHEN 'FLTP'. rv_type = |abap.fltp{ lv_notnull }|. WHEN 'CLNT'. rv_type = |abap.clnt{ lv_notnull }|. WHEN 'SSTR'. rv_type = |abap.sstring({ lv_leng }){ lv_notnull }|. WHEN 'QUAN'. rv_type = |abap.quan({ lv_leng },{ lv_decimals }){ lv_notnull }|. WHEN 'CURR'. rv_type = |abap.curr({ lv_leng },{ lv_decimals }){ lv_notnull }|. WHEN 'DEC'. rv_type = |abap.dec({ lv_leng },{ lv_decimals }){ lv_notnull }|. WHEN OTHERS. rv_type = |abap.{ to_lower( is_dd03p-datatype ) }({ lv_leng }){ lv_notnull }|. ENDCASE. ENDIF. ENDMETHOD. METHOD serialize_value_help. DATA ls_dd35v LIKE LINE OF is_data-dd35v. DATA ls_dd36m LIKE LINE OF is_data-dd36m. DATA lv_pre TYPE string. READ TABLE is_data-dd35v INTO ls_dd35v WITH KEY fieldname = iv_fieldname. IF sy-subrc <> 0. RETURN. ENDIF. rv_ddl = rv_ddl && |\n with value help { to_lower( ls_dd35v-shlpname ) }|. LOOP AT is_data-dd36m INTO ls_dd36m WHERE fieldname = iv_fieldname AND shlpname = ls_dd35v-shlpname AND shtype <> 'G'. IF lv_pre IS INITIAL. lv_pre = |\n where |. ELSE. lv_pre = |\n and |. ENDIF. IF ls_dd36m-shtype = 'C'. rv_ddl = rv_ddl && |{ lv_pre }{ to_lower( ls_dd36m-shlpfield ) } = { ls_dd36m-shtable }|. ELSE. rv_ddl = rv_ddl && |{ lv_pre }{ to_lower( ls_dd36m-shlpfield ) } = { to_lower( ls_dd36m-shtable ) }.{ to_lower( ls_dd36m-shfield ) }|. ENDIF. ENDLOOP. ENDMETHOD. METHOD unescape_string. rv_string = iv_string. REPLACE FIRST OCCURRENCE OF REGEX |^'| IN rv_string WITH ||. REPLACE FIRST OCCURRENCE OF REGEX |'$| IN rv_string WITH ||. REPLACE ALL OCCURRENCES OF |''| IN rv_string WITH |'|. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_TABL_COMPAR IMPLEMENTATION. METHOD constructor. mi_local = ii_local. ENDMETHOD. METHOD get_where_used_recursive. DATA: lt_findstrings TYPE string_table, lt_founds TYPE STANDARD TABLE OF rsfindlst, lt_scope TYPE ty_seu_obj, lv_findstring LIKE LINE OF lt_findstrings. FIELD-SYMBOLS: TYPE rsfindlst. IF iv_object_name IS INITIAL. RETURN. ENDIF. lt_scope = it_scope. lv_findstring = iv_object_name. INSERT lv_findstring INTO TABLE lt_findstrings. DO iv_depth TIMES. CLEAR: lt_founds. CALL FUNCTION 'RS_EU_CROSSREF' EXPORTING i_find_obj_cls = iv_object_type no_dialog = 'X' TABLES i_findstrings = lt_findstrings o_founds = lt_founds i_scope_object_cls = lt_scope EXCEPTIONS not_executed = 1 not_found = 2 illegal_object = 3 no_cross_for_this_object = 4 batch = 5 batchjob_error = 6 wrong_type = 7 object_not_exist = 8 OTHERS = 9. IF sy-subrc = 1 OR sy-subrc = 2 OR lines( lt_founds ) = 0. EXIT. ELSEIF sy-subrc > 2. zcx_abapgit_exception=>raise_t100( ). ENDIF. INSERT LINES OF lt_founds INTO TABLE rt_founds_all. CLEAR: lt_findstrings. LOOP AT lt_founds ASSIGNING . lv_findstring = -object. INSERT lv_findstring INTO TABLE lt_findstrings. ENDLOOP. ENDDO. ENDMETHOD. METHOD is_structure_used_in_db_table. DATA: lt_scope TYPE ty_seu_obj, lt_founds TYPE ty_founds. APPEND 'TABL' TO lt_scope. APPEND 'STRU' TO lt_scope. lt_founds = get_where_used_recursive( iv_object_name = iv_object_name iv_object_type = 'STRU' it_scope = lt_scope iv_depth = 5 ). DELETE lt_founds WHERE object_cls <> 'DT'. rv_is_structure_used_in_db_tab = boolc( lines( lt_founds ) > 0 ). ENDMETHOD. METHOD validate. DATA: lt_previous_table_fields TYPE TABLE OF dd03p, ls_previous_table_field LIKE LINE OF lt_previous_table_fields, lt_current_table_fields TYPE TABLE OF dd03p, ls_current_table_field LIKE LINE OF lt_current_table_fields, ls_dd02v TYPE dd02v, ls_item TYPE zif_abapgit_definitions=>ty_item, lv_inconsistent TYPE abap_bool. FIELD-SYMBOLS TYPE abap_bool. ii_remote_version->read( EXPORTING iv_name = 'DD02V' CHANGING cg_data = ls_dd02v ). " We only want to compare transparent tables, or structures used in transparent tables IF ls_dd02v-tabclass <> 'TRANSP' AND is_structure_used_in_db_table( ls_dd02v-tabname ) = abap_false. RETURN. ENDIF. " No comparison for global temporary tables ASSIGN COMPONENT 'IS_GTT' OF STRUCTURE ls_dd02v TO . IF sy-subrc = 0 AND = abap_true. RETURN. ENDIF. ii_remote_version->read( EXPORTING iv_name = 'DD03P_TABLE' CHANGING cg_data = lt_previous_table_fields ). ii_local_version->read( EXPORTING iv_name = 'DD03P_TABLE' CHANGING 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. READ TABLE lt_current_table_fields WITH KEY fieldname = ls_previous_table_field-fieldname INTO ls_current_table_field. IF sy-subrc = 0. IF ls_current_table_field-rollname <> ls_previous_table_field-rollname. IF ls_current_table_field-rollname IS NOT INITIAL AND ls_previous_table_field-rollname IS NOT INITIAL. ii_log->add_info( iv_msg = |Field { ls_previous_table_field-fieldname }: | & |Data element changed from { ls_previous_table_field-rollname } | & |to { ls_current_table_field-rollname }| is_item = ls_item ). ELSEIF ls_current_table_field-rollname IS NOT INITIAL. ii_log->add_info( iv_msg = |Field { ls_previous_table_field-fieldname }: | & |Data type changed from internal type | & |{ ls_previous_table_field-inttype }(length { ls_previous_table_field-intlen }) | & |to data element { ls_current_table_field-rollname }| is_item = ls_item ). ELSEIF ls_previous_table_field-rollname IS NOT INITIAL. ii_log->add_info( iv_msg = |Field { ls_previous_table_field-fieldname }: | & |Data type changed from date element { ls_previous_table_field-rollname } | & |to internal type | & |{ ls_current_table_field-inttype }(length { ls_current_table_field-intlen })| is_item = ls_item ). ENDIF. "TODO: perform several other checks, e.g. field length truncated, ... lv_inconsistent = abap_true. ENDIF. ELSE. ii_log->add_info( iv_msg = |Field { ls_previous_table_field-fieldname } removed| is_item = ls_item ). lv_inconsistent = abap_true. ENDIF. 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. rv_message = |Database Table { ls_dd02v-tabname }: { rv_message }|. ENDIF. ENDMETHOD. METHOD zif_abapgit_comparator~compare. rs_result-text = validate( ii_remote_version = ii_remote ii_local_version = mi_local ii_log = ii_log ). ENDMETHOD. ENDCLASS. CLASS kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb DEFINITION DEFERRED. * renamed: zcl_abapgit_object_tabl :: lcl_tabl_xml CLASS kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS add IMPORTING io_xml TYPE REF TO zif_abapgit_xml_output is_internal TYPE zif_abapgit_object_tabl=>ty_internal RAISING zcx_abapgit_exception. CLASS-METHODS read IMPORTING io_xml TYPE REF TO zif_abapgit_xml_input RETURNING VALUE(rs_internal) TYPE zif_abapgit_object_tabl=>ty_internal RAISING zcx_abapgit_exception. ENDCLASS. CLASS kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb IMPLEMENTATION. METHOD add. * adding to xml must be done in the right sequence to avoid changes io_xml->add( iv_name = 'DD02V' ig_data = is_internal-dd02v ). IF NOT is_internal-dd09l IS INITIAL. io_xml->add( iv_name = 'DD09L' ig_data = is_internal-dd09l ). ENDIF. io_xml->add( iv_name = 'DD03P_TABLE' ig_data = is_internal-dd03p ). io_xml->add( iv_name = 'DD05M_TABLE' ig_data = is_internal-dd05m ). io_xml->add( iv_name = 'DD08V_TABLE' ig_data = is_internal-dd08v ). io_xml->add( iv_name = 'DD12V' ig_data = is_internal-dd12v ). io_xml->add( iv_name = 'DD17V' ig_data = is_internal-dd17v ). io_xml->add( iv_name = 'DD35V_TALE' ig_data = is_internal-dd35v ). io_xml->add( iv_name = 'DD36M' ig_data = is_internal-dd36m ). IF lines( is_internal-i18n_langs ) > 0. io_xml->add( iv_name = 'I18N_LANGS' ig_data = is_internal-i18n_langs ). io_xml->add( iv_name = 'DD02_TEXTS' ig_data = is_internal-dd02_texts ). ENDIF. io_xml->add( iv_name = 'LONGTEXTS' ig_data = is_internal-longtexts ). io_xml->add( iv_name = zif_abapgit_object_tabl=>c_s_dataname-segment_definition ig_data = is_internal-segment_definitions ). io_xml->add( iv_name = zif_abapgit_object_tabl=>c_s_dataname-tabl_extras ig_data = is_internal-extras ). ENDMETHOD. METHOD read. io_xml->read( EXPORTING iv_name = zif_abapgit_object_tabl=>c_s_dataname-segment_definition CHANGING cg_data = rs_internal-segment_definitions ). io_xml->read( EXPORTING iv_name = 'DD02V' CHANGING cg_data = rs_internal-dd02v ). io_xml->read( EXPORTING iv_name = 'DD09L' CHANGING cg_data = rs_internal-dd09l ). io_xml->read( EXPORTING iv_name = 'DD03P_TABLE' CHANGING cg_data = rs_internal-dd03p ). io_xml->read( EXPORTING iv_name = 'DD05M_TABLE' CHANGING cg_data = rs_internal-dd05m ). io_xml->read( EXPORTING iv_name = 'DD08V_TABLE' CHANGING cg_data = rs_internal-dd08v ). io_xml->read( EXPORTING iv_name = 'DD35V_TALE' CHANGING cg_data = rs_internal-dd35v ). io_xml->read( EXPORTING iv_name = 'DD36M' CHANGING cg_data = rs_internal-dd36m ). io_xml->read( EXPORTING iv_name = zif_abapgit_object_tabl=>c_s_dataname-tabl_extras CHANGING cg_data = rs_internal-extras ). io_xml->read( EXPORTING iv_name = 'DD12V' CHANGING cg_data = rs_internal-dd12v ). io_xml->read( EXPORTING iv_name = 'DD17V' CHANGING cg_data = rs_internal-dd17v ). io_xml->read( EXPORTING iv_name = 'I18N_LANGS' CHANGING cg_data = rs_internal-i18n_langs ). io_xml->read( EXPORTING iv_name = 'DD02_TEXTS' CHANGING cg_data = rs_internal-dd02_texts ). io_xml->read( EXPORTING iv_name = 'LONGTEXTS' CHANGING cg_data = rs_internal-longtexts ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_tabl IMPLEMENTATION. METHOD clear_dd03p_fields. CONSTANTS lc_comptype_dataelement TYPE comptype VALUE 'E'. DATA: lv_masklen TYPE c LENGTH 4. FIELD-SYMBOLS: TYPE dd03p. * remove nested structures DELETE ct_dd03p WHERE depth <> '00'. * remove fields from .INCLUDEs DELETE ct_dd03p WHERE adminfield <> '0'. LOOP AT ct_dd03p ASSIGNING WHERE NOT rollname IS INITIAL. clear_dd03p_fields_common( CHANGING cs_dd03p = ). lv_masklen = -masklen. IF lv_masklen = '' OR NOT lv_masklen CO '0123456789'. * make sure the field contains valid data, or the XML will dump CLEAR -masklen. ENDIF. IF -comptype = lc_comptype_dataelement. clear_dd03p_fields_dataelement( CHANGING cs_dd03p = ). ENDIF. IF -shlporigin = 'D'. * search help from domain CLEAR: -shlpfield, -shlpname. ENDIF. * XML output assumes correct field content IF -routputlen = ' '. CLEAR -routputlen. ENDIF. ENDLOOP. " Clear position to avoid issues with include structures that contain different number of fields LOOP AT ct_dd03p ASSIGNING . CLEAR: -position, -tabname, -ddlanguage. ENDLOOP. ENDMETHOD. METHOD clear_dd03p_fields_common. CLEAR: cs_dd03p-ddlanguage, cs_dd03p-dtelmaster, cs_dd03p-logflag, cs_dd03p-ddtext, cs_dd03p-reservedte, cs_dd03p-reptext, cs_dd03p-scrtext_s, cs_dd03p-scrtext_m, cs_dd03p-scrtext_l. ENDMETHOD. METHOD clear_dd03p_fields_dataelement. * type specified via data element CLEAR: cs_dd03p-domname, cs_dd03p-inttype, cs_dd03p-intlen, cs_dd03p-mask, cs_dd03p-memoryid, cs_dd03p-headlen, cs_dd03p-scrlen1, cs_dd03p-scrlen2, cs_dd03p-scrlen3, cs_dd03p-datatype, cs_dd03p-leng, cs_dd03p-outputlen, cs_dd03p-deffdname, cs_dd03p-convexit, cs_dd03p-entitytab, cs_dd03p-dommaster, cs_dd03p-domname3l, cs_dd03p-decimals, cs_dd03p-lowercase, cs_dd03p-signflag. ENDMETHOD. METHOD delete_extras. DELETE FROM tddat WHERE tabname = iv_tabname. ENDMETHOD. METHOD delete_idoc_segment. DATA lv_segment_type TYPE edilsegtyp. DATA lv_result LIKE sy-subrc. IF is_idoc_segment( ) = abap_false. rv_deleted = abap_false. RETURN. "previous XML version or no IDoc segment ENDIF. rv_deleted = abap_true. lv_segment_type = ms_item-obj_name. CALL FUNCTION 'SEGMENT_DELETE' EXPORTING segmenttyp = lv_segment_type IMPORTING result = lv_result EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0 OR lv_result <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD deserialize_idoc_segment. DATA lv_result LIKE sy-subrc. DATA lv_package TYPE devclass. DATA lv_uname TYPE sy-uname. DATA lv_transport TYPE trkorr. DATA ls_edisdef TYPE edisdef. DATA ls_segment_definition TYPE zif_abapgit_object_tabl=>ty_segment_definition. FIELD-SYMBOLS TYPE zif_abapgit_object_tabl=>ty_segment_definition. rv_deserialized = abap_false. IF lines( is_internal-segment_definitions ) = 0. RETURN. "no IDoc segment ENDIF. rv_deserialized = abap_true. lv_package = iv_package. lv_transport = iv_transport. LOOP AT is_internal-segment_definitions ASSIGNING . ls_segment_definition = . ls_segment_definition-segmentheader-presp = sy-uname. ls_segment_definition-segmentheader-pwork = sy-uname. CALL FUNCTION 'SEGMENT_READ' EXPORTING segmenttyp = ls_segment_definition-segmentdefinition-segtyp IMPORTING result = lv_result EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0 OR lv_result <> 0. CALL FUNCTION 'SEGMENT_CREATE' IMPORTING segmentdefinition = ls_segment_definition-segmentdefinition TABLES segmentstructure = ls_segment_definition-segmentstructures CHANGING segmentheader = ls_segment_definition-segmentheader devclass = lv_package EXCEPTIONS OTHERS = 1. ELSE. CALL FUNCTION 'SEGMENT_MODIFY' CHANGING segmentheader = ls_segment_definition-segmentheader devclass = lv_package EXCEPTIONS OTHERS = 1. IF sy-subrc = 0. CALL FUNCTION 'SEGMENTDEFINITION_MODIFY' TABLES segmentstructure = ls_segment_definition-segmentstructures CHANGING segmentdefinition = ls_segment_definition-segmentdefinition EXCEPTIONS OTHERS = 1. ENDIF. ENDIF. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. " Check status of segment as stored in repo (field-symbol) IF -segmentdefinition-closed = abap_true. IF lv_transport IS NOT INITIAL. CALL FUNCTION 'SEGMENTDEFINITION_CLOSE' EXPORTING segmenttyp = ls_segment_definition-segmentdefinition-segtyp CHANGING order = lv_transport EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. " SEGMENTDEFINITION_CLOSE saves current release but it should be same as in repo SELECT SINGLE * FROM edisdef INTO ls_edisdef WHERE segtyp = ls_segment_definition-segmentdefinition-segtyp AND version = ls_segment_definition-segmentdefinition-version. ls_edisdef-released = -segmentdefinition-released. ls_edisdef-applrel = -segmentdefinition-applrel. ls_edisdef-closed = -segmentdefinition-closed. UPDATE edisdef FROM ls_edisdef. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error updating IDOC segment { ls_segment_definition-segmentdefinition-segtyp }| ). ENDIF. ENDIF. ENDLOOP. lv_uname = sy-uname. CALL FUNCTION 'TR_TADIR_INTERFACE' EXPORTING wi_test_modus = abap_false wi_tadir_pgmid = 'R3TR' wi_tadir_object = ms_item-obj_type wi_tadir_obj_name = ms_item-obj_name wi_tadir_author = lv_uname wi_tadir_devclass = iv_package wi_tadir_masterlang = mv_language iv_set_edtflag = abap_true iv_delflag = abap_false EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD deserialize_indexes. DATA: lv_name TYPE ddobjname, lv_subrc TYPE sy-subrc, lt_dd12v_db LIKE is_internal-dd12v, ls_dd12v LIKE LINE OF is_internal-dd12v, ls_dd17v LIKE LINE OF is_internal-dd17v, lt_secondary LIKE is_internal-dd17v. lv_name = ms_item-obj_name. " Get existing indexes and drop the ones that are not included in remote CALL FUNCTION 'DDIF_TABL_GET' EXPORTING name = lv_name langu = mv_language TABLES dd12v_tab = lt_dd12v_db EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from DDIF_TABL_GET' ). ENDIF. LOOP AT lt_dd12v_db INTO ls_dd12v. READ TABLE is_internal-dd12v TRANSPORTING NO FIELDS WITH KEY sqltab = ls_dd12v-sqltab indexname = ls_dd12v-indexname. IF sy-subrc <> 0. CALL FUNCTION 'DD_INDX_DEL' EXPORTING sqltab = ls_dd12v-sqltab indexname = ls_dd12v-indexname del_state = 'M' "all states IMPORTING rc = lv_subrc. IF lv_subrc <> 0. zcx_abapgit_exception=>raise( |Error deleting index { ls_dd12v-sqltab }~{ ls_dd12v-indexname }| ). ENDIF. ENDIF. ENDLOOP. " Create new or update existing indexes LOOP AT is_internal-dd12v INTO ls_dd12v. CLEAR lt_secondary. LOOP AT is_internal-dd17v INTO ls_dd17v WHERE sqltab = ls_dd12v-sqltab AND indexname = ls_dd12v-indexname. APPEND ls_dd17v TO lt_secondary. ENDLOOP. CALL FUNCTION 'DDIF_INDX_PUT' EXPORTING name = ls_dd12v-sqltab id = ls_dd12v-indexname dd12v_wa = ls_dd12v TABLES dd17v_tab = lt_secondary EXCEPTIONS indx_not_found = 1 name_inconsistent = 2 indx_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. " Secondary indexes are automatically activated as part of R3TR TABL " So there's no need to add them to activation queue ENDLOOP. ENDMETHOD. METHOD deserialize_texts. DATA: lv_name TYPE ddobjname, ls_dd02v_tmp TYPE dd02v. FIELD-SYMBOLS: LIKE LINE OF cs_internal-i18n_langs, LIKE LINE OF cs_internal-dd02_texts. lv_name = ms_item-obj_name. mo_i18n_params->trim_saplang_list( CHANGING ct_sap_langs = cs_internal-i18n_langs ). SORT cs_internal-i18n_langs. SORT cs_internal-dd02_texts BY ddlanguage. " Optimization LOOP AT cs_internal-i18n_langs ASSIGNING . " Table description ls_dd02v_tmp = cs_internal-dd02v. READ TABLE cs_internal-dd02_texts ASSIGNING WITH KEY ddlanguage = . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |DD02_TEXTS cannot find lang { } in XML| ). ENDIF. MOVE-CORRESPONDING TO ls_dd02v_tmp. CALL FUNCTION 'DDIF_TABL_PUT' EXPORTING name = lv_name dd02v_wa = ls_dd02v_tmp EXCEPTIONS tabl_not_found = 1 name_inconsistent = 2 tabl_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD is_db_table_category. " values from domain TABCLASS rv_is_db_table_type = boolc( iv_tabclass = 'TRANSP' OR iv_tabclass = 'CLUSTER' OR iv_tabclass = 'POOL' ). ENDMETHOD. METHOD is_idoc_segment. DATA lv_segment_type TYPE edilsegtyp. lv_segment_type = ms_item-obj_name. SELECT SINGLE segtyp FROM edisegment INTO lv_segment_type WHERE segtyp = lv_segment_type. rv_is_idoc_segment = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD read_extras. SELECT SINGLE * FROM tddat INTO rs_tabl_extras-tddat WHERE tabname = iv_tabname. ENDMETHOD. METHOD serialize_idoc_segment. DATA lv_segment_type TYPE edilsegtyp. DATA lv_result LIKE sy-subrc. DATA lv_devclass TYPE devclass. DATA lt_segmentdefinitions TYPE STANDARD TABLE OF edisegmdef. DATA ls_segment_definition TYPE zif_abapgit_object_tabl=>ty_segment_definition. FIELD-SYMBOLS: TYPE edisegmdef. IF is_idoc_segment( ) = abap_false. RETURN. ENDIF. lv_segment_type = ms_item-obj_name. CALL FUNCTION 'SEGMENT_READ' EXPORTING segmenttyp = lv_segment_type IMPORTING result = lv_result TABLES segmentdefinition = lt_segmentdefinitions EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0 OR lv_result <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. LOOP AT lt_segmentdefinitions ASSIGNING . CLEAR ls_segment_definition. CALL FUNCTION 'SEGMENTDEFINITION_READ' EXPORTING segmenttyp = -segtyp IMPORTING result = lv_result devclass = lv_devclass segmentheader = ls_segment_definition-segmentheader segmentdefinition = ls_segment_definition-segmentdefinition TABLES segmentstructure = ls_segment_definition-segmentstructures CHANGING version = -version EXCEPTIONS no_authority = 1 segment_not_existing = 2 OTHERS = 3. IF sy-subrc <> 0 OR lv_result <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_object_idoc=>clear_idoc_segement_fields( CHANGING cg_structure = ls_segment_definition-segmentdefinition ). zcl_abapgit_object_idoc=>clear_idoc_segement_fields( CHANGING cg_structure = ls_segment_definition-segmentheader ). APPEND ls_segment_definition TO cs_internal-segment_definitions. ENDLOOP. ENDMETHOD. METHOD serialize_texts. DATA: lv_name TYPE ddobjname, lv_index TYPE i, ls_dd02v TYPE dd02v, lt_language_filter TYPE zif_abapgit_environment=>ty_system_language_filter. FIELD-SYMBOLS: LIKE LINE OF cs_internal-i18n_langs, LIKE LINE OF cs_internal-dd02_texts. IF mo_i18n_params->ms_params-main_language_only = abap_true. RETURN. ENDIF. lv_name = ms_item-obj_name. " Collect additional languages, skip main lang - it was serialized already lt_language_filter = mo_i18n_params->build_language_filter( ). SELECT DISTINCT ddlanguage AS langu INTO TABLE cs_internal-i18n_langs FROM dd02v WHERE tabname = lv_name AND ddlanguage IN lt_language_filter AND ddlanguage <> mv_language ORDER BY langu. "#EC CI_SUBRC LOOP AT cs_internal-i18n_langs ASSIGNING . lv_index = sy-tabix. CALL FUNCTION 'DDIF_TABL_GET' EXPORTING name = lv_name langu = IMPORTING dd02v_wa = ls_dd02v EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0 OR ls_dd02v-ddlanguage IS INITIAL. DELETE cs_internal-i18n_langs INDEX lv_index. " Don't save this lang CONTINUE. ENDIF. APPEND INITIAL LINE TO cs_internal-dd02_texts ASSIGNING . MOVE-CORRESPONDING ls_dd02v TO . ENDLOOP. SORT cs_internal-i18n_langs ASCENDING. SORT cs_internal-dd02_texts BY ddlanguage ASCENDING. ENDMETHOD. METHOD update_extras. IF is_tabl_extras-tddat IS INITIAL. delete_extras( iv_tabname ). ELSE. MODIFY tddat FROM is_tabl_extras-tddat. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~changed_by. TYPES: BEGIN OF ty_data, as4user TYPE dd02l-as4user, as4date TYPE dd02l-as4date, as4time TYPE dd02l-as4time, END OF ty_data. DATA: lt_data TYPE STANDARD TABLE OF ty_data WITH DEFAULT KEY, ls_data LIKE LINE OF lt_data. SELECT as4user as4date as4time FROM dd02l INTO TABLE lt_data WHERE tabname = ms_item-obj_name AND as4local = 'A' AND as4vers = '0000' ORDER BY PRIMARY KEY. SELECT as4user as4date as4time APPENDING TABLE lt_data FROM dd09l WHERE tabname = ms_item-obj_name AND as4local = 'A' AND as4vers = '0000' ORDER BY PRIMARY KEY. SELECT as4user as4date as4time APPENDING TABLE lt_data FROM dd12l WHERE sqltab = ms_item-obj_name AND as4local = 'A' AND as4vers = '0000' ORDER BY PRIMARY KEY. SORT lt_data BY as4date DESCENDING as4time DESCENDING. READ TABLE lt_data INDEX 1 INTO ls_data. IF sy-subrc = 0. rv_user = ls_data-as4user. ELSE. rv_user = c_user_unknown. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lv_objname TYPE rsedd0-ddobjname, lv_no_ask TYPE abap_bool, lv_subrc TYPE sy-subrc, BEGIN OF ls_dd02l, tabname TYPE dd02l-tabname, tabclass TYPE dd02l-tabclass, sqltab TYPE dd02l-sqltab, END OF ls_dd02l. IF zif_abapgit_object~exists( ) = abap_false. " Proxies e.g. delete on its own, nothing todo here then. RETURN. ENDIF. lv_objname = ms_item-obj_name. IF delete_idoc_segment( ) = abap_false. lv_no_ask = abap_true. SELECT SINGLE tabname tabclass sqltab FROM dd02l INTO CORRESPONDING FIELDS OF ls_dd02l WHERE tabname = ms_item-obj_name AND as4local = 'A' AND as4vers = '0000'. IF sy-subrc = 0 AND is_db_table_category( ls_dd02l-tabclass ) = abap_true. CALL FUNCTION 'DD_EXISTS_DATA' EXPORTING reftab = ls_dd02l-sqltab tabclass = ls_dd02l-tabclass tabname = ls_dd02l-tabname IMPORTING subrc = lv_subrc EXCEPTIONS missing_reftab = 1 sql_error = 2 buffer_overflow = 3 unknown_error = 4 OTHERS = 5. IF sy-subrc = 0 AND lv_subrc = 0. lv_no_ask = abap_false. ENDIF. ENDIF. delete_ddic( iv_objtype = 'T' iv_no_ask = lv_no_ask ). delete_longtexts( c_longtext_id_tabl ). delete_extras( lv_objname ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lv_name TYPE ddobjname, ls_internal TYPE zif_abapgit_object_tabl=>ty_internal. FIELD-SYMBOLS: TYPE dd03p, TYPE dd05m, TYPE dd08v, TYPE dd35v, TYPE dd36m, TYPE any. lv_name = ms_item-obj_name. " type conversion ls_internal = kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb=>read( io_xml ). IF deserialize_idoc_segment( is_internal = ls_internal iv_transport = iv_transport iv_package = iv_package ) = abap_false. ASSIGN COMPONENT 'ROWORCOLST' OF STRUCTURE ls_internal-dd09l TO . IF sy-subrc = 0 AND IS INITIAL. = 'C'. "Reverse fix from serialize ENDIF. " Number fields sequentially and fill table name LOOP AT ls_internal-dd03p ASSIGNING . -position = sy-tabix. -tabname = lv_name. -ddlanguage = mv_language. ENDLOOP. LOOP AT ls_internal-dd05m ASSIGNING . -tabname = lv_name. ENDLOOP. LOOP AT ls_internal-dd08v ASSIGNING . -tabname = lv_name. -ddlanguage = mv_language. ENDLOOP. LOOP AT ls_internal-dd35v ASSIGNING . -tabname = lv_name. ENDLOOP. LOOP AT ls_internal-dd36m ASSIGNING . -tabname = lv_name. ENDLOOP. corr_insert( iv_package = iv_package ig_object_class = 'DICT' ). CALL FUNCTION 'DD_TABL_EXPAND' EXPORTING dd02v_wa = ls_internal-dd02v TABLES dd03p_tab = ls_internal-dd03p dd05m_tab = ls_internal-dd05m dd08v_tab = ls_internal-dd08v dd35v_tab = ls_internal-dd35v dd36m_tab = ls_internal-dd36m EXCEPTIONS illegal_parameter = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'DDIF_TABL_PUT' EXPORTING name = lv_name dd02v_wa = ls_internal-dd02v dd09l_wa = ls_internal-dd09l TABLES dd03p_tab = ls_internal-dd03p dd05m_tab = ls_internal-dd05m dd08v_tab = ls_internal-dd08v dd35v_tab = ls_internal-dd35v dd36m_tab = ls_internal-dd36m EXCEPTIONS tabl_not_found = 1 name_inconsistent = 2 tabl_inconsistent = 3 put_failure = 4 put_refused = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_objects_activation=>add_item( ms_item ). deserialize_indexes( ls_internal ). IF mo_i18n_params->is_lxe_applicable( ) = abap_false. deserialize_texts( CHANGING cs_internal = ls_internal ). ENDIF. deserialize_longtexts( ii_xml = io_xml iv_longtext_id = c_longtext_id_tabl ). update_extras( iv_tabname = lv_name is_tabl_extras = ls_internal-extras ). ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lv_tabname TYPE dd02l-tabname. lv_tabname = ms_item-obj_name. " Check nametab because it's fast CALL FUNCTION 'DD_GET_NAMETAB_HEADER' EXPORTING tabname = lv_tabname EXCEPTIONS not_found = 1 OTHERS = 2. IF sy-subrc <> 0. " Check for new, inactive, or modified versions that might not be in nametab SELECT SINGLE tabname FROM dd02l INTO lv_tabname WHERE tabname = lv_tabname. "#EC CI_NOORDER ENDIF. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_object~get_comparator. DATA: li_local_version_output TYPE REF TO zif_abapgit_xml_output, 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. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESDICT' iv_argument = |{ ms_item-obj_type }{ ms_item-obj_name }| ). ENDMETHOD. METHOD zif_abapgit_object~jump. " Covered by ZCL_ABAPGIT_OBJECT=>JUMP ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lv_name TYPE ddobjname, lv_state TYPE ddgotstate, ls_internal TYPE zif_abapgit_object_tabl=>ty_internal, lv_index LIKE sy-index. FIELD-SYMBOLS: LIKE LINE OF ls_internal-dd12v, LIKE LINE OF ls_internal-dd05m, LIKE LINE OF ls_internal-dd08v, LIKE LINE OF ls_internal-dd35v, LIKE LINE OF ls_internal-dd36m, TYPE any. lv_name = ms_item-obj_name. CALL FUNCTION 'DDIF_TABL_GET' EXPORTING name = lv_name langu = mv_language IMPORTING gotstate = lv_state dd02v_wa = ls_internal-dd02v dd09l_wa = ls_internal-dd09l TABLES dd03p_tab = ls_internal-dd03p dd05m_tab = ls_internal-dd05m dd08v_tab = ls_internal-dd08v dd12v_tab = ls_internal-dd12v dd17v_tab = ls_internal-dd17v dd35v_tab = ls_internal-dd35v dd36m_tab = ls_internal-dd36m EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from DDIF_TABL_GET' ). ENDIF. " Check if any active version was returned IF lv_state <> 'A'. RETURN. ENDIF. CLEAR: ls_internal-dd02v-as4user, ls_internal-dd02v-as4date, ls_internal-dd02v-as4time. * reset numeric field, so XML does not crash IF ls_internal-dd02v-prozpuff = ''. CLEAR ls_internal-dd02v-prozpuff. ENDIF. IF ls_internal-dd02v-datmin = ''. CLEAR ls_internal-dd02v-datmin. ENDIF. IF ls_internal-dd02v-datmax = ''. CLEAR ls_internal-dd02v-datmax. ENDIF. IF ls_internal-dd02v-datavg = ''. CLEAR ls_internal-dd02v-datavg. ENDIF. CLEAR: ls_internal-dd09l-as4user, ls_internal-dd09l-as4date, ls_internal-dd09l-as4time. ASSIGN COMPONENT 'ROWORCOLST' OF STRUCTURE ls_internal-dd09l TO . IF sy-subrc = 0 AND = 'C'. CLEAR . "To avoid diff errors. This field doesn't exist in all releases ENDIF. LOOP AT ls_internal-dd12v ASSIGNING . CLEAR: -as4user, -as4date, -as4time, -dbindex. ENDLOOP. clear_dd03p_fields( CHANGING ct_dd03p = ls_internal-dd03p ). * remove foreign keys inherited from .INCLUDEs DELETE ls_internal-dd08v WHERE noinherit = 'N'. LOOP AT ls_internal-dd05m ASSIGNING . CLEAR -tabname. CLEAR -leng. lv_index = sy-tabix. READ TABLE ls_internal-dd08v WITH KEY fieldname = -fieldname TRANSPORTING NO FIELDS. IF sy-subrc <> 0. DELETE ls_internal-dd05m INDEX lv_index. ENDIF. ENDLOOP. LOOP AT ls_internal-dd08v ASSIGNING . CLEAR: -tabname, -ddlanguage. ENDLOOP. LOOP AT ls_internal-dd35v ASSIGNING . CLEAR -tabname. ENDLOOP. * remove inherited search helps DELETE ls_internal-dd35v WHERE shlpinher = abap_true. LOOP AT ls_internal-dd36m ASSIGNING . CLEAR -tabname. lv_index = sy-tabix. READ TABLE ls_internal-dd35v WITH KEY fieldname = -fieldname TRANSPORTING NO FIELDS. IF sy-subrc <> 0. DELETE ls_internal-dd36m INDEX lv_index. ENDIF. ENDLOOP. IF mo_i18n_params->is_lxe_applicable( ) = abap_false. serialize_texts( CHANGING cs_internal = ls_internal ). ENDIF. ls_internal-longtexts = zcl_abapgit_factory=>get_longtexts( )->serialize( iv_object_name = ms_item-obj_name iv_longtext_id = c_longtext_id_tabl io_i18n_params = mo_i18n_params ii_xml = io_xml ). serialize_idoc_segment( CHANGING cs_internal = ls_internal ). ls_internal-extras = read_extras( lv_name ). kHGwlQLjNyVXWLuOOyJYhJlIeXZtBb=>add( io_xml = io_xml is_internal = ls_internal ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_sap_report IMPLEMENTATION. METHOD authorization_check. IF is_item IS NOT INITIAL. TRY. CALL FUNCTION 'RS_ACCESS_PERMISSION' EXPORTING mode = iv_mode object = is_item-obj_name object_class = is_item-obj_type suppress_corr_check = abap_true suppress_language_check = abap_true suppress_extend_dialog = abap_true abap_langu_version_upon_insert = is_item-abap_language_version " does not exist on lower releases EXCEPTIONS canceled_in_corr = 1 enqueued_by_user = 2 enqueue_system_failure = 3 illegal_parameter_values = 4 locked_by_author = 5 no_modify_permission = 6 no_show_permission = 7 permission_failure = 8 request_language_denied = 9 OTHERS = 10. CATCH cx_sy_dyn_call_param_not_found. CALL FUNCTION 'RS_ACCESS_PERMISSION' EXPORTING mode = iv_mode object = is_item-obj_name object_class = is_item-obj_type suppress_corr_check = abap_true suppress_language_check = abap_true suppress_extend_dialog = abap_true EXCEPTIONS canceled_in_corr = 1 enqueued_by_user = 2 enqueue_system_failure = 3 illegal_parameter_values = 4 locked_by_author = 5 no_modify_permission = 6 no_show_permission = 7 permission_failure = 8 request_language_denied = 9 OTHERS = 10. ENDTRY. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_sap_report~delete_report. authorization_check( iv_mode = 'DELETE' is_item = is_item ). DELETE REPORT iv_name. IF sy-subrc <> 0 AND iv_raise_error = abap_true. zcx_abapgit_exception=>raise( |Error deleting report { iv_name }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_sap_report~insert_report. ASSERT iv_state CA ' AI'. ASSERT iv_program_type CA ' 1FIJKMST'. authorization_check( iv_mode = 'MODIFY' is_item = is_item ). IF iv_state IS INITIAL. INSERT REPORT iv_name FROM it_source. ELSEIF iv_program_type IS INITIAL AND iv_extension_type IS INITIAL. INSERT REPORT iv_name FROM it_source STATE iv_state. ELSEIF iv_extension_type IS INITIAL. INSERT REPORT iv_name FROM it_source STATE iv_state PROGRAM TYPE iv_program_type. ELSE. INSERT REPORT iv_name FROM it_source STATE iv_state EXTENSION TYPE iv_extension_type PROGRAM TYPE iv_program_type. ENDIF. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error inserting report { iv_name }| ). ENDIF. " In lower releases, INSERT REPORT does not support setting ABAP Language version (VERSION) " Therefore, update the flag directly UPDATE progdir SET uccheck = iv_version WHERE name = iv_name AND state = iv_state. ENDMETHOD. METHOD zif_abapgit_sap_report~read_progdir. DATA ls_sapdir TYPE progdir. CALL FUNCTION 'READ_PROGDIR' EXPORTING i_progname = iv_name i_state = iv_state IMPORTING e_progdir = ls_sapdir EXCEPTIONS not_exists = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. MOVE-CORRESPONDING ls_sapdir TO rs_progdir. CLEAR: rs_progdir-edtx, rs_progdir-cnam, rs_progdir-cdat, rs_progdir-unam, rs_progdir-udat, rs_progdir-levl, rs_progdir-vern, rs_progdir-rmand, rs_progdir-sdate, rs_progdir-stime, rs_progdir-idate, rs_progdir-itime, rs_progdir-varcl, rs_progdir-state. ENDMETHOD. METHOD zif_abapgit_sap_report~read_report. ASSERT iv_state CA ' AI'. authorization_check( iv_mode = 'SHOW' is_item = is_item ). IF iv_state IS INITIAL. READ REPORT iv_name INTO rt_source. ELSE. READ REPORT iv_name INTO rt_source STATE iv_state. ENDIF. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error reading report { iv_name }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_sap_report~update_progdir. DATA ls_progdir_new TYPE progdir. CALL FUNCTION 'READ_PROGDIR' EXPORTING i_progname = is_progdir-name i_state = iv_state IMPORTING e_progdir = ls_progdir_new EXCEPTIONS not_exists = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error reading program directory' ). ENDIF. ls_progdir_new-ldbname = is_progdir-ldbname. ls_progdir_new-dbna = is_progdir-dbna. ls_progdir_new-dbapl = is_progdir-dbapl. ls_progdir_new-rload = is_progdir-rload. ls_progdir_new-fixpt = is_progdir-fixpt. ls_progdir_new-appl = is_progdir-appl. ls_progdir_new-rstat = is_progdir-rstat. ls_progdir_new-uccheck = is_progdir-uccheck. ls_progdir_new-sqlx = is_progdir-sqlx. ls_progdir_new-clas = is_progdir-clas. ls_progdir_new-secu = is_progdir-secu. CALL FUNCTION 'UPDATE_PROGDIR' EXPORTING i_progdir = ls_progdir_new i_progname = ls_progdir_new-name i_state = ls_progdir_new-state EXCEPTIONS not_executed = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error updating program directory' ). ENDIF. " Function UPDATE_PROGDIR does not update VARCL, so we do it here SELECT SINGLE * FROM progdir INTO ls_progdir_new WHERE name = ls_progdir_new-name AND state = ls_progdir_new-state. IF sy-subrc = 0 AND is_progdir-varcl <> ls_progdir_new-varcl. UPDATE progdir SET varcl = is_progdir-varcl WHERE name = ls_progdir_new-name AND state = ls_progdir_new-state. "#EC CI_SUBRC ENDIF. ENDMETHOD. METHOD zif_abapgit_sap_report~update_report. DATA lt_new TYPE string_table. DATA lt_old TYPE string_table. lt_new = it_source. lt_old = zif_abapgit_sap_report~read_report( iv_name ). IF lt_old <> lt_new. zif_abapgit_sap_report~insert_report( iv_name = iv_name it_source = it_source iv_state = iv_state iv_program_type = iv_program_type iv_extension_type = iv_extension_type iv_package = iv_package iv_version = iv_version is_item = is_item ). rv_updated = abap_true. ELSE. rv_updated = abap_false. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_sap_package IMPLEMENTATION. METHOD constructor. mv_package = iv_package. ENDMETHOD. METHOD zif_abapgit_sap_package~are_changes_recorded_in_tr_req. DATA: li_package TYPE REF TO if_package. cl_package_factory=>load_package( EXPORTING i_package_name = mv_package IMPORTING e_package = li_package EXCEPTIONS object_not_existing = 1 unexpected_error = 2 intern_err = 3 no_access = 4 object_locked_and_modified = 5 OTHERS = 6 ). CASE sy-subrc. WHEN 0. rv_are_changes_rec_in_tr_req = li_package->wbo_korr_flag. WHEN 1. " For new packages, derive from package name rv_are_changes_rec_in_tr_req = boolc( mv_package(1) <> '$' AND mv_package(1) <> 'T' ). WHEN OTHERS. zcx_abapgit_exception=>raise_t100( ). ENDCASE. ENDMETHOD. METHOD zif_abapgit_sap_package~create. DATA: lv_err TYPE string, li_package TYPE REF TO if_package, ls_package TYPE scompkdtln. ASSERT NOT is_package-devclass IS INITIAL. cl_package_factory=>load_package( EXPORTING i_package_name = is_package-devclass EXCEPTIONS object_not_existing = 1 unexpected_error = 2 intern_err = 3 no_access = 4 object_locked_and_modified = 5 ). IF sy-subrc = 0. " Package already exists. We assume this is fine. Its properties might be changed later at " DEVC deserialization. RETURN. ENDIF. MOVE-CORRESPONDING is_package TO ls_package. " Set software component to 'HOME' if none is set at this point. " Otherwise SOFTWARE_COMPONENT_INVALID will be raised. IF ls_package-dlvunit IS INITIAL. ls_package-dlvunit = 'HOME'. ENDIF. " For transportable packages, get default transport and layer IF ls_package-devclass(1) <> '$' AND ls_package-pdevclass IS INITIAL. ls_package-pdevclass = get_transport_layer( ). ENDIF. cl_package_factory=>create_new_package( EXPORTING i_reuse_deleted_object = abap_true * i_suppress_dialog = abap_true " does not exist in 730 IMPORTING e_package = li_package CHANGING c_package_data = ls_package EXCEPTIONS object_already_existing = 1 object_just_created = 2 not_authorized = 3 wrong_name_prefix = 4 undefined_name = 5 reserved_local_name = 6 invalid_package_name = 7 short_text_missing = 8 software_component_invalid = 9 layer_invalid = 10 author_not_existing = 11 component_not_existing = 12 component_missing = 13 prefix_in_use = 14 unexpected_error = 15 intern_err = 16 no_access = 17 * invalid_translation_depth = 18 * wrong_mainpack_value = 19 * superpackage_invalid = 20 * error_in_cts_checks = 21 OTHERS = 18 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. li_package->save( * EXPORTING * i_suppress_dialog = abap_true " Controls whether popups can be transmitted EXCEPTIONS object_invalid = 1 object_not_changeable = 2 cancelled_in_corr = 3 permission_failure = 4 unexpected_error = 5 intern_err = 6 OTHERS = 7 ). IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_err. " Here we have to delete the package, " otherwise it would remain in the memory " and cannot created again in this session. li_package->delete( EXCEPTIONS object_not_empty = 1 object_not_changeable = 2 object_invalid = 3 intern_err = 4 OTHERS = 5 ). zcx_abapgit_exception=>raise( lv_err ). ENDIF. li_package->set_changeable( abap_false ). ENDMETHOD. METHOD zif_abapgit_sap_package~create_child. DATA: li_parent TYPE REF TO if_package, ls_child TYPE zif_abapgit_sap_package=>ty_create. cl_package_factory=>load_package( EXPORTING i_package_name = mv_package IMPORTING e_package = li_parent EXCEPTIONS object_not_existing = 1 unexpected_error = 2 intern_err = 3 no_access = 4 object_locked_and_modified = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ls_child-devclass = iv_child. ls_child-dlvunit = li_parent->software_component. ls_child-component = li_parent->application_component. ls_child-ctext = iv_child. ls_child-parentcl = mv_package. ls_child-pdevclass = li_parent->transport_layer. ls_child-as4user = sy-uname. zif_abapgit_sap_package~create( ls_child ). ENDMETHOD. METHOD zif_abapgit_sap_package~create_local. DATA: ls_package TYPE zif_abapgit_sap_package=>ty_create. ls_package-devclass = mv_package. ls_package-ctext = mv_package. ls_package-parentcl = '$TMP'. ls_package-dlvunit = 'LOCAL'. ls_package-as4user = sy-uname. zif_abapgit_sap_package~create( ls_package ). ENDMETHOD. METHOD zif_abapgit_sap_package~exists. cl_package_factory=>load_package( EXPORTING i_package_name = mv_package EXCEPTIONS object_not_existing = 1 unexpected_error = 2 intern_err = 3 no_access = 4 object_locked_and_modified = 5 ). rv_bool = boolc( sy-subrc <> 1 ). ENDMETHOD. METHOD get_transport_layer. " Get default transport layer CALL FUNCTION 'TR_GET_TRANSPORT_TARGET' EXPORTING iv_use_default = abap_true iv_get_layer_only = abap_true IMPORTING ev_layer = rv_transport_layer EXCEPTIONS wrong_call = 1 invalid_input = 2 cts_initialization_failure = 3 OTHERS = 4. IF sy-subrc <> 0. " Return empty layer (i.e. "local workbench request" for the package) CLEAR rv_transport_layer. ENDIF. ENDMETHOD. METHOD zif_abapgit_sap_package~get_transport_type. DATA: lv_pkg_name TYPE e071-obj_name, lv_obj_name TYPE tadir-obj_name, lv_role TYPE trnrole. lv_pkg_name = mv_package. lv_obj_name = mv_package. CALL FUNCTION 'TR_GET_REQUEST_TYPE' EXPORTING iv_pgmid = 'R3TR' iv_object = 'DEVC' iv_obj_name = lv_pkg_name IMPORTING ev_request_type = rs_transport_type-request ev_task_type = rs_transport_type-task EXCEPTIONS no_request_needed = 1 invalid_object = 2 system_error = 3 OTHERS = 4. CASE sy-subrc. WHEN 0 OR 1. RETURN. WHEN 2. " For new packages, set to workbench request rs_transport_type-request = 'K'. CALL FUNCTION 'TR_GET_NAMESPACE_AND_ROLE' EXPORTING iv_pgmid = 'R3TR' iv_object = 'DEVC' iv_objname = lv_obj_name IMPORTING ev_role = lv_role EXCEPTIONS namespace_not_existing = 1 invalid_object = 2 namespace_not_determinable = 3 OTHERS = 4. IF sy-subrc = 0 AND lv_role = 'C'. " Namespace with repair license requires repair task rs_transport_type-task = 'R'. ELSE. " Otherwise use correction task rs_transport_type-task = 'S'. ENDIF. WHEN OTHERS. zcx_abapgit_exception=>raise_t100( ). ENDCASE. ENDMETHOD. METHOD zif_abapgit_sap_package~list_subpackages. DATA: lt_list LIKE rt_list. SELECT devclass FROM tdevc INTO TABLE lt_list WHERE parentcl = mv_package ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF rt_list = lt_list. WHILE lines( lt_list ) > 0. SELECT devclass FROM tdevc INTO TABLE lt_list FOR ALL ENTRIES IN lt_list WHERE parentcl = lt_list-table_line ORDER BY PRIMARY KEY. "#EC CI_SUBRC "#EC CI_GENBUFF APPEND LINES OF lt_list TO rt_list. ENDWHILE. ENDMETHOD. METHOD zif_abapgit_sap_package~list_superpackages. DATA: lt_list LIKE rt_list, lv_parent TYPE tdevc-parentcl. APPEND mv_package TO rt_list. lv_parent = zif_abapgit_sap_package~read_parent( ). IF sy-subrc = 0 AND NOT lv_parent IS INITIAL. lt_list = zcl_abapgit_factory=>get_sap_package( lv_parent )->list_superpackages( ). APPEND LINES OF lt_list TO rt_list. ENDIF. ENDMETHOD. METHOD zif_abapgit_sap_package~read_description. SELECT SINGLE ctext FROM tdevct INTO rv_description WHERE devclass = mv_package AND spras = sy-langu ##SUBRC_OK. ENDMETHOD. METHOD zif_abapgit_sap_package~read_parent. SELECT SINGLE parentcl FROM tdevc INTO rv_parentcl WHERE devclass = mv_package. "#EC CI_GENBUFF IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Inconsistent package structure! Cannot find parent for { mv_package }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_sap_package~read_responsible. SELECT SINGLE as4user FROM tdevc INTO rv_responsible WHERE devclass = mv_package ##SUBRC_OK. "#EC CI_GENBUFF ENDMETHOD. METHOD zif_abapgit_sap_package~validate_name. IF mv_package IS INITIAL. zcx_abapgit_exception=>raise( 'Package name must not be empty' ). ENDIF. IF mv_package = '$TMP'. zcx_abapgit_exception=>raise( 'It is not possible to use $TMP, use a different (local) package' ). ENDIF. " Check if package name is allowed cl_package_helper=>check_package_name( EXPORTING i_package_name = mv_package EXCEPTIONS undefined_name = 1 wrong_name_prefix = 2 reserved_local_name = 3 invalid_package_name = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Package name { mv_package } is not valid| ). ENDIF. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_SAP_NAMESPACE IMPLEMENTATION. METHOD zif_abapgit_sap_namespace~exists. DATA lv_editflag TYPE trnspace-editflag. DATA lo_obj TYPE REF TO object. DATA lo_nsp TYPE REF TO object. FIELD-SYMBOLS TYPE any. TRY. SELECT SINGLE editflag FROM ('TRNSPACE') INTO lv_editflag WHERE namespace = iv_namespace. rv_yes = boolc( sy-subrc = 0 ). CATCH cx_sy_dynamic_osql_error. ASSIGN ('XCO_CP_SYSTEM=>NAMESPACE') TO . lo_obj = . CALL METHOD lo_obj->('IF_XCO_CP_NAMESPACE_FACTORY~FOR') EXPORTING iv_value = iv_namespace RECEIVING ro_namespace = lo_nsp. CALL METHOD lo_nsp->('IF_XCO_CP_NAMESPACE~EXISTS') RECEIVING rv_exists = rv_yes. ENDTRY. ENDMETHOD. METHOD zif_abapgit_sap_namespace~is_editable. DATA lv_editflag TYPE trnspace-editflag. DATA lo_obj TYPE REF TO object. DATA lo_nsp TYPE REF TO object. FIELD-SYMBOLS TYPE any. TRY. SELECT SINGLE editflag FROM ('TRNSPACE') INTO lv_editflag WHERE namespace = iv_namespace. rv_yes = boolc( sy-subrc = 0 AND lv_editflag = 'X' ). CATCH cx_sy_dynamic_osql_error. ASSIGN ('XCO_CP_SYSTEM=>NAMESPACE') TO . lo_obj = . CALL METHOD lo_obj->('IF_XCO_CP_NAMESPACE_FACTORY~FOR') EXPORTING iv_value = iv_namespace RECEIVING ro_namespace = lo_nsp. CALL METHOD lo_nsp->('IF_XCO_CP_NAMESPACE~IS_CHANGEABLE') RECEIVING rv_exists = rv_yes. ENDTRY. ENDMETHOD. METHOD zif_abapgit_sap_namespace~split_by_name. * use this method instead of function module RS_NAME_SPLIT_NAMESPACE DATA lv_regex TYPE string. DATA lv_length TYPE i. DATA lr_ex TYPE REF TO cx_root. lv_regex = '^\/[^\/]{1,8}\/'. TRY. FIND REGEX lv_regex IN iv_obj_with_namespace MATCH LENGTH lv_length. CATCH cx_root INTO lr_ex. zcx_abapgit_exception=>raise( lr_ex->get_text( ) ). ENDTRY. IF sy-subrc = 0 AND lv_length > 1. rs_obj_namespace-namespace = iv_obj_with_namespace(lv_length). rs_obj_namespace-obj_without_namespace = iv_obj_with_namespace+lv_length. ELSE. IF iv_obj_with_namespace(1) = '/'. zcx_abapgit_exception=>raise( |The object { iv_obj_with_namespace } has an invalid namespace| ). ENDIF. rs_obj_namespace-obj_without_namespace = iv_obj_with_namespace. ENDIF. IF iv_allow_slash_in_name = abap_false AND rs_obj_namespace-obj_without_namespace CA '/'. zcx_abapgit_exception=>raise( |Object without namespace { rs_obj_namespace-obj_without_namespace } contains a '/'| ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_function_module IMPLEMENTATION. METHOD zif_abapgit_function_module~function_exists. DATA: lv_function_module_name TYPE c LENGTH 30. lv_function_module_name = iv_function_module_name. CALL FUNCTION 'FUNCTION_EXISTS' EXPORTING funcname = lv_function_module_name EXCEPTIONS function_not_exist = 1 OTHERS = 2. rv_exists = boolc( sy-subrc = 0 ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_field_rules IMPLEMENTATION. METHOD create. CREATE OBJECT ro_result TYPE zcl_abapgit_field_rules. ENDMETHOD. METHOD fill_value. DATA lv_timestamp TYPE timestampl. CASE iv_rule. WHEN zif_abapgit_field_rules=>c_fill_rule-date. cv_value = sy-datum. WHEN zif_abapgit_field_rules=>c_fill_rule-time. cv_value = sy-uzeit. WHEN zif_abapgit_field_rules=>c_fill_rule-timestamp. GET TIME STAMP FIELD lv_timestamp. cv_value = lv_timestamp. WHEN zif_abapgit_field_rules=>c_fill_rule-user. cv_value = sy-uname. WHEN zif_abapgit_field_rules=>c_fill_rule-client. cv_value = sy-mandt. WHEN zif_abapgit_field_rules=>c_fill_rule-package. cv_value = iv_package. ENDCASE. ENDMETHOD. METHOD zif_abapgit_field_rules~add. DATA ls_item TYPE ty_item. ls_item-tabname = iv_table. ls_item-fieldname = iv_field. ls_item-fill_rule = iv_fill_rule. INSERT ls_item INTO TABLE mt_item. ro_self = me. ENDMETHOD. METHOD zif_abapgit_field_rules~apply_clear_logic. DATA ls_item TYPE ty_item. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. IF mt_item IS INITIAL. RETURN. ENDIF. LOOP AT ct_data ASSIGNING . LOOP AT mt_item INTO ls_item WHERE tabname = iv_table. ASSIGN COMPONENT ls_item-fieldname OF STRUCTURE TO . IF sy-subrc = 0. CLEAR . ENDIF. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_field_rules~apply_fill_logic. DATA ls_item TYPE ty_item. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. IF mt_item IS INITIAL. RETURN. ENDIF. LOOP AT ct_data ASSIGNING . LOOP AT mt_item INTO ls_item WHERE tabname = iv_table. ASSIGN COMPONENT ls_item-fieldname OF STRUCTURE TO . IF sy-subrc = 0. fill_value( EXPORTING iv_rule = ls_item-fill_rule iv_package = iv_package CHANGING cv_value = ). ENDIF. ENDLOOP. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_oo_serializer IMPLEMENTATION. METHOD are_test_classes_skipped. rv_return = mv_skip_testclass. ENDMETHOD. METHOD calculate_skip_testclass. DATA: lv_line1 LIKE LINE OF it_source, lv_line2 LIKE LINE OF it_source. * when creating classes in Eclipse it automatically generates the * testclass include, but it is not needed, so skip to avoid * creating an extra file in the repository. * Also remove it if the content is manually removed, but * the class still thinks it contains tests rv_skip_testclass = abap_false. IF lines( it_source ) = 2. READ TABLE it_source INDEX 1 INTO lv_line1. ASSERT sy-subrc = 0. READ TABLE it_source INDEX 2 INTO lv_line2. ASSERT sy-subrc = 0. IF strlen( lv_line1 ) >= 3 AND lv_line1(3) = '*"*' AND lv_line2 IS INITIAL. rv_skip_testclass = abap_true. ENDIF. ELSEIF lines( it_source ) = 1. READ TABLE it_source INDEX 1 INTO lv_line1. ASSERT sy-subrc = 0. IF lv_line1 IS INITIAL OR ( strlen( lv_line1 ) >= 3 AND lv_line1(3) = '*"*' ) OR ( strlen( lv_line1 ) = 1 AND lv_line1(1) = '*' ). rv_skip_testclass = abap_true. ENDIF. ELSEIF lines( it_source ) = 0. rv_skip_testclass = abap_true. ENDIF. ENDMETHOD. METHOD read_include. DATA ls_include TYPE progstruc. DATA lv_program TYPE syrepid. DATA lt_source TYPE abaptxt255_tab. ASSERT iv_type = seop_ext_class_locals_def OR iv_type = seop_ext_class_locals_imp OR iv_type = seop_ext_class_macros OR iv_type = seop_ext_class_testclasses. ls_include-rootname = is_clskey-clsname. TRANSLATE ls_include-rootname USING ' ='. ls_include-categorya = iv_type(1). ls_include-codea = iv_type+1(4). * it looks like there is an issue in function module SEO_CLASS_GET_INCLUDE_SOURCE * on 750 kernels, where the READ REPORT without STATE addition does not * return the active version, this method is a workaround for this issue lv_program = ls_include. TRY. lt_source = zcl_abapgit_factory=>get_sap_report( )->read_report( lv_program ). CATCH zcx_abapgit_exception. * ignore if the report is not found, sometimes the CCDEF include does not exist ENDTRY. rt_source = lt_source. ENDMETHOD. METHOD reduce. DATA: lv_source LIKE LINE OF ct_source, lv_found TYPE abap_bool. * skip files that only contain the standard comments lv_found = abap_false. LOOP AT ct_source INTO lv_source. IF strlen( lv_source ) >= 3 AND lv_source(3) <> '*"*'. lv_found = abap_true. ENDIF. ENDLOOP. IF lv_found = abap_false. CLEAR ct_source. ENDIF. ENDMETHOD. METHOD remove_signatures. * signatures messes up in CL_OO_SOURCE when deserializing and serializing * within same session DATA: lv_begin TYPE string, lv_end TYPE string, lv_remove TYPE abap_bool, lv_source LIKE LINE OF ct_source. "@TODO: Put under test CONCATENATE '* ------------------------------------' '---------------------------------------------------+' INTO lv_begin. CONCATENATE '* +------------------------------------------------' '--------------------------------------' INTO lv_end. lv_remove = abap_false. LOOP AT ct_source INTO lv_source. IF lv_source = lv_begin. lv_remove = abap_true. ENDIF. IF lv_remove = abap_true. DELETE ct_source INDEX sy-tabix. ENDIF. IF lv_source = lv_end. lv_remove = abap_false. ENDIF. ENDLOOP. ENDMETHOD. METHOD serialize_abap_clif_source. rt_source = zcl_abapgit_exit=>get_instance( )->custom_serialize_abap_clif( is_class_key ). IF rt_source IS NOT INITIAL. RETURN. ENDIF. TRY. rt_source = serialize_abap_new( is_class_key ). CATCH cx_sy_dyn_call_error. rt_source = serialize_abap_old( is_class_key ). ENDTRY. " Call exit again for optional post-processing rt_source = zcl_abapgit_exit=>get_instance( )->custom_serialize_abap_clif( is_class_key = is_class_key it_source = rt_source ). ENDMETHOD. METHOD serialize_abap_new. DATA: lo_source TYPE REF TO object, lo_instance TYPE REF TO object. * do not call the class/methods statically, as it will * give syntax errors on old versions CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') RECEIVING result = lo_instance. CALL METHOD lo_instance->('CREATE_CLIF_SOURCE') EXPORTING clif_name = is_clskey-clsname version = 'A' RECEIVING result = lo_source. CALL METHOD lo_source->('GET_SOURCE') IMPORTING source = rt_source. ENDMETHOD. METHOD serialize_abap_old. * for old ABAP AS versions DATA: lo_source TYPE REF TO object. CREATE OBJECT lo_source TYPE ('CL_OO_SOURCE') EXPORTING clskey = is_clskey EXCEPTIONS class_not_existing = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL METHOD lo_source->('READ') EXPORTING version = 'A'. CALL METHOD lo_source->('GET_OLD_SOURCE') RECEIVING old_source = rt_source. remove_signatures( CHANGING ct_source = rt_source ). ENDMETHOD. METHOD serialize_locals_def. rt_source = read_include( is_clskey = is_clskey iv_type = seop_ext_class_locals_def ). reduce( CHANGING ct_source = rt_source ). ENDMETHOD. METHOD serialize_locals_imp. rt_source = read_include( is_clskey = is_clskey iv_type = seop_ext_class_locals_imp ). reduce( CHANGING ct_source = rt_source ). ENDMETHOD. METHOD serialize_macros. rt_source = read_include( is_clskey = is_clskey iv_type = seop_ext_class_macros ). reduce( CHANGING ct_source = rt_source ). ENDMETHOD. METHOD serialize_testclasses. DATA ls_vseoclass TYPE vseoclass. CALL FUNCTION 'SEO_CLIF_GET' EXPORTING cifkey = is_clskey version = seoc_version_active IMPORTING class = ls_vseoclass EXCEPTIONS not_existing = 1 deleted = 2 model_only = 3 OTHERS = 4. IF sy-subrc <> 0 OR ls_vseoclass-with_unit_tests = abap_false. mv_skip_testclass = abap_true. RETURN. ENDIF. rt_source = read_include( is_clskey = is_clskey iv_type = seop_ext_class_testclasses ). mv_skip_testclass = calculate_skip_testclass( rt_source ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_oo_interface IMPLEMENTATION. METHOD init_scanner. DATA: lx_exc TYPE REF TO cx_root, lv_message TYPE string, lv_classname TYPE abap_abstypename. FIELD-SYMBOLS: TYPE i. TRY. ro_scanner = cl_oo_source_scanner_interface=>create_interface_scanner( clif_name = iv_name source = it_source ). ro_scanner->scan( ). CATCH cx_clif_scan_error. zcx_abapgit_exception=>raise( 'error initializing INTF scanner' ). CATCH cx_root INTO lx_exc. lv_classname = cl_abap_classdescr=>get_class_name( lx_exc ). IF lv_classname = '\CLASS=CX_OO_CLIF_SCAN_ERROR_DETAIL'. ASSIGN lx_exc->('SOURCE_POSITION-LINE') TO . ASSERT sy-subrc = 0. lv_message = |{ lx_exc->get_text( ) }, line { }|. ELSE. lv_message = lx_exc->get_text( ). ENDIF. zcx_abapgit_exception=>raise( lv_message ). ENDTRY. ENDMETHOD. METHOD update_meta. DATA: lo_update TYPE REF TO cl_oo_interface_section_source, lx_error TYPE REF TO cx_oo_source_save_failure, ls_clskey TYPE seoclskey, lv_scan_error TYPE abap_bool. ls_clskey-clsname = iv_name. TRY. CALL FUNCTION 'SEO_BUFFER_REFRESH' EXPORTING cifkey = ls_clskey version = seoc_version_active. CREATE OBJECT lo_update TYPE ('CL_OO_INTERFACE_SECTION_SOURCE') EXPORTING intkey = ls_clskey state = 'A' source = it_source EXCEPTIONS interface_not_existing = 1 read_source_error = 2 OTHERS = 3 ##SUBRC_OK. CATCH cx_sy_dyn_call_param_not_found. * downport to 702, see https://github.com/abapGit/abapGit/issues/933 * this will READ REPORT instead of using it_source, which should be okay CREATE OBJECT lo_update TYPE cl_oo_interface_section_source EXPORTING intkey = ls_clskey state = 'A' EXCEPTIONS interface_not_existing = 1 read_source_error = 2 OTHERS = 3. ENDTRY. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. lo_update->set_dark_mode( abap_true ). lo_update->scan_section_source( RECEIVING scan_error = lv_scan_error EXCEPTIONS scan_abap_source_error = 1 OTHERS = 2 ). IF sy-subrc <> 0 OR lv_scan_error = abap_true. zcx_abapgit_exception=>raise( |INTF, error while scanning source. Subrc = { sy-subrc }| ). ENDIF. * this will update the SEO* database tables TRY. lo_update->revert_scan_result( ). CATCH cx_oo_source_save_failure INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD update_report. DATA lv_type TYPE c LENGTH 1. lv_type = zcl_abapgit_oo_base=>c_include_program_type. IF iv_program+30 = srext_ext_interface_pool. lv_type = zcl_abapgit_oo_base=>c_ip_program_type. ENDIF. rv_updated = zcl_abapgit_factory=>get_sap_report( )->update_report( iv_name = iv_program iv_package = iv_package iv_version = iv_version it_source = it_source iv_program_type = lv_type ). ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~create. DATA: lt_vseoattrib TYPE seoo_attributes_r, ls_interface_key TYPE seoclskey, ls_properties TYPE vseointerf. FIELD-SYMBOLS: TYPE seoclsname. ASSIGN COMPONENT 'CLSNAME' OF STRUCTURE cg_properties TO . ASSERT sy-subrc = 0. " Get existing interface properties and check if the interface " needs to be created/updated (or is the same) IF iv_check = abap_true. ls_interface_key-clsname = . ls_properties = zif_abapgit_oo_object_fnc~get_interface_properties( ls_interface_key ). IF ls_properties = cg_properties. RETURN. ENDIF. ENDIF. lt_vseoattrib = convert_attrib_to_vseoattrib( iv_clsname = it_attributes = it_attributes ). " Hardcode STATE (#2612) ls_properties = cg_properties. ls_properties-state = seoc_state_implemented. TRY. CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' EXPORTING devclass = iv_package overwrite = abap_true version = seoc_version_active suppress_dialog = abap_true " Parameter missing in 702 CHANGING interface = ls_properties attributes = lt_vseoattrib EXCEPTIONS existing = 1 is_class = 2 db_error = 3 component_error = 4 no_access = 5 other = 6 OTHERS = 7. CATCH cx_sy_dyn_call_param_not_found. CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' EXPORTING devclass = iv_package overwrite = abap_true version = seoc_version_active CHANGING interface = ls_properties attributes = lt_vseoattrib EXCEPTIONS existing = 1 is_class = 2 db_error = 3 component_error = 4 no_access = 5 other = 6 OTHERS = 7. ENDTRY. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~delete. CALL FUNCTION 'SEO_INTERFACE_DELETE_COMPLETE' EXPORTING intkey = is_deletion_key EXCEPTIONS not_existing = 1 is_class = 2 db_error = 3 no_access = 4 other = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~deserialize_source. DATA: lv_updated TYPE abap_bool, lv_program TYPE program, lo_scanner TYPE REF TO cl_oo_source_scanner_interface, lt_public TYPE seop_source_string. "Buffer needs to be refreshed, "otherwise standard SAP CLIF_SOURCE reorder methods alphabetically CALL FUNCTION 'SEO_BUFFER_INIT'. CALL FUNCTION 'SEO_BUFFER_REFRESH' EXPORTING cifkey = is_key version = seoc_version_inactive. lo_scanner = init_scanner( it_source = it_source iv_name = is_key-clsname ). lt_public = lo_scanner->get_interface_section_source( ). IF lt_public IS NOT INITIAL. lv_program = cl_oo_classname_service=>get_intfsec_name( is_key-clsname ). lv_updated = update_report( iv_program = lv_program iv_package = iv_package iv_version = iv_version it_source = lt_public ). IF lv_updated = abap_true. update_meta( iv_name = is_key-clsname it_source = lt_public ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~exists. CALL FUNCTION 'SEO_INTERFACE_EXISTENCE_CHECK' EXPORTING intkey = is_object_name EXCEPTIONS not_specified = 1 not_existing = 2 is_class = 3 no_text = 4 inconsistent = 5 OTHERS = 6. rv_exists = boolc( sy-subrc = 0 OR sy-subrc = 4 ). ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~get_includes. DATA lv_interface_name TYPE seoclsname. lv_interface_name = iv_object_name. APPEND cl_oo_classname_service=>get_interfacepool_name( lv_interface_name ) TO rt_includes. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~get_interface_properties. CALL FUNCTION 'SEO_CLIF_GET' EXPORTING cifkey = is_interface_key version = seoc_version_active IMPORTING interface = rs_interface_properties EXCEPTIONS not_existing = 1 deleted = 2 model_only = 3 OTHERS = 4. IF sy-subrc = 1. RETURN. " in case only inactive version exists ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CLEAR: " TODO 2023-08-01: Clear rs_interface_properties-state (#2612) rs_interface_properties-uuid, rs_interface_properties-author, rs_interface_properties-createdon, rs_interface_properties-changedby, rs_interface_properties-changedon, rs_interface_properties-chgdanyby, rs_interface_properties-chgdanyon, rs_interface_properties-r3release, rs_interface_properties-version. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~syntax_check. DATA: ls_intkey TYPE seoclskey, lv_syntaxerror TYPE abap_bool. ls_intkey-clsname = to_upper( iv_object_name ). CALL FUNCTION 'SEO_INTERFACE_CHECK_POOL' EXPORTING intkey = ls_intkey suppress_error_popup = abap_true IMPORTING syntaxerror = lv_syntaxerror EXCEPTIONS error_message = 1 " suppress S-message OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF lv_syntaxerror = abap_true. zcx_abapgit_exception=>raise( |Interface { ls_intkey-clsname } has syntax errors | ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_oo_factory IMPLEMENTATION. METHOD get_by_type. IF iv_object_type = 'CLAS'. CREATE OBJECT ri_object_oriented_object TYPE zcl_abapgit_oo_class. ELSEIF iv_object_type = 'INTF'. CREATE OBJECT ri_object_oriented_object TYPE zcl_abapgit_oo_interface. ENDIF. ENDMETHOD. METHOD get_by_name. DATA: li_interface TYPE REF TO zif_abapgit_oo_object_fnc, li_class TYPE REF TO zif_abapgit_oo_object_fnc, ls_object_name TYPE seoclskey. ls_object_name-clsname = to_upper( iv_object_name ). CREATE OBJECT li_class TYPE zcl_abapgit_oo_class. IF li_class->exists( ls_object_name ) = abap_true. ri_object_oriented_object = li_class. RETURN. ENDIF. CREATE OBJECT li_interface TYPE zcl_abapgit_oo_interface. IF li_interface->exists( ls_object_name ) = abap_true. ri_object_oriented_object = li_interface. RETURN. ENDIF. zcx_abapgit_exception=>raise( |{ iv_object_name } is neither a class nor an interface| ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_oo_class IMPLEMENTATION. METHOD create_report. zcl_abapgit_factory=>get_sap_report( )->insert_report( iv_name = iv_program iv_package = iv_package it_source = it_source iv_state = iv_state iv_version = iv_version iv_program_type = iv_program_type iv_extension_type = iv_extension ). ENDMETHOD. METHOD delete_report. zcl_abapgit_factory=>get_sap_report( )->delete_report( iv_program ). ENDMETHOD. METHOD determine_method_include. DATA: ls_mtdkey TYPE seocpdkey. ls_mtdkey-clsname = iv_name. ls_mtdkey-cpdname = iv_method. cl_oo_classname_service=>get_method_include( EXPORTING mtdkey = ls_mtdkey RECEIVING result = rv_program EXCEPTIONS method_not_existing = 1 ). IF sy-subrc = 0. RETURN. ENDIF. CALL FUNCTION 'SEO_METHOD_GENERATE_INCLUDE' EXPORTING suppress_mtdkey_check = abap_true mtdkey = ls_mtdkey EXCEPTIONS not_existing = 1 model_only = 2 include_existing = 3 method_imp_not_generated = 4 method_imp_not_initialised = 5 _internal_class_not_existing = 6 _internal_method_overflow = 7 cancelled = 8 method_is_abstract_implemented = 9 method_is_final_implemented = 10 internal_error_insert_report = 11 OTHERS = 12. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. rv_program = cl_oo_classname_service=>get_method_include( ls_mtdkey ). ENDMETHOD. METHOD generate_classpool. DATA: ls_clskey TYPE seoclskey. ls_clskey-clsname = iv_name. CALL FUNCTION 'SEO_CLASS_GENERATE_CLASSPOOL' EXPORTING clskey = ls_clskey suppress_corr = abap_true EXCEPTIONS not_existing = 1 model_only = 2 class_pool_not_generated = 3 class_stment_not_generated = 4 locals_not_generated = 5 macros_not_generated = 6 public_sec_not_generated = 7 protected_sec_not_generated = 8 private_sec_not_generated = 9 typeref_not_generated = 10 class_pool_not_initialised = 11 class_stment_not_initialised = 12 locals_not_initialised = 13 macros_not_initialised = 14 public_sec_not_initialised = 15 protected_sec_not_initialised = 16 private_sec_not_initialised = 17 typeref_not_initialised = 18 _internal_class_overflow = 19 OTHERS = 20. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD get_method_includes. " get method includes for implemented interfaces " this will contain also leftover includes for deleted interface methods rt_includes = cl_oo_classname_service=>get_all_method_includes( iv_classname ). ENDMETHOD. METHOD init_scanner. DATA: lx_exc TYPE REF TO cx_root, lv_message TYPE string, lv_classname TYPE abap_abstypename. FIELD-SYMBOLS: TYPE i. TRY. ro_scanner = cl_oo_source_scanner_class=>create_class_scanner( clif_name = iv_name source = it_source ). ro_scanner->scan( ). CATCH cx_clif_scan_error. zcx_abapgit_exception=>raise( 'error initializing CLAS scanner' ). CATCH cx_root INTO lx_exc. lv_classname = cl_abap_classdescr=>get_class_name( lx_exc ). IF lv_classname = '\CLASS=CX_OO_CLIF_SCAN_ERROR_DETAIL'. ASSIGN lx_exc->('SOURCE_POSITION-LINE') TO . ASSERT sy-subrc = 0. lv_message = |{ lx_exc->get_text( ) }, line { }|. ELSE. lv_message = lx_exc->get_text( ). ENDIF. zcx_abapgit_exception=>raise( lv_message ). ENDTRY. ENDMETHOD. METHOD repair_classpool. CALL FUNCTION 'SEO_CLASS_REPAIR_CLASSPOOL' EXPORTING clskey = is_key EXCEPTIONS not_existing = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error repairing class { is_key-clsname }| ). ENDIF. ENDMETHOD. METHOD repair_redefinitions. " Same logic as SE24 > Utilities > Clean-up > Redefinitions (LSEODCCO) DATA: lt_inheritance TYPE vseoextend, lt_redefinitions TYPE seor_redefinitions_r, ls_cpdkey TYPE seocpdkey, lv_tabix TYPE sy-tabix, lv_exposure TYPE n LENGTH 1, lv_update TYPE abap_bool, lv_local_component TYPE abap_bool. FIELD-SYMBOLS TYPE seoredef. CALL FUNCTION 'SEO_CLASS_TYPEINFO_GET' EXPORTING clskey = is_key version = seoc_version_active IMPORTING inheritance = lt_inheritance redefinitions = lt_redefinitions EXCEPTIONS not_existing = 1 is_interface = 2 model_only = 3 OTHERS = 4. IF sy-subrc <> 0. RETURN. ENDIF. " check redefinitions validity LOOP AT lt_redefinitions ASSIGNING . lv_tabix = sy-tabix. ls_cpdkey-clsname = is_key-clsname. ls_cpdkey-cpdname = -mtdname. CALL FUNCTION 'SEO_COMPONENT_BY_INHERITANCE' EXPORTING cpdkey = ls_cpdkey version = seoc_version_active IMPORTING exposure = lv_exposure is_local_component = lv_local_component EXCEPTIONS not_existing = 1 model_only = 2 OTHERS = 3. IF sy-subrc <> 0. DELETE lt_redefinitions INDEX lv_tabix. lv_update = abap_true. ELSEIF -exposure <> lv_exposure. -exposure = lv_exposure. lv_update = abap_true. ELSEIF lv_local_component = abap_true AND -attvalue IS INITIAL AND -mtdabstrct IS INITIAL AND -mtdfinal IS INITIAL. DELETE lt_redefinitions INDEX lv_tabix. lv_update = abap_true. ENDIF. ENDLOOP. IF lv_update = abap_true. CALL FUNCTION 'SEO_INHERITANC_CHANGE_F_DATA' EXPORTING save = abap_false CHANGING inheritance = lt_inheritance redefinitions = lt_redefinitions EXCEPTIONS not_existing = 1 deleted = 2 is_comprising = 3 is_implementing = 4 not_changed = 5 db_error = 6 OTHERS = 7. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error repairing redefinitions for { is_key-clsname }| ). ENDIF. CALL FUNCTION 'SEO_CLIF_SAVE_ALL' EXPORTING cifkey = is_key EXCEPTIONS not_existing = 1 nothing_to_do = 2 access_error = 3 db_error = 4 error_in_code_generation = 5 OTHERS = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error repairing redefinitions for { is_key-clsname }| ). ENDIF. ENDIF. ENDMETHOD. METHOD update_cs_number_of_methods. " Indirect access to keep downward compatibility DATA lr_cache_entry TYPE REF TO data. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE DATA lr_cache_entry TYPE ('SEO_CS_CACHE'). CATCH cx_sy_create_data_error. * does not exist in some older systems RETURN. ENDTRY. ASSIGN lr_cache_entry->* TO . ASSERT sy-subrc = 0. ASSIGN COMPONENT 'CLSNAME' OF STRUCTURE TO . ASSERT sy-subrc = 0. = iv_classname. ASSIGN COMPONENT 'NO_OF_METHOD_IMPLS' OF STRUCTURE TO . ASSERT sy-subrc = 0. = iv_number_of_impl_methods. MODIFY ('SEO_CS_CACHE') FROM . ENDMETHOD. METHOD update_full_class_include. CONSTANTS: lc_class_source_extension TYPE c LENGTH 2 VALUE 'CS', lc_include_program_type TYPE c LENGTH 1 VALUE 'I', lc_active_version TYPE r3state VALUE 'A'. create_report( iv_program = cl_oo_classname_service=>get_cs_name( iv_classname ) iv_package = iv_package it_source = it_source iv_extension = lc_class_source_extension iv_program_type = lc_include_program_type iv_state = lc_active_version iv_version = iv_version ). " Assuming that all methods that were scanned are implemented update_cs_number_of_methods( iv_classname = iv_classname iv_number_of_impl_methods = lines( it_methods ) ). ENDMETHOD. METHOD update_meta. DATA: lo_update TYPE REF TO cl_oo_class_section_source, lx_error TYPE REF TO cx_oo_source_save_failure, ls_clskey TYPE seoclskey, lv_scan_error TYPE abap_bool. ls_clskey-clsname = iv_name. TRY. CALL FUNCTION 'SEO_BUFFER_REFRESH' EXPORTING cifkey = ls_clskey version = seoc_version_active. CREATE OBJECT lo_update TYPE ('CL_OO_CLASS_SECTION_SOURCE') EXPORTING clskey = ls_clskey exposure = iv_exposure state = 'A' source = it_source suppress_constrctr_generation = abap_true EXCEPTIONS class_not_existing = 1 read_source_error = 2 OTHERS = 3 ##SUBRC_OK. CATCH cx_sy_dyn_call_param_not_found. * downport to 702, see https://github.com/abapGit/abapGit/issues/933 * this will READ REPORT instead of using it_source, which should be okay CREATE OBJECT lo_update TYPE cl_oo_class_section_source EXPORTING clskey = ls_clskey exposure = iv_exposure state = 'A' EXCEPTIONS class_not_existing = 1 read_source_error = 2 OTHERS = 3. ENDTRY. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. lo_update->set_dark_mode( abap_true ). TRY. CALL METHOD lo_update->('SET_AMDP_SUPPORT') EXPORTING enabled = abap_true. CATCH cx_sy_dyn_call_illegal_method ##NO_HANDLER. * AMDP not supported in this system, ignore error ENDTRY. lo_update->scan_section_source( RECEIVING scan_error = lv_scan_error EXCEPTIONS scan_abap_source_error = 1 OTHERS = 2 ). IF sy-subrc <> 0 OR lv_scan_error = abap_true. zcx_abapgit_exception=>raise( |CLAS, error while scanning source. Subrc = { sy-subrc }| ). ENDIF. * this will update the SEO* database tables TRY. lo_update->revert_scan_result( ). CATCH cx_oo_source_save_failure INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. IF iv_exposure = seoc_exposure_public. generate_classpool( iv_name ). ENDIF. ENDMETHOD. METHOD update_report. DATA lv_type TYPE c LENGTH 1. lv_type = zcl_abapgit_oo_base=>c_include_program_type. IF iv_program+30 = srext_ext_class_pool. lv_type = zcl_abapgit_oo_base=>c_cp_program_type. ENDIF. rv_updated = zcl_abapgit_factory=>get_sap_report( )->update_report( iv_name = iv_program iv_package = iv_package iv_version = iv_version it_source = it_source iv_program_type = lv_type ). ENDMETHOD. METHOD update_source_index. CONSTANTS: lc_version_active TYPE r3state VALUE 'A', lc_version_inactive TYPE r3state VALUE 'I'. " dynamic invocation, IF_OO_SOURCE_POS_INDEX_HELPER doesn't exist in 702. DATA lo_index_helper TYPE REF TO object. TRY. CREATE OBJECT lo_index_helper TYPE ('CL_OO_SOURCE_POS_INDEX_HELPER'). CALL METHOD lo_index_helper->('IF_OO_SOURCE_POS_INDEX_HELPER~CREATE_INDEX_WITH_SCANNER') EXPORTING class_name = iv_clsname version = lc_version_active scanner = io_scanner. CALL METHOD lo_index_helper->('IF_OO_SOURCE_POS_INDEX_HELPER~DELETE_INDEX') EXPORTING class_name = iv_clsname version = lc_version_inactive. CATCH cx_root. " it's probably okay to no update the index RETURN. ENDTRY. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~create. DATA: lt_vseoattrib TYPE seoo_attributes_r, ls_class_key TYPE seoclskey, ls_properties TYPE vseoclass, lt_attributes TYPE zif_abapgit_oo_object_fnc=>ty_obj_attribute_tt. FIELD-SYMBOLS: TYPE seoclsname. ASSIGN COMPONENT 'CLSNAME' OF STRUCTURE cg_properties TO . ASSERT sy-subrc = 0. " Get existing class properties and attributes and check if the class " needs to be created/updated (or is the same) IF iv_check = abap_true. ls_class_key-clsname = . ls_properties = zif_abapgit_oo_object_fnc~get_class_properties( ls_class_key ). lt_attributes = zif_abapgit_oo_object_fnc~read_attributes( ). IF ls_properties = cg_properties AND lt_attributes = it_attributes. RETURN. ENDIF. ENDIF. lt_vseoattrib = convert_attrib_to_vseoattrib( iv_clsname = it_attributes = it_attributes ). " Hardcode STATE (#2612) ls_properties = cg_properties. ls_properties-state = seoc_state_implemented. TRY. CALL FUNCTION 'SEO_CLASS_CREATE_COMPLETE' EXPORTING devclass = iv_package overwrite = abap_true version = seoc_version_active suppress_dialog = abap_true " Parameter missing in 702 CHANGING class = ls_properties attributes = lt_vseoattrib EXCEPTIONS existing = 1 is_interface = 2 db_error = 3 component_error = 4 no_access = 5 other = 6 OTHERS = 7. CATCH cx_sy_dyn_call_param_not_found. CALL FUNCTION 'SEO_CLASS_CREATE_COMPLETE' EXPORTING devclass = iv_package overwrite = abap_true version = seoc_version_active CHANGING class = ls_properties attributes = lt_vseoattrib EXCEPTIONS existing = 1 is_interface = 2 db_error = 3 component_error = 4 no_access = 5 other = 6 OTHERS = 7. ENDTRY. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~create_sotr. zcl_abapgit_sotr_handler=>create_sotr( iv_package = iv_package io_xml = ii_xml ). zcl_abapgit_sots_handler=>create_sots( iv_package = iv_package io_xml = ii_xml ). ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~delete. " SEO_CLASS_DELETE_COMPLETE deletes OTR usage, only " Use handler to also delete OTR header and texts zcl_abapgit_sotr_handler=>delete_sotr( iv_pgmid = 'LIMU' iv_object = 'CPUB' iv_obj_name = is_deletion_key-clsname ). zcl_abapgit_sots_handler=>delete_sots( iv_pgmid = 'LIMU' iv_object = 'CPUB' iv_obj_name = is_deletion_key-clsname ). CALL FUNCTION 'SEO_CLASS_DELETE_COMPLETE' EXPORTING clskey = is_deletion_key EXCEPTIONS not_existing = 1 is_interface = 2 db_error = 3 no_access = 4 other = 5 OTHERS = 6. IF sy-subrc = 1. * ignore deletion of objects that does not exist * this can happen when the SXCI object is deleted before the implementing CLAS RETURN. ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~deserialize_source. DATA: lv_updated TYPE abap_bool, lv_program TYPE program, lo_scanner TYPE REF TO cl_oo_source_scanner_class, lt_methods TYPE cl_oo_source_scanner_class=>type_method_implementations, lt_incls TYPE seop_methods_w_include, lv_method LIKE LINE OF lt_methods, lt_public TYPE seop_source_string, lt_source TYPE seop_source_string. "Buffer needs to be refreshed, "otherwise standard SAP CLIF_SOURCE reorder methods alphabetically CALL FUNCTION 'SEO_BUFFER_INIT'. CALL FUNCTION 'SEO_BUFFER_REFRESH' EXPORTING cifkey = is_key version = seoc_version_inactive. lo_scanner = init_scanner( it_source = it_source iv_name = is_key-clsname ). * public lt_public = lo_scanner->get_public_section_source( ). IF lt_public IS NOT INITIAL. lv_program = cl_oo_classname_service=>get_pubsec_name( is_key-clsname ). lv_updated = update_report( iv_program = lv_program iv_package = iv_package iv_version = iv_version it_source = lt_public ). IF lv_updated = abap_true. update_meta( iv_name = is_key-clsname iv_exposure = seoc_exposure_public it_source = lt_public ). ENDIF. ENDIF. * protected lt_source = lo_scanner->get_protected_section_source( ). IF lt_source IS NOT INITIAL. lv_program = cl_oo_classname_service=>get_prosec_name( is_key-clsname ). lv_updated = update_report( iv_program = lv_program iv_package = iv_package iv_version = iv_version it_source = lt_source ). IF lv_updated = abap_true. update_meta( iv_name = is_key-clsname iv_exposure = seoc_exposure_protected it_source = lt_source ). ENDIF. ENDIF. * private lt_source = lo_scanner->get_private_section_source( ). IF lt_source IS NOT INITIAL. lv_program = cl_oo_classname_service=>get_prisec_name( is_key-clsname ). lv_updated = update_report( iv_program = lv_program iv_package = iv_package iv_version = iv_version it_source = lt_source ). IF lv_updated = abap_true. update_meta( iv_name = is_key-clsname iv_exposure = seoc_exposure_private it_source = lt_source ). ENDIF. ENDIF. * methods lt_methods = lo_scanner->get_method_implementations( ). lt_incls = get_method_includes( is_key-clsname ). LOOP AT lt_methods INTO lv_method. TRY. lt_source = lo_scanner->get_method_impl_source( lv_method ). CATCH cx_oo_clif_component. zcx_abapgit_exception=>raise( 'error from GET_METHOD_IMPL_SOURCE' ). ENDTRY. lv_program = determine_method_include( iv_name = is_key-clsname iv_method = lv_method ). update_report( iv_program = lv_program iv_package = iv_package iv_version = iv_version it_source = lt_source ). " If method was implemented before, remove from list DELETE lt_incls WHERE cpdkey-clsname = is_key-clsname AND cpdkey-cpdname = lv_method. ENDLOOP. * full class include update_full_class_include( iv_classname = is_key-clsname iv_package = iv_package iv_version = iv_version it_source = it_source it_methods = lt_methods ). " If there are leftover method includes, then class needs to be repaired " which will delete the obsolete includes IF lt_incls IS NOT INITIAL. repair_classpool( is_key ). repair_redefinitions( is_key ). ENDIF. update_source_index( iv_clsname = is_key-clsname io_scanner = lo_scanner ). ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~exists. CALL FUNCTION 'SEO_CLASS_EXISTENCE_CHECK' EXPORTING clskey = is_object_name EXCEPTIONS not_specified = 1 not_existing = 2 is_interface = 3 no_text = 4 inconsistent = 5 OTHERS = 6. rv_exists = boolc( sy-subrc = 0 OR sy-subrc = 4 ). ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~generate_locals. DATA: lv_program TYPE syrepid. IF lines( it_local_definitions ) > 0. lv_program = cl_oo_classname_service=>get_ccdef_name( is_key-clsname ). update_report( iv_program = lv_program iv_package = iv_package iv_version = iv_version it_source = it_local_definitions ). ENDIF. IF lines( it_local_implementations ) > 0. lv_program = cl_oo_classname_service=>get_ccimp_name( is_key-clsname ). update_report( iv_program = lv_program iv_package = iv_package iv_version = iv_version it_source = it_local_implementations ). ENDIF. IF lines( it_local_macros ) > 0. lv_program = cl_oo_classname_service=>get_ccmac_name( is_key-clsname ). update_report( iv_program = lv_program iv_package = iv_package iv_version = iv_version it_source = it_local_macros ). ENDIF. lv_program = cl_oo_classname_service=>get_ccau_name( is_key-clsname ). IF lines( it_local_test_classes ) > 0. update_report( iv_program = lv_program iv_package = iv_package iv_version = iv_version it_source = it_local_test_classes ). ELSE. " Drop the include to remove left-over test classes delete_report( lv_program ). ENDIF. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~get_class_properties. CALL FUNCTION 'SEO_CLIF_GET' EXPORTING cifkey = is_class_key version = seoc_version_active IMPORTING class = rs_class_properties EXCEPTIONS not_existing = 1 deleted = 2 model_only = 3 OTHERS = 4. IF sy-subrc = 1. RETURN. " in case only inactive version exists ELSEIF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CLEAR: " TODO 2023-08-01: Clear rs_class_properties-state (#2612) rs_class_properties-uuid, rs_class_properties-author, rs_class_properties-createdon, rs_class_properties-changedby, rs_class_properties-changedon, rs_class_properties-r3release, rs_class_properties-chgdanyby, rs_class_properties-chgdanyon, rs_class_properties-clsfinal, rs_class_properties-clsabstrct, rs_class_properties-exposure, rs_class_properties-version. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~get_includes. * note: includes returned might not exist * method cl_oo_classname_service=>GET_ALL_CLASS_INCLUDES does not exist in 702 DATA: lv_class_name TYPE seoclsname, lt_methods TYPE seop_methods_w_include. FIELD-SYMBOLS: LIKE LINE OF lt_methods. lv_class_name = iv_object_name. APPEND cl_oo_classname_service=>get_ccdef_name( lv_class_name ) TO rt_includes. APPEND cl_oo_classname_service=>get_ccmac_name( lv_class_name ) TO rt_includes. APPEND cl_oo_classname_service=>get_ccimp_name( lv_class_name ) TO rt_includes. APPEND cl_oo_classname_service=>get_cl_name( lv_class_name ) TO rt_includes. APPEND cl_oo_classname_service=>get_ccau_name( lv_class_name ) TO rt_includes. APPEND cl_oo_classname_service=>get_pubsec_name( lv_class_name ) TO rt_includes. APPEND cl_oo_classname_service=>get_prosec_name( lv_class_name ) TO rt_includes. APPEND cl_oo_classname_service=>get_prisec_name( lv_class_name ) TO rt_includes. APPEND cl_oo_classname_service=>get_classpool_name( lv_class_name ) TO rt_includes. APPEND cl_oo_classname_service=>get_ct_name( lv_class_name ) TO rt_includes. * skip the CS include, as it is sometimes generated on the fly instead of * when the methods are changed cl_oo_classname_service=>get_all_method_includes( EXPORTING clsname = lv_class_name RECEIVING result = lt_methods EXCEPTIONS class_not_existing = 1 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Class { lv_class_name } not existing| ). ENDIF. LOOP AT lt_methods ASSIGNING . APPEND -incname TO rt_includes. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~insert_text_pool. DATA: lv_cp TYPE program. lv_cp = cl_oo_classname_service=>get_classpool_name( iv_class_name ). INSERT TEXTPOOL lv_cp FROM it_text_pool LANGUAGE iv_language STATE iv_state. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from INSERT TEXTPOOL' ). ENDIF. zcl_abapgit_objects_activation=>add( iv_type = 'REPT' iv_name = lv_cp ). ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~read_sotr. zcl_abapgit_sotr_handler=>read_sotr( iv_pgmid = 'LIMU' iv_object = 'CPUB' iv_obj_name = iv_object_name io_i18n_params = io_i18n_params io_xml = ii_xml ). zcl_abapgit_sots_handler=>read_sots( iv_pgmid = 'LIMU' iv_object = 'CPUB' iv_obj_name = iv_object_name io_i18n_params = io_i18n_params io_xml = ii_xml ). ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~read_text_pool. DATA: lv_cp TYPE program. lv_cp = cl_oo_classname_service=>get_classpool_name( iv_class_name ). READ TEXTPOOL lv_cp INTO rt_text_pool LANGUAGE iv_language. "#EC CI_READ_REP ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~syntax_check. DATA: ls_clskey TYPE seoclskey, lv_syntaxerror TYPE abap_bool. ls_clskey-clsname = to_upper( iv_object_name ). CALL FUNCTION 'SEO_CLASS_CHECK_CLASSPOOL' EXPORTING clskey = ls_clskey suppress_error_popup = abap_true IMPORTING syntaxerror = lv_syntaxerror EXCEPTIONS _internal_class_not_existing = 1 error_message = 2 " suppress S-message OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF lv_syntaxerror = abap_true. zcx_abapgit_exception=>raise( |Class { ls_clskey-clsname } has syntax errors | ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_oo_base IMPLEMENTATION. METHOD convert_attrib_to_vseoattrib. FIELD-SYMBOLS: LIKE LINE OF it_attributes, LIKE LINE OF rt_vseoattrib. LOOP AT it_attributes ASSIGNING . INSERT INITIAL LINE INTO TABLE rt_vseoattrib ASSIGNING . MOVE-CORRESPONDING TO . -clsname = iv_clsname. -state = seoc_state_implemented. -exposure = -exposure. UNASSIGN . ENDLOOP. UNASSIGN . ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~add_to_activation_list. zcl_abapgit_objects_activation=>add_item( is_item ). ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~create. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~create_documentation. CALL FUNCTION 'DOCU_UPD' EXPORTING id = iv_id langu = iv_language object = iv_object_name no_masterlang = iv_no_masterlang state = c_docu_state_active TABLES line = it_lines EXCEPTIONS ret_code = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~create_sotr. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~delete. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~delete_documentation. CALL FUNCTION 'DOCU_DEL' EXPORTING id = iv_id langu = iv_language object = iv_object_name typ = 'E' EXCEPTIONS ret_code = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Error from DOCU_DEL' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~deserialize_source. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~exists. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~generate_locals. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~get_class_properties. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~get_includes. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~get_interface_properties. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~get_skip_test_classes. rv_skip = mv_skip_test_classes. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~insert_text_pool. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~read_attributes. SELECT cmpname attbusobj attkeyfld exposure FROM seocompodf INTO CORRESPONDING FIELDS OF TABLE rt_attributes WHERE clsname = iv_object_name AND ( attbusobj <> space OR attkeyfld <> space ) AND version = '1' ORDER BY PRIMARY KEY. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~read_descriptions. FIELD-SYMBOLS LIKE LINE OF rt_descriptions. IF iv_language IS INITIAL. " load all languages SELECT * FROM seocompotx INTO TABLE rt_descriptions WHERE clsname = iv_object_name AND descript <> '' ORDER BY PRIMARY KEY. "#EC CI_SUBRC ELSE. " load main language SELECT * FROM seocompotx INTO TABLE rt_descriptions WHERE clsname = iv_object_name AND langu = iv_language AND descript <> '' ORDER BY PRIMARY KEY. "#EC CI_SUBRC ENDIF. LOOP AT rt_descriptions ASSIGNING . CLEAR -clsname. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~read_descriptions_sub. FIELD-SYMBOLS LIKE LINE OF rt_descriptions. IF iv_language IS INITIAL. " load all languages SELECT * FROM seosubcotx INTO TABLE rt_descriptions WHERE clsname = iv_object_name AND descript <> '' ORDER BY PRIMARY KEY. "#EC CI_SUBRC ELSE. " load main language SELECT * FROM seosubcotx INTO TABLE rt_descriptions WHERE clsname = iv_object_name AND langu = iv_language AND descript <> '' ORDER BY PRIMARY KEY. "#EC CI_SUBRC ENDIF. LOOP AT rt_descriptions ASSIGNING . CLEAR -clsname. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~read_documentation. DATA: lv_state TYPE dokstate, lt_lines TYPE tlinetab. CALL FUNCTION 'DOCU_GET' EXPORTING id = iv_id langu = iv_language object = iv_object_name version_active_or_last = space " retrieve active version IMPORTING dokstate = lv_state TABLES line = lt_lines EXCEPTIONS no_docu_on_screen = 1 no_docu_self_def = 2 no_docu_temp = 3 ret_code = 4 OTHERS = 5. IF sy-subrc = 0 AND lv_state = c_docu_state_active. rt_lines = lt_lines. ELSE. CLEAR rt_lines. ENDIF. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~read_sotr. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~read_superclass. SELECT SINGLE refclsname FROM vseoextend INTO rv_superclass WHERE clsname = iv_classname. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~read_text_pool. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~serialize_abap. DATA lo_oo_serializer TYPE REF TO zcl_abapgit_oo_serializer. CREATE OBJECT lo_oo_serializer. CASE iv_type. WHEN seop_ext_class_locals_def. rt_source = lo_oo_serializer->serialize_locals_def( is_class_key ). WHEN seop_ext_class_locals_imp. rt_source = lo_oo_serializer->serialize_locals_imp( is_class_key ). WHEN seop_ext_class_macros. rt_source = lo_oo_serializer->serialize_macros( is_class_key ). WHEN seop_ext_class_testclasses. rt_source = lo_oo_serializer->serialize_testclasses( is_class_key ). mv_skip_test_classes = lo_oo_serializer->are_test_classes_skipped( ). WHEN OTHERS. rt_source = lo_oo_serializer->serialize_abap_clif_source( is_class_key ). ENDCASE. ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~update_descriptions. DATA lt_descriptions LIKE it_descriptions. DATA lt_components TYPE seo_components. DATA ls_description LIKE LINE OF it_descriptions. DATA lv_lang TYPE tadir-masterlang. FIELD-SYMBOLS LIKE LINE OF it_descriptions. FIELD-SYMBOLS TYPE vseocompdf. lt_descriptions = it_descriptions. LOOP AT lt_descriptions ASSIGNING . -clsname = is_key-clsname. ENDLOOP. " make sure to not damage VSEO* views by deleting texts of all components - an empty text must be kept!! SELECT * FROM vseocompdf INTO TABLE lt_components WHERE clsname = is_key-clsname AND version <> seoc_version_deleted AND state = seoc_state_implemented AND alias = seox_false ORDER BY clsname cmpname version. IF lt_components IS NOT INITIAL. SELECT SINGLE masterlang FROM tadir INTO lv_lang WHERE pgmid = 'R3TR' AND ( object = 'CLAS' OR object = 'INTF' ) AND obj_name = is_key-clsname. "#EC CI_GENBUFF IF sy-subrc <> 0. lv_lang = sy-langu. ENDIF. LOOP AT lt_components ASSIGNING . READ TABLE lt_descriptions TRANSPORTING NO FIELDS WITH KEY clsname = is_key-clsname cmpname = -cmpname. IF sy-subrc <> 0. ls_description-clsname = is_key-clsname. ls_description-cmpname = -cmpname. ls_description-langu = lv_lang. ls_description-descript = space. APPEND ls_description TO lt_descriptions. ENDIF. ENDLOOP. ENDIF. DELETE FROM seocompotx WHERE clsname = is_key-clsname."#EC CI_SUBRC INSERT seocompotx FROM TABLE lt_descriptions. "#EC CI_SUBRC ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~update_descriptions_sub. DATA lt_descriptions LIKE it_descriptions. DATA lt_subcomponents TYPE seo_subcomponents. DATA ls_description LIKE LINE OF it_descriptions. DATA lv_lang TYPE tadir-masterlang. FIELD-SYMBOLS LIKE LINE OF it_descriptions. FIELD-SYMBOLS TYPE vseosubcdf. lt_descriptions = it_descriptions. LOOP AT lt_descriptions ASSIGNING . -clsname = is_key-clsname. ENDLOOP. " make sure to not damage VSEO* views by deleting texts of all subcomponents - an empty text must be kept!! SELECT * FROM vseosubcdf INTO TABLE lt_subcomponents WHERE clsname = is_key-clsname AND version <> seoc_version_deleted ORDER BY clsname cmpname sconame version. IF lt_subcomponents IS NOT INITIAL. SELECT SINGLE masterlang FROM tadir INTO lv_lang WHERE pgmid = 'R3TR' AND ( object = 'CLAS' OR object = 'INTF' ) AND obj_name = is_key-clsname. "#EC CI_GENBUFF IF sy-subrc <> 0. lv_lang = sy-langu. ENDIF. LOOP AT lt_subcomponents ASSIGNING . READ TABLE lt_descriptions TRANSPORTING NO FIELDS WITH KEY clsname = is_key-clsname cmpname = -cmpname sconame = -sconame. IF sy-subrc <> 0. ls_description-clsname = is_key-clsname. ls_description-cmpname = -cmpname. ls_description-sconame = -sconame. ls_description-langu = lv_lang. ls_description-descript = space. APPEND ls_description TO lt_descriptions. ENDIF. ENDLOOP. ENDIF. DELETE FROM seosubcotx WHERE clsname = is_key-clsname."#EC CI_SUBRC INSERT seosubcotx FROM TABLE lt_descriptions. "#EC CI_SUBRC ENDMETHOD. METHOD zif_abapgit_oo_object_fnc~syntax_check. ASSERT 0 = 1. "Subclass responsibility ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_gui_jumper IMPLEMENTATION. METHOD jump_bw. DATA: lv_exit TYPE abap_bool, lv_tlogo TYPE c LENGTH 4, "rstlogo lv_objnm TYPE c LENGTH 40. "rsawbnobjnm lv_tlogo = is_item-obj_type. lv_objnm = is_item-obj_name. TRY. CALL METHOD ('CL_RSAWBN_AWB')=>('IS_SUPPORTED_NAVIGATION') EXPORTING i_tlogo = lv_tlogo i_fcode = 'DISPLAY' IMPORTING re_is_supported_fcode = lv_exit. IF lv_exit = abap_false. RETURN. ENDIF. CATCH cx_root. " Not a BW system RETURN. ENDTRY. TRY. CALL METHOD ('CL_RSAWBN_AWB')=>('NAVIGATE_FROM_APPLICATION') EXPORTING i_tlogo = lv_tlogo i_objnm = lv_objnm i_new_mode = iv_new_window IMPORTING e_exit_own_application = lv_exit. CATCH cx_root. " Older release without i_new_mode CALL METHOD ('CL_RSAWBN_AWB')=>('NAVIGATE_FROM_APPLICATION') EXPORTING i_tlogo = lv_tlogo i_objnm = lv_objnm IMPORTING e_exit_own_application = lv_exit. ENDTRY. rv_exit = lv_exit. ENDMETHOD. METHOD jump_tr. DATA: lv_e071_object TYPE e071-object, lv_e071_obj_name TYPE e071-obj_name. lv_e071_object = is_item-obj_type. lv_e071_obj_name = is_item-obj_name. CALL FUNCTION 'TR_OBJECT_JUMP_TO_TOOL' EXPORTING iv_action = 'SHOW' iv_pgmid = 'R3TR' iv_object = lv_e071_object iv_obj_name = lv_e071_obj_name EXCEPTIONS jump_not_possible = 1 OTHERS = 2. rv_exit = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD jump_wb. CALL FUNCTION 'RS_TOOL_ACCESS' EXPORTING operation = 'SHOW' object_name = is_item-obj_name object_type = is_item-obj_type devclass = is_item-devclass in_new_window = iv_new_window EXCEPTIONS not_executed = 1 invalid_object_type = 2 OTHERS = 3. rv_exit = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD jump_wb_line. IF 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 (iv_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 devclass = is_item-devclass include = iv_sub_obj_name position = iv_line_number in_new_window = iv_new_window EXCEPTIONS not_executed = 1 invalid_object_type = 2 OTHERS = 3. rv_exit = boolc( sy-subrc = 0 ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_jumper~jump. " WebGUI cannot open windows or ADT IF zcl_abapgit_ui_factory=>get_frontend_services( )->is_webgui( ) = abap_true. zcx_abapgit_exception=>raise( |Jump not possible in WebGUI| ). ENDIF. " Try all generic jump options " 1) ADT Jump rv_exit = zif_abapgit_gui_jumper~jump_adt( is_item = is_item iv_sub_obj_name = is_sub_item-obj_name iv_line_number = iv_line_number ). IF rv_exit = abap_true. RETURN. ENDIF. " 2) WB Jump with Line Number rv_exit = jump_wb_line( is_item = is_item iv_sub_obj_name = is_sub_item-obj_name iv_sub_obj_type = is_sub_item-obj_type iv_line_number = iv_line_number iv_new_window = iv_new_window ). IF rv_exit = abap_true. RETURN. ENDIF. " 3) WB Jump without Line Number rv_exit = jump_wb( is_item = is_item iv_new_window = iv_new_window ). IF rv_exit = abap_true. RETURN. ENDIF. " 4) Transport Tool Jump rv_exit = jump_tr( is_item ). IF rv_exit = abap_true. RETURN. ENDIF. " 5) BW Jump rv_exit = jump_bw( is_item = is_item iv_new_window = iv_new_window ). ENDMETHOD. METHOD zif_abapgit_gui_jumper~jump_abapgit. DATA lt_spagpa TYPE STANDARD TABLE OF rfc_spagpa. DATA ls_spagpa LIKE LINE OF lt_spagpa. DATA lv_save_sy_langu TYPE sy-langu. DATA lv_subrc TYPE syst-subrc. DATA lv_tcode TYPE tcode. DATA lv_langu_text TYPE string. DATA lv_msg TYPE c LENGTH 200. " https://blogs.sap.com/2017/01/13/logon-language-sy-langu-and-rfc/ lv_tcode = zcl_abapgit_services_abapgit=>get_abapgit_tcode( ). lv_save_sy_langu = sy-langu. SET LOCALE LANGUAGE iv_language. ls_spagpa-parid = zif_abapgit_definitions=>c_spagpa_param_repo_key. ls_spagpa-parval = iv_key. INSERT ls_spagpa INTO TABLE lt_spagpa. CALL FUNCTION 'ABAP4_CALL_TRANSACTION' DESTINATION 'NONE' STARTING NEW TASK 'ABAPGIT' EXPORTING tcode = lv_tcode TABLES spagpa_tab = lt_spagpa EXCEPTIONS communication_failure = 1 MESSAGE lv_msg system_failure = 2 MESSAGE lv_msg OTHERS = 3. lv_subrc = sy-subrc. SET LOCALE LANGUAGE lv_save_sy_langu. CASE lv_subrc. WHEN 1. lv_msg = |Communication error { lv_msg }|. WHEN 2. SELECT SINGLE sptxt FROM t002t INTO lv_langu_text WHERE spras = sy-langu AND sprsl = iv_language. IF sy-subrc <> 0. lv_langu_text = iv_language. ENDIF. lv_msg = |Language { lv_langu_text } ({ zcl_abapgit_convert=>language_sap1_to_sap2( iv_language ) })| && | is not installed|. WHEN 3. lv_msg = |{ lv_subrc }|. ENDCASE. IF lv_msg IS INITIAL. MESSAGE 'Repository opened in a new window' TYPE 'S'. ELSE. zcx_abapgit_exception=>raise( |Error starting transaction { lv_tcode }: { lv_msg }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_jumper~jump_adt. " Open object in ADT (if enabled) DATA lv_adt_jump_enabled TYPE abap_bool. lv_adt_jump_enabled = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_adt_jump_enabled( ). IF lv_adt_jump_enabled = abap_true. TRY. zcl_abapgit_adt_link=>jump( iv_obj_name = is_item-obj_name iv_obj_type = is_item-obj_type iv_sub_obj_name = iv_sub_obj_name iv_line_number = iv_line_number ). rv_exit = abap_true. CATCH zcx_abapgit_exception ##NO_HANDLER. " Use fallback ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_jumper~jump_batch_input. DATA lv_msg TYPE c LENGTH 80. IF iv_new_window = abap_true. CALL FUNCTION 'ABAP4_CALL_TRANSACTION' STARTING NEW TASK 'GIT' EXPORTING tcode = iv_tcode mode_val = 'E' TABLES using_tab = it_bdcdata EXCEPTIONS system_failure = 1 MESSAGE lv_msg communication_failure = 2 MESSAGE lv_msg resource_failure = 3 OTHERS = 4. ELSE. CALL FUNCTION 'ABAP4_CALL_TRANSACTION' EXPORTING tcode = iv_tcode mode_val = 'E' TABLES using_tab = it_bdcdata EXCEPTIONS OTHERS = 4. ENDIF. CASE sy-subrc. WHEN 1 OR 2. zcx_abapgit_exception=>raise( |Batch input error for transaction { iv_tcode }: { lv_msg }| ). WHEN 3 OR 4. zcx_abapgit_exception=>raise( |Batch input error for transaction { iv_tcode }| ). ENDCASE. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_adt_link IMPLEMENTATION. METHOD link_transport. * call to CL_CTS_ADT_TM_URI_BUILDER=>CREATE_ADT_URI replaced with logic that works on all systems, rv_link = |adt://{ sy-sysid }/sap/bc/adt/cts/transportrequests/{ iv_transport }|. ENDMETHOD. METHOD generate. DATA: lv_adt_link TYPE string. DATA: lo_adt_uri_mapper TYPE REF TO object. DATA: lo_adt_objref TYPE REF TO object. DATA: lo_adt_sub_objref TYPE REF TO object. DATA: lv_program TYPE progname. DATA: lv_include TYPE progname. FIELD-SYMBOLS: TYPE string. get_adt_objects_and_names( EXPORTING iv_obj_name = iv_obj_name iv_obj_type = iv_obj_type IMPORTING eo_adt_uri_mapper = lo_adt_uri_mapper eo_adt_objectref = lo_adt_objref ev_program = lv_program ev_include = lv_include ). TRY. IF iv_sub_obj_name IS NOT INITIAL. IF ( lv_program <> iv_obj_name AND lv_include IS INITIAL ) OR ( lv_program = lv_include AND iv_sub_obj_name IS NOT INITIAL ). lv_include = iv_sub_obj_name. ENDIF. CALL METHOD lo_adt_uri_mapper->('IF_ADT_URI_MAPPER~MAP_INCLUDE_TO_OBJREF') EXPORTING program = lv_program include = lv_include line = iv_line_number line_offset = 0 end_line = iv_line_number end_offset = 1 RECEIVING result = lo_adt_sub_objref. IF lo_adt_sub_objref IS NOT INITIAL. lo_adt_objref = lo_adt_sub_objref. ENDIF. ENDIF. ASSIGN ('LO_ADT_OBJREF->REF_DATA-URI') TO . ASSERT sy-subrc = 0. CONCATENATE 'adt://' sy-sysid INTO lv_adt_link. rv_result = lv_adt_link. CATCH cx_root. zcx_abapgit_exception=>raise( 'ADT Jump Error' ). ENDTRY. ENDMETHOD. METHOD get_adt_objects_and_names. DATA lv_obj_type TYPE trobjtype. DATA lv_obj_name TYPE trobj_name. DATA lo_object TYPE REF TO cl_wb_object. DATA lo_adt TYPE REF TO object. FIELD-SYMBOLS TYPE string. lv_obj_name = iv_obj_name. lv_obj_type = iv_obj_type. TRY. cl_wb_object=>create_from_transport_key( EXPORTING p_object = lv_obj_type p_obj_name = lv_obj_name RECEIVING p_wb_object = lo_object EXCEPTIONS OTHERS = 1 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'ADT Jump Error' ). ENDIF. CALL METHOD ('CL_ADT_TOOLS_CORE_FACTORY')=>('GET_INSTANCE') RECEIVING result = lo_adt. IF is_adt_jump_possible( io_object = lo_object io_adt = lo_adt ) = abap_false. zcx_abapgit_exception=>raise( 'ADT Jump Error' ). ENDIF. CALL METHOD lo_adt->('IF_ADT_TOOLS_CORE_FACTORY~GET_URI_MAPPER') RECEIVING result = eo_adt_uri_mapper. CALL METHOD eo_adt_uri_mapper->('IF_ADT_URI_MAPPER~MAP_WB_OBJECT_TO_OBJREF') EXPORTING wb_object = lo_object RECEIVING result = eo_adt_objectref. ASSIGN ('EO_ADT_OBJECTREF->REF_DATA-URI') TO . ASSERT sy-subrc = 0. CALL METHOD eo_adt_uri_mapper->('IF_ADT_URI_MAPPER~MAP_OBJREF_TO_INCLUDE') EXPORTING uri = IMPORTING program = ev_program include = ev_include. CATCH cx_root. zcx_abapgit_exception=>raise( 'ADT Jump Error' ). ENDTRY. ENDMETHOD. METHOD is_adt_jump_possible. DATA: lo_wb_request TYPE REF TO cl_wb_request, lo_adt_uri_mapper_vit TYPE REF TO object, lv_vit_wb_request TYPE abap_bool. cl_wb_request=>create_from_object_ref( EXPORTING p_wb_object = io_object RECEIVING p_wb_request = lo_wb_request EXCEPTIONS illegal_operation = 1 cancelled = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'ADT Jump Error' ). ENDIF. TRY. CALL METHOD io_adt->('IF_ADT_TOOLS_CORE_FACTORY~GET_URI_MAPPER_VIT') RECEIVING result = lo_adt_uri_mapper_vit. CALL METHOD lo_adt_uri_mapper_vit->('IF_ADT_URI_MAPPER_VIT~IS_VIT_WB_REQUEST') EXPORTING wb_request = lo_wb_request RECEIVING result = lv_vit_wb_request. rv_is_adt_jump_possible = boolc( NOT lv_vit_wb_request = abap_true ). CATCH cx_root. zcx_abapgit_exception=>raise( 'ADT Jump Error' ). ENDTRY. ENDMETHOD. METHOD jump. DATA lv_adt_link TYPE string. TRY. lv_adt_link = generate( iv_obj_name = iv_obj_name iv_obj_type = iv_obj_type iv_sub_obj_name = iv_sub_obj_name iv_line_number = iv_line_number ). zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = lv_adt_link ). CATCH cx_root. zcx_abapgit_exception=>raise( 'ADT Jump Error' ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enhs_hook_d IMPLEMENTATION. METHOD zif_abapgit_object_enhs~deserialize. DATA: lv_enh_shorttext TYPE string, ls_enh_hook_definition TYPE enh_hook_def, ls_hook_definition TYPE ty_hook_defifnition, li_enh_object TYPE REF TO if_enh_object, li_enh_object_docu TYPE REF TO if_enh_object_docu, lo_hookdef_tool TYPE REF TO cl_enh_tool_hook_def, lx_enh_root TYPE REF TO cx_enh_root. FIELD-SYMBOLS: TYPE enh_hook_def_ext. ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' CHANGING cg_data = lv_enh_shorttext ). ii_xml->read( EXPORTING iv_name = 'BADI_DATA' CHANGING cg_data = ls_hook_definition ). li_enh_object ?= ii_enh_spot_tool. li_enh_object_docu ?= ii_enh_spot_tool. TRY. li_enh_object_docu->set_shorttext( lv_enh_shorttext ). lo_hookdef_tool ?= ii_enh_spot_tool. lo_hookdef_tool->set_original_object( pgmid = ls_hook_definition-pgmid obj_name = ls_hook_definition-obj_name obj_type = ls_hook_definition-obj_type program = ls_hook_definition-program main_type = ls_hook_definition-main_type main_name = ls_hook_definition-main_name ). LOOP AT ls_hook_definition-def_hooks ASSIGNING . MOVE-CORRESPONDING TO ls_enh_hook_definition. lo_hookdef_tool->add_hook_def( ls_enh_hook_definition ). ENDLOOP. li_enh_object->save( ). li_enh_object->activate( ). li_enh_object->unlock( ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object_enhs~serialize. DATA: lo_hookdef_tool TYPE REF TO cl_enh_tool_hook_def, lv_enh_shorttext TYPE string, li_enh_object_docu TYPE REF TO if_enh_object_docu, ls_hook_definition TYPE ty_hook_defifnition. lo_hookdef_tool ?= ii_enh_spot_tool. li_enh_object_docu ?= ii_enh_spot_tool. lv_enh_shorttext = li_enh_object_docu->get_shorttext( ). ls_hook_definition-def_hooks = lo_hookdef_tool->get_hook_defs( ). lo_hookdef_tool->get_original_object( IMPORTING pgmid = ls_hook_definition-pgmid obj_name = ls_hook_definition-obj_name obj_type = ls_hook_definition-obj_type main_type = ls_hook_definition-main_type main_name = ls_hook_definition-main_name program = ls_hook_definition-program ). ii_xml->add( ig_data = ii_enh_spot_tool->get_tool( ) iv_name = 'TOOL' ). ii_xml->add( ig_data = lv_enh_shorttext iv_name = 'SHORTTEXT' ). ii_xml->add( ig_data = ls_hook_definition iv_name = 'BADI_DATA' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enhs_badi_d IMPLEMENTATION. METHOD zif_abapgit_object_enhs~deserialize. DATA: lv_parent TYPE enhspotcompositename, lt_enh_badi TYPE enh_badi_data_it, lo_badidef_tool TYPE REF TO cl_enh_tool_badi_def, lv_enh_shorttext TYPE string, li_enh_object TYPE REF TO if_enh_object, li_enh_object_docu TYPE REF TO if_enh_object_docu, lx_enh_root TYPE REF TO cx_enh_root. FIELD-SYMBOLS: LIKE LINE OF lt_enh_badi. ii_xml->read( EXPORTING iv_name = 'PARENT_COMP' CHANGING cg_data = lv_parent ). ii_xml->read( EXPORTING iv_name = 'BADI_DATA' CHANGING cg_data = lt_enh_badi ). ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' CHANGING cg_data = lv_enh_shorttext ). li_enh_object ?= ii_enh_spot_tool. li_enh_object_docu ?= ii_enh_spot_tool. TRY. li_enh_object_docu->set_shorttext( lv_enh_shorttext ). lo_badidef_tool ?= ii_enh_spot_tool. LOOP AT lt_enh_badi ASSIGNING . lo_badidef_tool->add_badi_def( ). ENDLOOP. li_enh_object->save( ). li_enh_object->activate( ). li_enh_object->unlock( ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object_enhs~serialize. DATA: lv_spot_name TYPE enhspotname, lv_parent TYPE enhspotcompositename, lt_enh_badi TYPE enh_badi_data_it, lo_badidef_tool TYPE REF TO cl_enh_tool_badi_def, lv_enh_shorttext TYPE string, li_enh_object_docu TYPE REF TO if_enh_object_docu. lo_badidef_tool ?= ii_enh_spot_tool. li_enh_object_docu ?= ii_enh_spot_tool. lv_enh_shorttext = li_enh_object_docu->get_shorttext( ). "get parent = composite enhs (ENHC) lv_parent = cl_r3standard_persistence=>enh_find_parent_composite( lv_spot_name ). "get subsequent BADI definitions lt_enh_badi = lo_badidef_tool->get_badi_defs( ). ii_xml->add( ig_data = ii_enh_spot_tool->get_tool( ) iv_name = 'TOOL' ). ii_xml->add( ig_data = lv_enh_shorttext iv_name = 'SHORTTEXT' ). ii_xml->add( ig_data = lv_parent iv_name = 'PARENT_COMP' ). ii_xml->add( ig_data = lt_enh_badi iv_name = 'BADI_DATA' ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enho_wdyn IMPLEMENTATION. METHOD constructor. ms_item = is_item. ENDMETHOD. METHOD zif_abapgit_object_enho~deserialize. DATA: ls_enh_data TYPE enhwdyn, li_tool TYPE REF TO if_enh_tool, lo_wdyn TYPE REF TO cl_enh_tool_wdy, lv_tool_type TYPE enhtooltype, lv_package TYPE devclass. FIELD-SYMBOLS: TYPE enhwdyc, TYPE enhwdyv. ii_xml->read( EXPORTING iv_name = 'TOOL' CHANGING cg_data = lv_tool_type ). ii_xml->read( EXPORTING iv_name = 'COMPONENT_DATA' CHANGING cg_data = ls_enh_data ). lv_package = iv_package. TRY. cl_enh_factory=>create_enhancement( EXPORTING enhname = |{ ms_item-obj_name }| enhtype = '' enhtooltype = lv_tool_type IMPORTING enhancement = li_tool CHANGING devclass = lv_package ). lo_wdyn ?= li_tool. lo_wdyn->initialize( ls_enh_data-component_name ). lo_wdyn->set_component_data( ls_enh_data-component_data ). LOOP AT ls_enh_data-controller_data ASSIGNING . lo_wdyn->set_controller_data( p_controller_name = -controller_name p_enh_data = ). ENDLOOP. LOOP AT ls_enh_data-view_data ASSIGNING . lo_wdyn->set_view_data( p_view_name = -view_name p_enh_data = ). ENDLOOP. lo_wdyn->if_enh_object~save( run_dark = abap_true ). lo_wdyn->if_enh_object~unlock( ). CATCH cx_root. TRY. lo_wdyn->if_enh_object~unlock( ). CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. ENDTRY. zcx_abapgit_exception=>raise( |error deserializing ENHO wdyn { ms_item-obj_name }| ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object_enho~serialize. DATA: lo_wdyn TYPE REF TO cl_enh_tool_wdy, lv_component_name TYPE wdy_component_name, ls_enh_data TYPE enhwdyn. lo_wdyn ?= ii_enh_tool. lv_component_name = lo_wdyn->get_component_name( ). TRY. lo_wdyn->get_all_data_for_comp( EXPORTING p_component_name = lv_component_name IMPORTING p_enh_data = ls_enh_data ). ii_xml->add( iv_name = 'TOOL' ig_data = ii_enh_tool->get_tool( ) ). ii_xml->add( iv_name = 'COMPONENT_DATA' ig_data = ls_enh_data ). CATCH cx_enh_not_found. zcx_abapgit_exception=>raise( |error serializing ENHO wdyn { ms_item-obj_name }| ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enho_wdyc IMPLEMENTATION. METHOD constructor. ms_item = is_item. ENDMETHOD. METHOD zif_abapgit_object_enho~deserialize. DATA: lv_enhname TYPE enhname, lo_wdyconf TYPE REF TO cl_wdr_cfg_enhancement, li_tool TYPE REF TO if_enh_tool, ls_obj TYPE wdy_config_key, lv_xml TYPE string, lt_data TYPE wdy_cfg_expl_data_tab, lv_package TYPE devclass. ii_xml->read( EXPORTING iv_name = 'ORIGINAL_OBJECT' CHANGING cg_data = ls_obj ). ii_xml->read( EXPORTING iv_name = 'ENHANCEMENT_DATA' CHANGING cg_data = lv_xml ). lv_enhname = ms_item-obj_name. lv_package = iv_package. TRY. cl_enh_factory=>create_enhancement( EXPORTING enhname = lv_enhname enhtype = '' enhtooltype = cl_wdr_cfg_enhancement=>tooltype IMPORTING enhancement = li_tool CHANGING devclass = lv_package ). lo_wdyconf ?= li_tool. CALL METHOD cl_wdr_cfg_persistence_utils=>('COMP_XML_TO_TABLES') EXPORTING xml_content = lv_xml IMPORTING expl_data_tab = lt_data. * only works on new ABAP versions, parameters differ between versions CALL METHOD lo_wdyconf->('SET_ENHANCEMENT_DATA') EXPORTING p_enh_data = lt_data. lo_wdyconf->if_enh_object~save( run_dark = abap_true ). lo_wdyconf->if_enh_object~unlock( ). CATCH cx_enh_root cx_static_check. TRY. lo_wdyconf->if_enh_object~unlock( ). CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. ENDTRY. zcx_abapgit_exception=>raise( 'error deserializing ENHO wdyconf' ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object_enho~serialize. DATA: lo_wdyconf TYPE REF TO cl_wdr_cfg_enhancement, lt_data TYPE wdy_cfg_expl_data_tab, ls_outline TYPE wdy_cfg_outline_data, ls_obj TYPE wdy_config_key, li_document TYPE REF TO if_ixml_document, li_element TYPE REF TO if_ixml_element. lo_wdyconf ?= ii_enh_tool. ls_obj = lo_wdyconf->get_original_object( ). ii_xml->add( iv_name = 'TOOL' ig_data = ii_enh_tool->get_tool( ) ). ii_xml->add( iv_name = 'ORIGINAL_OBJECT' ig_data = ls_obj ). * only works on new ABAP versions, parameters differ between versions CALL METHOD lo_wdyconf->('GET_ENHANCEMENT_DATA') EXPORTING p_scope = 1 IMPORTING p_enh_data = lt_data. CALL METHOD cl_wdr_cfg_persistence_utils=>('COMP_TABLES_TO_XML') EXPORTING outline_data = ls_outline expl_data_tab = lt_data IMPORTING element = li_element CHANGING document = li_document. ii_xml->add_xml( iv_name = 'ENHANCEMENT_DATA' ii_xml = li_element ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enho_intf IMPLEMENTATION. METHOD constructor. ms_item = is_item. mo_files = io_files. ENDMETHOD. METHOD zif_abapgit_object_enho~deserialize. DATA: lo_enh_intf TYPE REF TO cl_enh_tool_intf, li_tool TYPE REF TO if_enh_tool, lv_shorttext TYPE string, lv_class TYPE seoclsname, lv_enhname TYPE enhname, lv_package TYPE devclass, lx_enh_root TYPE REF TO cx_enh_root. ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' CHANGING cg_data = lv_shorttext ). ii_xml->read( EXPORTING iv_name = 'CLASS' CHANGING cg_data = lv_class ). lv_enhname = ms_item-obj_name. lv_package = iv_package. TRY. cl_enh_factory=>create_enhancement( EXPORTING enhname = lv_enhname enhtype = '' enhtooltype = cl_enh_tool_intf=>tooltype IMPORTING enhancement = li_tool CHANGING devclass = lv_package ). lo_enh_intf ?= li_tool. lo_enh_intf->if_enh_object_docu~set_shorttext( lv_shorttext ). lo_enh_intf->set_class( lv_class ). zcl_abapgit_object_enho_clif=>deserialize( io_xml = ii_xml io_clif = lo_enh_intf ). lo_enh_intf->if_enh_object~save( run_dark = abap_true ). lo_enh_intf->if_enh_object~unlock( ). CATCH cx_enh_root INTO lx_enh_root. TRY. lo_enh_intf->if_enh_object~unlock( ). CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. ENDTRY. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object_enho~serialize. DATA: lo_enh_intf TYPE REF TO cl_enh_tool_intf, lv_class TYPE seoclsname, lv_shorttext TYPE string. lo_enh_intf ?= ii_enh_tool. lv_shorttext = lo_enh_intf->if_enh_object_docu~get_shorttext( ). lo_enh_intf->get_class( IMPORTING class_name = lv_class ). ii_xml->add( iv_name = 'TOOL' ig_data = ii_enh_tool->get_tool( ) ). ii_xml->add( ig_data = lv_shorttext iv_name = 'SHORTTEXT' ). ii_xml->add( iv_name = 'CLASS' ig_data = lv_class ). zcl_abapgit_object_enho_clif=>serialize( io_xml = ii_xml io_clif = lo_enh_intf ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enho_hook IMPLEMENTATION. METHOD add_sources. DATA lv_source TYPE string. DATA ls_file LIKE LINE OF ct_files. FIELD-SYMBOLS LIKE LINE OF ct_enhancements. LOOP AT ct_enhancements ASSIGNING . " Use hash as filename since full_name is very long CLEAR ls_file. ls_file-name = -full_name. ls_file-file = substring( val = zcl_abapgit_hash=>sha1_string( -full_name ) len = 8 ). INSERT ls_file INTO TABLE ct_files. " Add full name as comment and put code between enhancement statements lv_source = c_enhancement. REPLACE '*' IN lv_source WITH ms_item-obj_name. INSERT lv_source INTO -source INDEX 1. lv_source = |"Name: { -full_name }|. INSERT lv_source INTO -source INDEX 1. APPEND c_endenhancement TO -source. mo_files->add_abap( iv_extra = ls_file-file it_abap = -source ). CLEAR -source. ENDLOOP. ENDMETHOD. METHOD constructor. ms_item = is_item. mo_files = io_files. ENDMETHOD. METHOD hook_impl_deserialize. FIELD-SYMBOLS: LIKE LINE OF ct_impl, TYPE string, TYPE i, LIKE LINE OF it_spaces. LOOP AT ct_impl ASSIGNING . READ TABLE it_spaces ASSIGNING WITH KEY full_name = -full_name. IF sy-subrc = 0. LOOP AT -source ASSIGNING . READ TABLE -spaces ASSIGNING INDEX sy-tabix. IF sy-subrc = 0 AND > 0. DO TIMES. CONCATENATE space INTO RESPECTING BLANKS. ENDDO. ENDIF. ENDLOOP. ENDIF. ENDLOOP. ENDMETHOD. METHOD read_sources. DATA lv_source TYPE string. DATA ls_file LIKE LINE OF ct_files. DATA lv_from TYPE i. DATA lv_to TYPE i. FIELD-SYMBOLS LIKE LINE OF ct_enhancements. LOOP AT ct_enhancements ASSIGNING . READ TABLE ct_files INTO ls_file WITH TABLE KEY name = -full_name. IF sy-subrc = 0. -source = mo_files->read_abap( iv_extra = ls_file-file ). " Get code between enhancement statements LOOP AT -source INTO lv_source. IF lv_source CP c_enhancement. lv_from = sy-tabix. ENDIF. IF lv_source CP c_endenhancement. lv_to = sy-tabix. ENDIF. ENDLOOP. DELETE -source FROM lv_to. DELETE -source TO lv_from. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object_enho~deserialize. DATA: lv_shorttext TYPE string, lo_hook_impl TYPE REF TO cl_enh_tool_hook_impl, li_tool TYPE REF TO if_enh_tool, lv_enhname TYPE enhname, lv_package TYPE devclass, ls_original_object TYPE enh_hook_admin, lt_spaces TYPE ty_spaces_tt, lt_files TYPE ty_files, lt_enhancements TYPE enh_hook_impl_it, lx_enh_root TYPE REF TO cx_enh_root. FIELD-SYMBOLS: LIKE LINE OF lt_enhancements. ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' CHANGING cg_data = lv_shorttext ). ii_xml->read( EXPORTING iv_name = 'ORIGINAL_OBJECT' CHANGING cg_data = ls_original_object ). ii_xml->read( EXPORTING iv_name = 'ENHANCEMENTS' CHANGING cg_data = lt_enhancements ). ii_xml->read( EXPORTING iv_name = 'FILES' CHANGING cg_data = lt_files ). ii_xml->read( EXPORTING iv_name = 'SPACES' CHANGING cg_data = lt_spaces ). " todo: kept for compatibility, remove after grace period #3680 hook_impl_deserialize( EXPORTING it_spaces = lt_spaces CHANGING ct_impl = lt_enhancements ). read_sources( CHANGING ct_enhancements = lt_enhancements ct_files = lt_files ). lv_enhname = ms_item-obj_name. lv_package = iv_package. TRY. cl_enh_factory=>create_enhancement( EXPORTING enhname = lv_enhname enhtype = cl_abstract_enh_tool_redef=>credefinition enhtooltype = cl_enh_tool_hook_impl=>tooltype IMPORTING enhancement = li_tool CHANGING devclass = lv_package ). lo_hook_impl ?= li_tool. lo_hook_impl->if_enh_object_docu~set_shorttext( lv_shorttext ). lo_hook_impl->set_original_object( pgmid = ls_original_object-pgmid obj_name = ls_original_object-org_obj_name obj_type = ls_original_object-org_obj_type program = ls_original_object-programname main_type = ls_original_object-org_main_type main_name = ls_original_object-org_main_name ). lo_hook_impl->set_include_bound( ls_original_object-include_bound ). LOOP AT lt_enhancements ASSIGNING . lo_hook_impl->add_hook_impl( overwrite = -overwrite method = -method enhmode = -enhmode full_name = -full_name source = -source spot = -spotname parent_full_name = -parent_full_name ). ENDLOOP. lo_hook_impl->if_enh_object~save( run_dark = abap_true ). lo_hook_impl->if_enh_object~unlock( ). CATCH cx_enh_root INTO lx_enh_root. TRY. lo_hook_impl->if_enh_object~unlock( ). CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. ENDTRY. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object_enho~serialize. DATA: lv_shorttext TYPE string, lo_hook_impl TYPE REF TO cl_enh_tool_hook_impl, ls_original_object TYPE enh_hook_admin, lt_spaces TYPE ty_spaces_tt, lt_files TYPE ty_files, lt_enhancements TYPE enh_hook_impl_it. FIELD-SYMBOLS: LIKE LINE OF lt_enhancements. lo_hook_impl ?= ii_enh_tool. lv_shorttext = lo_hook_impl->if_enh_object_docu~get_shorttext( ). lo_hook_impl->get_original_object( IMPORTING pgmid = ls_original_object-pgmid obj_name = ls_original_object-org_obj_name obj_type = ls_original_object-org_obj_type main_type = ls_original_object-org_main_type main_name = ls_original_object-org_main_name program = ls_original_object-programname ). ls_original_object-include_bound = lo_hook_impl->get_include_bound( ). lt_enhancements = lo_hook_impl->get_hook_impls( ). LOOP AT lt_enhancements ASSIGNING . CLEAR: -extid, -id. ENDLOOP. add_sources( CHANGING ct_enhancements = lt_enhancements ct_files = lt_files ). ii_xml->add( iv_name = 'TOOL' ig_data = ii_enh_tool->get_tool( ) ). ii_xml->add( iv_name = 'SHORTTEXT' ig_data = lv_shorttext ). ii_xml->add( iv_name = 'ORIGINAL_OBJECT' ig_data = ls_original_object ). ii_xml->add( iv_name = 'ENHANCEMENTS' ig_data = lt_enhancements ). ii_xml->add( iv_name = 'FILES' ig_data = lt_files ). ii_xml->add( iv_name = 'SPACES' ig_data = lt_spaces ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enho_fugr IMPLEMENTATION. METHOD constructor. ms_item = is_item. mo_files = io_files. ENDMETHOD. METHOD zif_abapgit_object_enho~deserialize. DATA: lo_fugrdata TYPE REF TO cl_enh_tool_fugr, ls_enha_data TYPE enhfugrdata, li_tool TYPE REF TO if_enh_tool, lv_tool TYPE enhtooltype, lv_package TYPE devclass, lx_enh_root TYPE REF TO cx_enh_root. FIELD-SYMBOLS: TYPE enhfugrfuncdata. ii_xml->read( EXPORTING iv_name = 'TOOL' CHANGING cg_data = lv_tool ). ii_xml->read( EXPORTING iv_name = 'FUGRDATA' CHANGING cg_data = ls_enha_data ). lv_package = iv_package. TRY. cl_enh_factory=>create_enhancement( EXPORTING enhname = |{ ms_item-obj_name }| enhtype = '' enhtooltype = lv_tool IMPORTING enhancement = li_tool CHANGING devclass = lv_package ). lo_fugrdata ?= li_tool. lo_fugrdata->set_fugr( ls_enha_data-fugr ). LOOP AT ls_enha_data-enh_fubas ASSIGNING . lo_fugrdata->set_func_data( func_name = -fuba func_enhadata = ). ENDLOOP. lo_fugrdata->if_enh_object~save( run_dark = abap_true ). lo_fugrdata->if_enh_object~unlock( ). CATCH cx_enh_root INTO lx_enh_root. TRY. lo_fugrdata->if_enh_object~unlock( ). CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. ENDTRY. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object_enho~serialize. DATA: lo_fugrdata TYPE REF TO cl_enh_tool_fugr, lv_fugr_name TYPE rs38l-area, ls_enha_data TYPE enhfugrdata. FIELD-SYMBOLS: TYPE enhfugrparamdocu. lo_fugrdata ?= ii_enh_tool. lo_fugrdata->get_fugr( IMPORTING fugr_name = lv_fugr_name ). TRY. lo_fugrdata->get_all_data_for_fugr( EXPORTING fugr_name = lv_fugr_name IMPORTING enha_data = ls_enha_data ). LOOP AT ls_enha_data-docuobjs ASSIGNING . CLEAR: -shorttext, -longtext. ENDLOOP. CATCH cx_enh_not_found. zcx_abapgit_exception=>raise( |error deserializing ENHO fugrdata { ms_item-obj_name }| ). ENDTRY. ii_xml->add( iv_name = 'TOOL' ig_data = lo_fugrdata->if_enh_tool~get_tool( ) ). ii_xml->add( iv_name = 'FUGRDATA' ig_data = ls_enha_data ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enho_clif IMPLEMENTATION. METHOD deserialize. DATA: lt_tab_attributes TYPE enhclasstabattrib, lt_tab_types TYPE enhtype_tab, lt_tab_methods TYPE enhnewmeth_tab, ls_type_line TYPE vseotype, ls_header TYPE vseomethod, ls_param TYPE vseomepara, ls_exc TYPE vseoexcep, lt_tab_eventdata TYPE enhevent_tab, ls_event_line TYPE vseoevent, ls_event_param TYPE vseoeparam. FIELD-SYMBOLS: LIKE LINE OF lt_tab_types, LIKE LINE OF lt_tab_methods, LIKE LINE OF -meth_param, LIKE LINE OF lt_tab_eventdata, LIKE LINE OF -meth_exc, LIKE LINE OF -event_param. io_xml->read( EXPORTING iv_name = 'TAB_ATTRIBUTES' CHANGING cg_data = lt_tab_attributes ). io_xml->read( EXPORTING iv_name = 'TAB_TYPES' CHANGING cg_data = lt_tab_types ). io_xml->read( EXPORTING iv_name = 'TAB_METHODS' CHANGING cg_data = lt_tab_methods ). io_xml->read( EXPORTING iv_name = 'TAB_EVENTDATA' CHANGING cg_data = lt_tab_eventdata ). LOOP AT lt_tab_types ASSIGNING . MOVE-CORRESPONDING TO ls_type_line. TRY. io_clif->add_change_enha_type( type_line = ls_type_line ). CATCH cx_enh_mod_not_allowed cx_enh_is_not_enhanceable. " TODO ENDTRY. ENDLOOP. io_clif->set_enhattributes( lt_tab_attributes ). * SAP standard SET_ENH_NEW_METHOS does not work LOOP AT lt_tab_methods ASSIGNING . MOVE-CORRESPONDING -meth_header TO ls_header. io_clif->add_change_new_enh_method( methkey = -methkey method_header = ls_header ). * parameters LOOP AT -meth_param ASSIGNING . MOVE-CORRESPONDING TO ls_param. io_clif->add_change_enh_methparam( methname = -methkey-cmpname param_line = ls_param ). ENDLOOP. * exceptions LOOP AT -meth_exc ASSIGNING . MOVE-CORRESPONDING TO ls_exc. io_clif->add_change_enh_methexc( methname = -methkey-cmpname except_line = ls_exc ). ENDLOOP. ENDLOOP. " events are renumbered based on LOOP AT lt_tab_eventdata ASSIGNING . MOVE-CORRESPONDING -event_header TO ls_event_line. io_clif->add_change_enha_event( event_key = -eventkey event_line = ls_event_line ). * parameters LOOP AT -event_param ASSIGNING . MOVE-CORRESPONDING TO ls_event_param. io_clif->add_change_enh_eventparam( eventname = -eventkey-cmpname event_param = ls_event_param ). ENDLOOP. ENDLOOP. ENDMETHOD. METHOD serialize. DATA: lt_tab_attributes TYPE enhclasstabattrib, lt_tab_types TYPE enhtype_tab, lt_tab_methods TYPE enhnewmeth_tab, lt_tab_eventdata TYPE enhevent_tab, lv_editorder TYPE i. FIELD-SYMBOLS: LIKE LINE OF lt_tab_attributes, LIKE LINE OF lt_tab_types, LIKE LINE OF lt_tab_methods, LIKE LINE OF -meth_param, LIKE LINE OF -meth_exc, LIKE LINE OF lt_tab_eventdata, LIKE LINE OF -event_param. io_clif->get_enhattributes( IMPORTING tab_attributes = lt_tab_attributes ). io_clif->get_enhatypes( IMPORTING tab_types = lt_tab_types ). io_clif->get_enh_new_methodes( IMPORTING tab_methodes = lt_tab_methods ). io_clif->get_enhevents( IMPORTING tab_eventdata = lt_tab_eventdata ). LOOP AT lt_tab_attributes ASSIGNING . CLEAR: -author, -createdon, -changedby, -changedon, -descript_id. ENDLOOP. LOOP AT lt_tab_types ASSIGNING . CLEAR: -author, -createdon, -changedby, -changedon, -descript_id. ENDLOOP. lv_editorder = 0. SORT lt_tab_methods BY meth_header-editorder. LOOP AT lt_tab_methods ASSIGNING . CLEAR: -meth_header-author, -meth_header-createdon, -meth_header-changedby, -meth_header-changedon, -meth_header-descript_id. lv_editorder = lv_editorder + 1. -meth_header-editorder = lv_editorder. LOOP AT -meth_param ASSIGNING . CLEAR: -author, -createdon, -changedby, -changedon, -descript_id. ENDLOOP. LOOP AT -meth_exc ASSIGNING . CLEAR: -author, -createdon, -changedby, -changedon, -descript_id. ENDLOOP. ENDLOOP. LOOP AT lt_tab_eventdata ASSIGNING . CLEAR: -event_header-author, -event_header-createdon, -event_header-changedby, -event_header-changedon, -event_header-descript_id. LOOP AT -event_param ASSIGNING . CLEAR: -author, -createdon, -changedby, -changedon, -descript_id. ENDLOOP. ENDLOOP. io_xml->add( iv_name = 'TAB_ATTRIBUTES' ig_data = lt_tab_attributes ). io_xml->add( iv_name = 'TAB_TYPES' ig_data = lt_tab_types ). io_xml->add( iv_name = 'TAB_METHODS' ig_data = lt_tab_methods ). io_xml->add( iv_name = 'TAB_EVENTDATA' ig_data = lt_tab_eventdata ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enho_class IMPLEMENTATION. METHOD constructor. ms_item = is_item. mo_files = io_files. ENDMETHOD. METHOD deserialize_includes. DATA: lt_tab_methods TYPE enhnewmeth_tab, lv_editorder TYPE n LENGTH 3, lv_methname TYPE seocpdname, lt_abap TYPE rswsourcet, lx_enh_root TYPE REF TO cx_enh_root, lv_new_em TYPE abap_bool, lt_files TYPE zif_abapgit_git_definitions=>ty_files_tt. FIELD-SYMBOLS: LIKE LINE OF lt_tab_methods, TYPE zif_abapgit_git_definitions=>ty_file. ii_xml->read( EXPORTING iv_name = 'TAB_METHODS' CHANGING cg_data = lt_tab_methods ). lv_new_em = abap_false. lt_files = mo_files->get_files( ). LOOP AT lt_files ASSIGNING WHERE filename CS 'enho.em_'. lv_new_em = abap_true. EXIT. ENDLOOP. SORT lt_tab_methods BY meth_header-editorder. LOOP AT lt_tab_methods ASSIGNING . lv_methname = -methkey-cmpname. IF lv_new_em = abap_true. lt_abap = mo_files->read_abap( iv_extra = 'em_' && lv_methname ). ELSE. " old way lv_editorder = -meth_header-editorder. lt_abap = mo_files->read_abap( iv_extra = 'em' && lv_editorder ). ENDIF. TRY. io_class->add_change_new_method_source( clsname = -methkey-clsname methname = lv_methname methsource = lt_abap ). CATCH cx_enh_root INTO lx_enh_root. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDLOOP. ENDMETHOD. METHOD serialize_includes. DATA: lt_includes TYPE enhnewmeth_tabincl_plus_enha, lt_source TYPE TABLE OF abaptxt255, lv_include TYPE syrepid. FIELD-SYMBOLS: LIKE LINE OF lt_includes. lt_includes = io_class->get_enh_method_includes( ). LOOP AT lt_includes ASSIGNING . lv_include = io_class->if_enh_tool~get_name( ). TRANSLATE lv_include USING ' ='. lv_include+30 = 'EM'. lv_include+32(8) = -includenr. CALL FUNCTION 'RPY_PROGRAM_READ' EXPORTING program_name = lv_include with_includelist = abap_false with_lowercase = abap_true TABLES source_extended = lt_source EXCEPTIONS cancelled = 1 not_found = 2 permission_error = 3 OTHERS = 4. IF sy-subrc = 0. mo_files->add_abap( iv_extra = |EM_{ -cpdname }| it_abap = lt_source ). ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_object_enho~deserialize. DATA: lo_enh_class TYPE REF TO cl_enh_tool_class, lt_owr TYPE enhmeth_tabkeys, lt_pre TYPE enhmeth_tabkeys, lt_post TYPE enhmeth_tabkeys, lt_source TYPE rswsourcet, li_tool TYPE REF TO if_enh_tool, lv_shorttext TYPE string, lv_class TYPE seoclsname, lv_enhname TYPE enhname, lv_package TYPE devclass, lx_enh_root TYPE REF TO cx_enh_root. ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' CHANGING cg_data = lv_shorttext ). ii_xml->read( EXPORTING iv_name = 'OWR_METHODS' CHANGING cg_data = lt_owr ). ii_xml->read( EXPORTING iv_name = 'PRE_METHODS' CHANGING cg_data = lt_pre ). ii_xml->read( EXPORTING iv_name = 'POST_METHODS' CHANGING cg_data = lt_post ). ii_xml->read( EXPORTING iv_name = 'CLASS' CHANGING cg_data = lv_class ). lt_source = mo_files->read_abap( ). lv_enhname = ms_item-obj_name. lv_package = iv_package. TRY. cl_enh_factory=>create_enhancement( EXPORTING enhname = lv_enhname enhtype = '' enhtooltype = cl_enh_tool_class=>tooltype IMPORTING enhancement = li_tool CHANGING devclass = lv_package ). lo_enh_class ?= li_tool. lo_enh_class->if_enh_object_docu~set_shorttext( lv_shorttext ). lo_enh_class->set_class( lv_class ). lo_enh_class->set_owr_methods( version = 'I' owr_methods = lt_owr ). lo_enh_class->set_pre_methods( version = 'I' pre_methods = lt_pre ). lo_enh_class->set_post_methods( version = 'I' post_methods = lt_post ). lo_enh_class->set_eimp_include( version = 'I' eimp_source = lt_source ). zcl_abapgit_object_enho_clif=>deserialize( io_xml = ii_xml io_clif = lo_enh_class ). deserialize_includes( ii_xml = ii_xml io_class = lo_enh_class ). lo_enh_class->if_enh_object~save( run_dark = abap_true ). lo_enh_class->if_enh_object~unlock( ). CATCH cx_enh_root INTO lx_enh_root. TRY. lo_enh_class->if_enh_object~unlock( ). CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. ENDTRY. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object_enho~serialize. DATA: lo_enh_class TYPE REF TO cl_enh_tool_class, lt_owr TYPE enhmeth_tabkeys, lt_pre TYPE enhmeth_tabkeys, lt_post TYPE enhmeth_tabkeys, lt_source TYPE rswsourcet, lv_class TYPE seoclsname, lv_shorttext TYPE string. lo_enh_class ?= ii_enh_tool. lv_shorttext = lo_enh_class->if_enh_object_docu~get_shorttext( ). lt_owr = lo_enh_class->get_owr_methods( ). lt_pre = lo_enh_class->get_pre_methods( ). lt_post = lo_enh_class->get_post_methods( ). lt_source = lo_enh_class->get_eimp_include( ). lo_enh_class->get_class( IMPORTING class_name = lv_class ). ii_xml->add( iv_name = 'TOOL' ig_data = ii_enh_tool->get_tool( ) ). ii_xml->add( ig_data = lv_shorttext iv_name = 'SHORTTEXT' ). ii_xml->add( iv_name = 'CLASS' ig_data = lv_class ). ii_xml->add( iv_name = 'OWR_METHODS' ig_data = lt_owr ). ii_xml->add( iv_name = 'PRE_METHODS' ig_data = lt_pre ). ii_xml->add( iv_name = 'POST_METHODS' ig_data = lt_post ). mo_files->add_abap( lt_source ). zcl_abapgit_object_enho_clif=>serialize( io_xml = ii_xml io_clif = lo_enh_class ). serialize_includes( lo_enh_class ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_enho_badi IMPLEMENTATION. METHOD constructor. ms_item = is_item. ENDMETHOD. METHOD zif_abapgit_object_enho~deserialize. DATA: lv_spot_name TYPE enhspotname, lv_shorttext TYPE string, lv_enhname TYPE enhname, lo_badi TYPE REF TO cl_enh_tool_badi_impl, li_tool TYPE REF TO if_enh_tool, lv_package TYPE devclass, lt_impl TYPE enh_badi_impl_data_it, lx_enh_root TYPE REF TO cx_enh_root. FIELD-SYMBOLS: LIKE LINE OF lt_impl. ii_xml->read( EXPORTING iv_name = 'SHORTTEXT' CHANGING cg_data = lv_shorttext ). ii_xml->read( EXPORTING iv_name = 'SPOT_NAME' CHANGING cg_data = lv_spot_name ). ii_xml->read( EXPORTING iv_name = 'IMPL' CHANGING cg_data = lt_impl ). lv_enhname = ms_item-obj_name. lv_package = iv_package. TRY. cl_enh_factory=>create_enhancement( EXPORTING enhname = lv_enhname enhtype = cl_abstract_enh_tool_redef=>credefinition enhtooltype = cl_enh_tool_badi_impl=>tooltype IMPORTING enhancement = li_tool CHANGING devclass = lv_package ). lo_badi ?= li_tool. lo_badi->set_spot_name( lv_spot_name ). lo_badi->if_enh_object_docu~set_shorttext( lv_shorttext ). LOOP AT lt_impl ASSIGNING . lo_badi->add_implementation( ). ENDLOOP. lo_badi->if_enh_object~save( run_dark = abap_true ). lo_badi->if_enh_object~unlock( ). CATCH cx_enh_root INTO lx_enh_root. TRY. lo_badi->if_enh_object~unlock( ). CATCH cx_sy_ref_is_initial cx_enh_mod_not_allowed ##NO_HANDLER. ENDTRY. zcx_abapgit_exception=>raise_with_text( lx_enh_root ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object_enho~serialize. DATA: lo_badi_impl TYPE REF TO cl_enh_tool_badi_impl, lv_spot_name TYPE enhspotname, lv_shorttext TYPE string, lt_impl TYPE enh_badi_impl_data_it. FIELD-SYMBOLS: LIKE LINE OF lt_impl, LIKE LINE OF -filter_values, LIKE LINE OF -filters. lo_badi_impl ?= ii_enh_tool. lv_shorttext = lo_badi_impl->if_enh_object_docu~get_shorttext( ). lv_spot_name = lo_badi_impl->get_spot_name( ). lt_impl = lo_badi_impl->get_implementations( ). LOOP AT lt_impl ASSIGNING . * make sure the XML serialization does not dump, field type = N LOOP AT -filter_values ASSIGNING . IF -filter_numeric_value1 CA space. CLEAR -filter_numeric_value1. ENDIF. ENDLOOP. LOOP AT -filters ASSIGNING . IF -filter_numeric_value1 CA space. CLEAR -filter_numeric_value1. ENDIF. ENDLOOP. ENDLOOP. ii_xml->add( iv_name = 'TOOL' ig_data = ii_enh_tool->get_tool( ) ). ii_xml->add( ig_data = lv_shorttext iv_name = 'SHORTTEXT' ). ii_xml->add( iv_name = 'SPOT_NAME' ig_data = lv_spot_name ). ii_xml->add( iv_name = 'IMPL' ig_data = lt_impl ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ecatt_val_obj_upl IMPLEMENTATION. METHOD get_business_msgs_from_dom. " downport from CL_APL_ECATT_VO_UPLOAD DATA: li_section TYPE REF TO if_ixml_element, lt_buss_msg_ref TYPE zif_abapgit_ecatt=>ty_bus_msgs, lv_exception_occurred TYPE etonoff, lo_ecatt_vo TYPE REF TO object. FIELD-SYMBOLS: TYPE any. li_section = template_over_all->find_from_name_ns( 'ETVO_MSG' ). IF NOT li_section IS INITIAL. CALL FUNCTION 'SDIXML_DOM_TO_DATA' EXPORTING data_as_dom = li_section IMPORTING dataobject = lt_buss_msg_ref EXCEPTIONS illegal_object = 1 OTHERS = 2. IF sy-subrc <> 0. CLEAR lt_buss_msg_ref. ENDIF. ENDIF. ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_vo = . TRY. CALL METHOD lo_ecatt_vo->('SET_BUSSINESS_MSG') EXPORTING im_buss_msg_ref = lt_buss_msg_ref. CATCH cx_ecatt_apl INTO exception_to_raise. lv_exception_occurred = 'X'. ENDTRY. IF lv_exception_occurred = 'X'. raise_upload_exception( previous = exception_to_raise ). ENDIF. ENDMETHOD. METHOD get_impl_detail_from_dom. " downport from CL_APL_ECATT_VO_UPLOAD DATA: li_section TYPE REF TO if_ixml_element, ls_impl_details TYPE zif_abapgit_ecatt=>ty_impl_det, lv_exception_occurred TYPE etonoff, lo_ecatt_vo TYPE REF TO object. FIELD-SYMBOLS: TYPE any. li_section = template_over_all->find_from_name_ns( 'IMPL_DET' ). IF NOT li_section IS INITIAL. CALL FUNCTION 'SDIXML_DOM_TO_DATA' EXPORTING data_as_dom = li_section IMPORTING dataobject = ls_impl_details EXCEPTIONS illegal_object = 1 OTHERS = 2. IF sy-subrc <> 0. CLEAR ls_impl_details. ENDIF. ENDIF. ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_vo = . TRY. CALL METHOD lo_ecatt_vo->('SET_IMPL_DETAILS') EXPORTING im_impl_details = ls_impl_details. CATCH cx_ecatt_apl INTO exception_to_raise. lv_exception_occurred = 'X'. ENDTRY. IF lv_exception_occurred = 'X'. raise_upload_exception( previous = exception_to_raise ). ENDIF. ENDMETHOD. METHOD get_vo_flags_from_dom. " downport from CL_APL_ECATT_VO_UPLOAD DATA: li_section TYPE REF TO if_ixml_element, lv_error_prio TYPE zif_abapgit_ecatt=>ty_error_prio, lv_invert_validation TYPE zif_abapgit_ecatt=>ty_invert_validation, lv_exception_occurred TYPE etonoff, lo_ecatt_vo TYPE REF TO object. FIELD-SYMBOLS: TYPE any. li_section = template_over_all->find_from_name_ns( 'INVERT_VALIDATION' ). IF NOT li_section IS INITIAL. CALL FUNCTION 'SDIXML_DOM_TO_DATA' EXPORTING data_as_dom = li_section IMPORTING dataobject = lv_invert_validation EXCEPTIONS illegal_object = 1 OTHERS = 2. IF sy-subrc <> 0. CLEAR lv_invert_validation. ENDIF. ENDIF. ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_vo = . TRY. CALL METHOD lo_ecatt_vo->('SET_INVERT_VALIDATION_FLAG') EXPORTING im_invert_validation = lv_invert_validation. CATCH cx_ecatt_apl INTO exception_to_raise. lv_exception_occurred = 'X'. ENDTRY. li_section = template_over_all->find_from_name_ns( 'ERROR_PRIORITY' ). IF NOT li_section IS INITIAL. CALL FUNCTION 'SDIXML_DOM_TO_DATA' EXPORTING data_as_dom = li_section IMPORTING dataobject = lv_error_prio EXCEPTIONS illegal_object = 1 OTHERS = 2. IF sy-subrc <> 0. CLEAR lv_invert_validation. ENDIF. ENDIF. TRY. CALL METHOD lo_ecatt_vo->('SET_ERROR_PRIORITY') EXPORTING im_error_prio = lv_error_prio. CATCH cx_ecatt_apl INTO exception_to_raise. lv_exception_occurred = 'X'. ENDTRY. IF lv_exception_occurred = 'X'. raise_upload_exception( previous = exception_to_raise ). ENDIF. ENDMETHOD. METHOD upload. " We inherit from CL_APL_ECATT_UPLOAD because CL_APL_ECATT_VO_UPLOAD " doesn't exist in 702 " downport from CL_APL_ECATT_VO_UPLOAD DATA: lx_ex TYPE REF TO cx_ecatt_apl, lv_exists TYPE etonoff, lv_exc_occ TYPE etonoff, ls_tadir TYPE tadir, lo_ecatt_vo TYPE REF TO object, lo_params TYPE REF TO cl_apl_ecatt_params. FIELD-SYMBOLS: TYPE any, TYPE data, TYPE data, TYPE data. TRY. ch_object-i_devclass = ch_object-d_devclass. ASSIGN COMPONENT 'D_AKH' OF STRUCTURE ch_object TO . " doesn't exist in 702 ASSIGN COMPONENT 'I_AKH' OF STRUCTURE ch_object TO . " doesn't exist in 702 IF IS ASSIGNED AND IS ASSIGNED. = . ENDIF. super->upload( CHANGING ch_object = ch_object ). upload_data_from_stream( ch_object-filename ). CATCH cx_ecatt_apl INTO lx_ex. IF template_over_all IS INITIAL. RAISE EXCEPTION lx_ex. ELSE. lv_exc_occ = 'X'. ENDIF. ENDTRY. TRY. CALL METHOD ('GET_ATTRIBUTES_FROM_DOM_NEW') " doesn't exit in 702 CHANGING ch_object = ch_object. CATCH cx_ecatt_apl INTO lx_ex. lv_exc_occ = 'X'. ENDTRY. ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_vo = . ASSIGN lo_ecatt_vo->('PARAMS') TO . ASSERT sy-subrc = 0. lo_params = . TRY. get_impl_detail_from_dom( ). CATCH cx_ecatt_apl INTO lx_ex. lv_exc_occ = 'X'. ENDTRY. TRY. get_vo_flags_from_dom( ). CATCH cx_ecatt_apl INTO lx_ex. lv_exc_occ = 'X'. ENDTRY. TRY. get_business_msgs_from_dom( ). CATCH cx_ecatt_apl INTO lx_ex. lv_exc_occ = 'X'. ENDTRY. TRY. CALL METHOD ('GET_PARAMS_FROM_DOM_NEW') " doesn't exist in 702 EXPORTING im_params = lo_params. CATCH cx_ecatt_apl INTO lx_ex. lv_exc_occ = 'X'. ENDTRY. TRY. get_variants_from_dom( lo_params ). CATCH cx_ecatt_apl INTO lx_ex. lv_exc_occ = 'X'. ENDTRY. TRY. lv_exists = cl_apl_ecatt_object=>existence_check_object( im_name = ch_object-d_obj_name im_version = ch_object-d_obj_ver im_obj_type = ch_object-s_obj_type im_exists_any_version = 'X' ). IF lv_exists = space. CALL METHOD lo_ecatt_vo->('SET_TADIR_FOR_NEW_OBJECT') EXPORTING im_tadir_for_new_object = tadir_preset. ENDIF. CATCH cx_ecatt. CLEAR lv_exists. ENDTRY. TRY. CALL METHOD lo_ecatt_vo->('SAVE') EXPORTING im_do_commit = 'X'. CATCH cx_ecatt_apl INTO lx_ex. lv_exc_occ = 'X'. ENDTRY. * get devclass from existing object TRY. cl_apl_ecatt_object=>get_tadir_entry( EXPORTING im_obj_name = ch_object-d_obj_name im_obj_type = ch_object-s_obj_type IMPORTING ex_tadir = ls_tadir ). ch_object-d_devclass = ls_tadir-devclass. CATCH cx_ecatt. CLEAR ls_tadir. ENDTRY. IF lv_exc_occ = 'X'. raise_upload_exception( previous = lx_ex ). ENDIF. ENDMETHOD. METHOD upload_data_from_stream. " Downport template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). ENDMETHOD. METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. " downport from CL_ABAPGIT_ECATT_DATA_UPLOAD SET_STREAM_FOR_UPLOAD mv_external_xml = iv_xml. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ECATT_VAL_OBJ_DOWN IMPLEMENTATION. METHOD download. " We inherit from CL_APL_ECATT_DOWNLOAD because CL_APL_ECATT_VO_DOWNLOAD " doesn't exist in 702 " Downport DATA: lv_partyp TYPE string, lo_ecatt_vo TYPE REF TO object. FIELD-SYMBOLS: TYPE any, TYPE REF TO cl_apl_ecatt_params. load_help = im_load_help. typ = im_object_type. TRY. cl_apl_ecatt_object=>show_object( EXPORTING im_obj_type = im_object_type im_name = im_object_name im_version = im_object_version IMPORTING re_object = ecatt_object ). CATCH cx_ecatt INTO ex_ecatt. RETURN. ENDTRY. lv_partyp = cl_apl_ecatt_const=>params_type_par. ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_vo = . set_attributes_to_template( ). set_ecatt_impl_detail( ). set_ecatt_flags( ). set_business_msgs( ). ASSIGN lo_ecatt_vo->('PARAMS') TO . ASSERT sy-subrc = 0. get_general_params_data( im_params = im_ptyp = lv_partyp ). LOOP AT parm INTO wa_parm. set_general_params_data_to_dom( ). IF NOT wa_parm-val_type IS INITIAL. set_deep_stru_to_dom( ). set_deep_data_to_dom( im_params = im_pindex = wa_parm-pindex ). ENDIF. ENDLOOP. set_variants_to_dom( ). download_data( ). ENDMETHOD. METHOD download_data. " Downport mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). ENDMETHOD. METHOD set_business_msgs. DATA: lt_buss_msg_ref TYPE zif_abapgit_ecatt=>ty_bus_msgs, li_element TYPE REF TO if_ixml_element, li_insert_objects TYPE REF TO if_ixml_element, lo_ecatt_vo TYPE REF TO object. FIELD-SYMBOLS: TYPE any. ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_vo = . mi_objects_node = template_over_all->create_simple_element( name = 'BUSINESS_MESSAGES' parent = root_node ). CALL METHOD lo_ecatt_vo->('GET_BUSSINESS_MSG') IMPORTING ex_buss_msg_ref = lt_buss_msg_ref. CALL FUNCTION 'SDIXML_DATA_TO_DOM' EXPORTING name = 'ETVO_MSG' dataobject = lt_buss_msg_ref IMPORTING data_as_dom = li_element CHANGING document = template_over_all EXCEPTIONS illegal_name = 1 OTHERS = 2. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. li_insert_objects ?= template_over_all->find_from_name( 'BUSINESS_MESSAGES' ). li_insert_objects->append_child( li_element ). ENDMETHOD. METHOD set_ecatt_flags. DATA: lv_invert_validation TYPE zif_abapgit_ecatt=>ty_invert_validation, lv_error_prio TYPE zif_abapgit_ecatt=>ty_error_prio, li_element TYPE REF TO if_ixml_element, li_insert_objects TYPE REF TO if_ixml_element, lo_ecatt_vo TYPE REF TO object. FIELD-SYMBOLS: TYPE any. mi_objects_node = template_over_all->create_simple_element( name = 'VO_FLAGS' parent = root_node ). ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_vo = . CALL METHOD lo_ecatt_vo->('GET_INVERT_VALIDATION_FLAG') RECEIVING re_invert_validation = lv_invert_validation. CALL FUNCTION 'SDIXML_DATA_TO_DOM' EXPORTING name = 'INVERT_VALIDATION' dataobject = lv_invert_validation IMPORTING data_as_dom = li_element CHANGING document = template_over_all EXCEPTIONS illegal_name = 1 OTHERS = 2. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. li_insert_objects ?= template_over_all->find_from_name( 'VO_FLAGS' ). li_insert_objects->append_child( li_element ). CALL METHOD lo_ecatt_vo->('GET_ERROR_PRIORITY') RECEIVING re_error_prio = lv_error_prio. CALL FUNCTION 'SDIXML_DATA_TO_DOM' EXPORTING name = 'ERROR_PRIORITY' dataobject = lv_error_prio IMPORTING data_as_dom = li_element CHANGING document = template_over_all EXCEPTIONS illegal_name = 1 OTHERS = 2. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. li_insert_objects = template_over_all->find_from_name( 'VO_FLAGS' ). li_insert_objects->append_child( li_element ). ENDMETHOD. METHOD set_ecatt_impl_detail. DATA: ls_impl_details TYPE zif_abapgit_ecatt=>ty_impl_det, li_element TYPE REF TO if_ixml_element, li_insert_objects TYPE REF TO if_ixml_element, lo_ecatt_vo TYPE REF TO object. FIELD-SYMBOLS: TYPE any. mi_objects_node = template_over_all->create_simple_element( name = 'IMPL_DETAILS' parent = root_node ). ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_vo = . CALL METHOD lo_ecatt_vo->('GET_IMPL_DETAILS') RECEIVING re_impl_details = ls_impl_details. CALL FUNCTION 'SDIXML_DATA_TO_DOM' EXPORTING name = 'IMPL_DET' dataobject = ls_impl_details IMPORTING data_as_dom = li_element CHANGING document = template_over_all EXCEPTIONS illegal_name = 1 OTHERS = 2. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. li_insert_objects = template_over_all->find_from_name( 'IMPL_DETAILS' ). li_insert_objects->append_child( li_element ). ENDMETHOD. METHOD zif_abapgit_ecatt_download~get_xml_stream. rv_xml_stream = mv_xml_stream. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ECATT_SYSTEM_UPL IMPLEMENTATION. METHOD upload_data_from_stream. " Downport template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). ENDMETHOD. METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. " downport from CL_APL_ECATT_SYSTEMS_UPLOAD SET_STREAM_FOR_UPLOAD mv_external_xml = iv_xml. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ecatt_system_downl IMPLEMENTATION. METHOD download. " Downport load_help = im_load_help. typ = im_object_type. TRY. cl_apl_ecatt_object=>show_object( EXPORTING im_obj_type = im_object_type im_name = im_object_name im_version = im_object_version IMPORTING re_object = ecatt_object ). CATCH cx_ecatt INTO ex_ecatt. RETURN. ENDTRY. set_attributes_to_template( ). set_systems_data_to_template( ). download_data( ). ENDMETHOD. METHOD download_data. " Downport mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). ENDMETHOD. METHOD zif_abapgit_ecatt_download~get_xml_stream. rv_xml_stream = mv_xml_stream. ENDMETHOD. METHOD set_systems_data_to_template. DATA: lo_ecatt_systems TYPE REF TO cl_apl_ecatt_system_data, lt_sys_data TYPE etsys_def_tabtype, ls_sys_data TYPE etsys_def, li_item TYPE REF TO if_ixml_element, li_sysdata_node TYPE REF TO if_ixml_element. lo_ecatt_systems ?= ecatt_object. lt_sys_data = lo_ecatt_systems->get_system_data( ). li_sysdata_node = template_over_all->create_simple_element( name = 'SYSTEMS_DATA' parent = root_node ). etpar_node = template_over_all->create_simple_element( name = 'ETSYS_DEF' parent = li_sysdata_node ). LOOP AT lt_sys_data INTO ls_sys_data. CLEAR: ls_sys_data-sys_desc, ls_sys_data-instance. CALL FUNCTION 'SDIXML_DATA_TO_DOM' EXPORTING name = 'item' dataobject = ls_sys_data IMPORTING data_as_dom = li_item CHANGING document = template_over_all EXCEPTIONS illegal_name = 1 OTHERS = 2. ASSERT sy-subrc = 0. etpar_node->append_child( li_item ). ENDLOOP. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ECATT_SP_UPLOAD IMPLEMENTATION. METHOD get_ecatt_sp. " downport DATA: li_ixml TYPE REF TO if_ixml, li_section TYPE REF TO if_ixml_element, li_dom TYPE REF TO if_ixml_document, li_root TYPE REF TO if_ixml_node, lv_start_profile TYPE etxml_line_str, lv_exception_occurred TYPE etonoff, lo_ecatt_sp TYPE REF TO object. FIELD-SYMBOLS: TYPE any. TRY. li_section = template_over_all->find_from_name_ns( 'START_PROFILE' ). IF NOT li_section IS INITIAL. li_ixml = cl_ixml=>create( ). li_dom = li_ixml->create_document( ). li_root ?= li_section->clone( ). li_dom->append_child( li_root ). CALL FUNCTION 'SDIXML_DOM_TO_XML' EXPORTING document = li_dom IMPORTING xml_as_string = lv_start_profile. ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_sp = . CALL METHOD lo_ecatt_sp->('SET_SP_ATTRIBUTES') EXPORTING i_sp_xml = lv_start_profile. ENDIF. CATCH cx_ecatt_apl. lv_exception_occurred = 'X'. ENDTRY. IF lv_exception_occurred = 'X'. raise_upload_exception( previous = exception_to_raise ). ENDIF. ENDMETHOD. METHOD upload. " We inherit from CL_APL_ECATT_UPLOAD because CL_APL_ECATT_SP_UPLOAD " doesn't exist in 702 " Downport "26.03.2013 DATA: lx_ecatt TYPE REF TO cx_ecatt_apl, lv_exists TYPE etonoff, lv_exc_occ TYPE etonoff, ls_tadir TYPE tadir, lo_ecatt_sp TYPE REF TO object. FIELD-SYMBOLS: TYPE any, TYPE data, TYPE data. TRY. ch_object-i_devclass = ch_object-d_devclass. ASSIGN COMPONENT 'D_AKH' OF STRUCTURE ch_object TO . " doesn't exist in 702 ASSIGN COMPONENT 'I_AKH' OF STRUCTURE ch_object TO . " doesn't exist in 702 IF IS ASSIGNED AND IS ASSIGNED. = . ENDIF. super->upload( CHANGING ch_object = ch_object ). upload_data_from_stream( ch_object-filename ). CATCH cx_ecatt_apl INTO lx_ecatt. IF template_over_all IS INITIAL. RAISE EXCEPTION lx_ecatt. ELSE. lv_exc_occ = 'X'. ENDIF. ENDTRY. TRY. CALL METHOD ('GET_ATTRIBUTES_FROM_DOM_NEW') " doesn't exist in 720 CHANGING ch_object = ch_object. CATCH cx_ecatt_apl INTO lx_ecatt. lv_exc_occ = 'X'. ENDTRY. ASSIGN ecatt_object TO . ASSERT sy-subrc = 0. lo_ecatt_sp = . TRY. get_ecatt_sp( ). CATCH cx_ecatt_apl INTO lx_ecatt. lv_exc_occ = 'X'. ENDTRY. TRY. lv_exists = cl_apl_ecatt_object=>existence_check_object( im_name = ch_object-d_obj_name im_version = ch_object-d_obj_ver im_obj_type = ch_object-s_obj_type im_exists_any_version = 'X' ). IF lv_exists = space. CALL METHOD lo_ecatt_sp->('SET_TADIR_FOR_NEW_OBJECT') EXPORTING im_tadir_for_new_object = tadir_preset. ENDIF. CATCH cx_ecatt. CLEAR lv_exists. ENDTRY. TRY. CALL METHOD lo_ecatt_sp->('SAVE') EXPORTING im_do_commit = 'X'. CATCH cx_ecatt_apl INTO lx_ecatt. lv_exc_occ = 'X'. ENDTRY. * Devesh,C5129871 18.07.2011 Releasing enqueue after uploading *begin TRY. ecatt_object->close_object( im_suppress_events = 'X' ). CATCH cx_ecatt_apl INTO lx_ecatt. ENDTRY. *end * get devclass from existing object TRY. cl_apl_ecatt_object=>get_tadir_entry( EXPORTING im_obj_name = ch_object-d_obj_name im_obj_type = ch_object-s_obj_type IMPORTING ex_tadir = ls_tadir ). ch_object-d_devclass = ls_tadir-devclass. CATCH cx_ecatt. CLEAR ls_tadir. ENDTRY. IF lv_exc_occ = 'X'. raise_upload_exception( previous = lx_ecatt ). ENDIF. ENDMETHOD. METHOD upload_data_from_stream. " Downport template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). ENDMETHOD. METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. " downport from CL_APL_ECATT_START_PROFIL SET_STREAM_FOR_UPLOAD mv_external_xml = iv_xml. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ECATT_SP_DOWNLOAD IMPLEMENTATION. METHOD download. " We inherit from CL_APL_ECATT_DOWNLOAD because CL_APL_ECATT_SP_DOWNLOAD " doesn't exist in 702 " Downport load_help = im_load_help. typ = im_object_type. TRY. cl_apl_ecatt_object=>show_object( EXPORTING im_obj_type = im_object_type im_name = im_object_name im_version = im_object_version IMPORTING re_object = ecatt_object ). CATCH cx_ecatt INTO ex_ecatt. RETURN. ENDTRY. set_attributes_to_template( ). set_sp_data_to_template( ). download_data( ). ENDMETHOD. METHOD download_data. " Downport mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). ENDMETHOD. METHOD set_sp_data_to_template. " downport DATA: li_dom TYPE REF TO if_ixml_document, li_start_profile_data_node TYPE REF TO if_ixml_element, li_element TYPE REF TO if_ixml_element, lv_sp_xml TYPE etxml_line_str, lo_ecatt_sp TYPE REF TO object. FIELD-SYMBOLS: TYPE data. li_start_profile_data_node = template_over_all->create_simple_element( name = 'START_PROFILE' parent = root_node ). ASSIGN ('ECATT_OBJECT') TO . ASSERT sy-subrc = 0. lo_ecatt_sp = . TRY. CALL METHOD lo_ecatt_sp->('GET_SP_ATTRIBUTES') IMPORTING e_sp_xml = lv_sp_xml. CATCH cx_ecatt_apl. ENDTRY. CALL FUNCTION 'SDIXML_XML_TO_DOM' EXPORTING xml = lv_sp_xml IMPORTING document = li_dom. li_element = li_dom->get_root_element( ). li_start_profile_data_node->append_child( li_element ). ENDMETHOD. METHOD zif_abapgit_ecatt_download~get_xml_stream. rv_xml_stream = mv_xml_stream. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ECATT_SCRIPT_UPL IMPLEMENTATION. METHOD upload_data_from_stream. " Downport template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). ENDMETHOD. METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. " downport from CL_ABAPGIT_ECATT_DATA_UPLOAD SET_STREAM_FOR_UPLOAD mv_external_xml = iv_xml. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ecatt_script_downl IMPLEMENTATION. METHOD download. " Downport load_help = im_load_help. typ = im_object_type. TRY. cl_apl_ecatt_object=>show_object( EXPORTING im_obj_type = im_object_type im_name = im_object_name im_version = im_object_version IMPORTING re_object = ecatt_object ). CATCH cx_ecatt INTO ex_ecatt. RETURN. ENDTRY. toolname = ecatt_object->attrib->get_tool_name( ). set_attributes_to_template( ). IF toolname = cl_apl_ecatt_const=>toolname_ecatt. ecatt_script ?= ecatt_object. set_script_to_template( ). TRY. get_general_params_data( ecatt_script->params ). CATCH cx_ecatt_apl. "#EC NO_HANDLER * proceed with download and report errors later ENDTRY. LOOP AT parm INTO wa_parm. TRY. IF wa_parm-value = ''. CLEAR wa_parm-value. ENDIF. set_general_params_data_to_dom( ). IF NOT wa_parm-pstruc_typ IS INITIAL. set_deep_stru_to_dom( ecatt_script->params ). set_deep_data_to_dom( ecatt_script->params ). IF wa_parm-xmlref_typ = cl_apl_ecatt_const=>ref_type_c_tcd. set_control_data_for_tcd( is_param = wa_parm io_params = ecatt_script->params ). ENDIF. ENDIF. CATCH cx_ecatt_apl. "#EC NO_HANDLER * proceed with download and report errors later ENDTRY. ENDLOOP. ELSE. set_blob_to_template( ). set_artmp_to_template( ). ENDIF. download_data( ). ENDMETHOD. METHOD download_data. " Downport mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). ENDMETHOD. METHOD escape_control_data. " Downport DATA: li_iter TYPE REF TO if_ixml_node_iterator, li_textit TYPE REF TO if_ixml_node_iterator, li_abapctrl TYPE REF TO if_ixml_node_collection, li_text TYPE REF TO if_ixml_text, li_filter TYPE REF TO if_ixml_node_filter, li_list TYPE REF TO if_ixml_node_list, lv_value TYPE etdom_name, li_vars TYPE REF TO if_ixml_element, li_elem TYPE REF TO if_ixml_element. li_vars = ii_element->find_from_name_ns( iv_tabname ). li_filter = ii_element->create_filter_node_type( if_ixml_node=>co_node_text ). IF li_vars IS NOT INITIAL. li_abapctrl = ii_element->get_elements_by_tag_name_ns( iv_node ). * just for debugging li_iter = li_abapctrl->create_iterator( ). li_elem ?= li_iter->get_next( ). WHILE li_elem IS NOT INITIAL. li_list = li_elem->get_children( ). li_textit = li_list->create_rev_iterator_filtered( li_filter ). li_text ?= li_textit->get_next( ). IF li_text IS NOT INITIAL. lv_value = li_text->get_data( ). IF lv_value(1) = cl_abap_char_utilities=>minchar. REPLACE SECTION OFFSET 0 LENGTH 1 OF lv_value WITH space. li_text->set_value( value = lv_value ). ENDIF. ENDIF. CLEAR: li_textit, li_list, li_elem, lv_value. li_elem ?= li_iter->get_next( ). ENDWHILE. CLEAR: li_abapctrl, li_elem, li_iter. ENDIF. ENDMETHOD. METHOD set_artmp_to_template. " Downport DATA: li_artmp_node TYPE REF TO if_ixml_element, lv_rc TYPE sy-subrc, lv_text TYPE string, lv_rc_args_tmpl TYPE i, lv_errmsg TYPE string. li_artmp_node = template_over_all->create_simple_element( name = 'ECET_ARTMP' parent = root_node ). ecatt_extprog->get_args_tmpl( IMPORTING ex_xml_arg_tmpl = lv_text ex_rc = lv_rc_args_tmpl ex_errmsg = lv_errmsg ). IF li_artmp_node IS INITIAL OR lv_rc_args_tmpl > 0. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_ARTMP_TO_TEMPLATE' free_text = lv_errmsg ). ENDIF. lv_rc = li_artmp_node->set_value( lv_text ). IF lv_rc <> 0. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_ARTMP_TO_TEMPLATE' ). ENDIF. ENDMETHOD. METHOD set_blob_to_template. " Downport DATA: li_blob_node TYPE REF TO if_ixml_element, lv_rc TYPE sy-subrc, lv_text TYPE string. li_blob_node = template_over_all->create_simple_element( name = 'ECET_BLOBS' parent = root_node ). IF li_blob_node IS INITIAL. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_BLOB_TO_TEMPLATE' ). ENDIF. ecatt_extprog->get_blob( EXPORTING im_whole_data = 1 IMPORTING ex_xml_blob = lv_text ). lv_rc = li_blob_node->set_value( lv_text ). IF lv_rc <> 0. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_BLOB_TO_TEMPLATE' ). ENDIF. ENDMETHOD. METHOD set_control_data_for_tcd. " Downport DATA: lt_params TYPE ettcd_params_tabtype, lt_verbs TYPE ettcd_verbs_tabtype, lt_vars TYPE ettcd_vars_tabtype, lt_dp_tab TYPE ettcd_dp_tab_tabtype, lt_dp_for TYPE ettcd_dp_for_tabtype, lt_dp_pro TYPE ettcd_dp_pro_tabtype, lt_dp_fld TYPE ettcd_dp_fld_tabtype, lt_svars TYPE ettcd_svars_tabtype. DATA: li_element TYPE REF TO if_ixml_element, li_deep_tcd TYPE REF TO if_ixml_element, lv_rc TYPE sy-subrc, lv_name TYPE string, lv_parname TYPE string, lo_pval_xml TYPE REF TO cl_apl_ecatt_xml_data, lo_ctrl_tabs TYPE REF TO cl_apl_ecatt_control_tables. FIELD-SYMBOLS: TYPE STANDARD TABLE. IF is_param-xmlref_typ <> cl_apl_ecatt_const=>ref_type_c_tcd OR io_params IS INITIAL. RETURN. ENDIF. lv_parname = is_param-pname. io_params->get_param_value( "TCD command interface EXPORTING im_var_id = cl_apl_ecatt_const=>varid_default_val im_pname = lv_parname im_pindex = is_param-pindex IMPORTING ex_pval_xml = lo_pval_xml ). lo_ctrl_tabs = lo_pval_xml->get_control_tables_ref( ). IF lo_ctrl_tabs IS INITIAL. RETURN. ENDIF. lo_ctrl_tabs->get_control_tables( "Read 8 control tables IMPORTING ex_params = lt_params ex_verbs = lt_verbs ex_vars = lt_vars ex_dp_tab = lt_dp_tab ex_dp_for = lt_dp_for ex_dp_pro = lt_dp_pro ex_dp_fld = lt_dp_fld ex_svars = lt_svars ). IF lt_params IS INITIAL OR lt_verbs IS INITIAL OR lt_vars IS INITIAL OR lt_dp_tab IS INITIAL OR lt_dp_for IS INITIAL OR lt_dp_pro IS INITIAL OR lt_dp_fld IS INITIAL OR lt_svars IS INITIAL. RETURN. ENDIF. li_deep_tcd = template_over_all->create_simple_element_ns( name = cl_apl_xml_const=>upl_tcd_node parent = ap_current_param ). IF li_deep_tcd IS INITIAL. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt ). ENDIF. DO 8 TIMES. "Loop at 8 control tables CASE sy-index. WHEN 1. lv_name = 'ETTCD_PARAMS_TABTYPE'. ASSIGN lt_params TO . WHEN 2. lv_name = 'ETTCD_VERBS_TABTYPE'. ASSIGN lt_verbs TO . WHEN 3. lv_name = 'ETTCD_VARS_TABTYPE'. ASSIGN lt_vars TO . WHEN 4. lv_name = 'ETTCD_DP_TAB_TABTYPE'. ASSIGN lt_dp_tab TO . WHEN 5. lv_name = 'ETTCD_DP_FOR_TABTYPE'. ASSIGN lt_dp_for TO . WHEN 6. lv_name = 'ETTCD_DP_PRO_TABTYPE'. ASSIGN lt_dp_pro TO . WHEN 7. lv_name = 'ETTCD_DP_FLD_TABTYPE'. ASSIGN lt_dp_fld TO . WHEN 8. lv_name = 'ETTCD_SVARS_TABTYPE'. ASSIGN lt_svars TO . ENDCASE. CALL FUNCTION 'SDIXML_DATA_TO_DOM' "Generate branch EXPORTING name = lv_name dataobject = IMPORTING data_as_dom = li_element EXCEPTIONS illegal_name = 1 OTHERS = 2. IF sy-subrc <> 0. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt ). ENDIF. * Hang a branch in the main tree lv_rc = li_deep_tcd->append_child( li_element ). IF lv_rc <> 0. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt ). ENDIF. FREE li_element. UNASSIGN . ENDDO. escape_control_data( ii_element = li_deep_tcd iv_tabname = 'ETTCD_VARS_TABTYPE' iv_node = 'CB_INDEX' ). escape_control_data( ii_element = li_deep_tcd iv_tabname = 'ETTCD_VERBS_TABTYPE' iv_node = 'NAME' ). FREE: lt_dp_tab, lt_dp_for, lt_dp_fld, lt_svars, lt_params, lt_vars, lt_dp_pro, lt_verbs. ENDMETHOD. METHOD set_script_to_template. " Downport DATA: lt_text TYPE etxml_line_tabtype, li_element TYPE REF TO if_ixml_element, lv_rc TYPE sy-subrc. ecatt_script->get_script_text( CHANGING scripttext = lt_text ). mi_script_node = template_over_all->create_simple_element( name = 'SCRIPT' parent = root_node ). IF mi_script_node IS INITIAL. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_SCRIPT_TO_TEMPLATE' ). ENDIF. CALL FUNCTION 'SDIXML_DATA_TO_DOM' EXPORTING name = 'ETXML_LINE_TABTYPE' dataobject = lt_text IMPORTING data_as_dom = li_element CHANGING document = template_over_all EXCEPTIONS illegal_name = 1 OTHERS = 2. IF sy-subrc <> 0. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_SCRIPT_TO_TEMPLATE' ). ENDIF. lv_rc = mi_script_node->append_child( li_element ). IF lv_rc <> 0. raise_download_exception( textid = cx_ecatt_apl_util=>download_processing previous = ex_ecatt called_method = 'CL_APL_ECATT_SCRIPT_DOWNLOAD->SET_SCRIPT_TO_TEMPLATE' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_ecatt_download~get_xml_stream. rv_xml_stream = mv_xml_stream. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ecatt_helper IMPLEMENTATION. METHOD build_xml_of_object. " downport of CL_APL_ECATT_DOWNLOAD=>BUILD_XML_OF_OBJECT DATA: lo_load_help_dummy TYPE REF TO cl_apl_ecatt_load_help, lx_ecatt TYPE REF TO cx_ecatt_apl, lv_text TYPE string, li_download TYPE REF TO zif_abapgit_ecatt_download. "download method will create the xml stream "note: it's the redefined download( ) of each object type specific download, which is called TRY. CREATE OBJECT lo_load_help_dummy EXPORTING im_maintain_function = ''. io_download->download( im_object_name = iv_object_name im_object_version = iv_object_version im_object_type = iv_object_type im_load_help = lo_load_help_dummy ). CATCH cx_ecatt_apl INTO lx_ecatt. lv_text = lx_ecatt->get_text( ). zcx_abapgit_exception=>raise( lv_text ). " note, exception cx_ecatt_ui_attachment doesn't exist in 702 CATCH cx_ecatt. "will never be raised from download, when called with mv_generate_xml_no_download = 'X'. ENDTRY. li_download ?= io_download. rv_xml_stream = li_download->get_xml_stream( ). ENDMETHOD. METHOD download_data. DATA: lo_xml TYPE REF TO cl_apl_ecatt_xml. TRY. CALL METHOD cl_apl_ecatt_xml=>('CREATE') " doesn't exist in 702 EXPORTING im_type = c_xml RECEIVING re_xml = lo_xml. lo_xml->set_attributes( im_dom = ii_template_over_all ). lo_xml->get_attributes( IMPORTING ex_xml = rv_xml_stream ). CATCH cx_ecatt_apl_xml. RETURN. ENDTRY. ENDMETHOD. METHOD upload_data_from_stream. DATA: lo_xml TYPE REF TO cl_apl_ecatt_xml, lv_xstr TYPE xstring, li_nc_xmlref_typ TYPE REF TO if_ixml_node_collection, li_n_xmlref_typ TYPE REF TO if_ixml_node, lv_index TYPE i VALUE 0, lv_count TYPE i. lv_xstr = iv_xml_stream. CALL METHOD cl_apl_ecatt_xml=>('CREATE') " doesn't exist in 702 EXPORTING im_type = c_xml RECEIVING re_xml = lo_xml. * whitespace stripping needs a namespace * remove white spaces only at the time of upload lo_xml->stream_to_dom( im_xstream = lv_xstr im_ignore_white_space = 'X' im_uri = cl_apl_xml_const=>schema_uri ). lo_xml->get_attributes( IMPORTING ex_dom = ri_template_over_all ). * MD: Workaround, because nodes starting with "XML" are not allowed li_nc_xmlref_typ ?= ri_template_over_all->get_elements_by_tag_name_ns( 'XMLREF_TYP' ). CALL METHOD li_nc_xmlref_typ->('GET_LENGTH') " downport RECEIVING rval = lv_count. WHILE lv_index < lv_count. li_n_xmlref_typ = li_nc_xmlref_typ->get_item( lv_index ). li_n_xmlref_typ->set_name( 'X-MLREF_TYP' ). lv_index = lv_index + 1. ENDWHILE. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ecatt_data_upload IMPLEMENTATION. METHOD upload. SET HANDLER on_ev_object_saved FOR ALL INSTANCES. ms_current_object-s_obj_type = ch_object-s_obj_type. ms_current_object-d_obj_name = ch_object-d_obj_name. ms_current_object-d_obj_ver = ch_object-d_obj_ver. TRY. super->upload( CHANGING ch_object = ch_object ). SET HANDLER on_ev_object_saved FOR ALL INSTANCES ACTIVATION abap_false. CLEANUP. SET HANDLER on_ev_object_saved FOR ALL INSTANCES ACTIVATION abap_false. ENDTRY. IF mx_ecatt_apl IS BOUND. raise_upload_exception( previous = mx_ecatt_apl ). ENDIF. ENDMETHOD. METHOD upload_data_from_stream. " Downport template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). ENDMETHOD. METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. " downport from CL_ABAPGIT_ECATT_DATA_UPLOAD SET_STREAM_FOR_UPLOAD mv_external_xml = iv_xml. ENDMETHOD. METHOD on_ev_object_saved. DATA lo_ecatt_td TYPE REF TO cl_apl_ecatt_test_data. " Trickery to remove any local variants that do not exist on the remote on pull. SET HANDLER on_ev_object_saved FOR ALL INSTANCES ACTIVATION abap_false. TRY. IF ex_ecatt_object->object_type <> ms_current_object-s_obj_type OR ex_ecatt_object->object_name <> ms_current_object-d_obj_name OR ex_ecatt_object->object_version <> ms_current_object-d_obj_ver. CREATE OBJECT mx_ecatt_apl EXPORTING textid = cx_ecatt_apl=>any_text free_text = 'Unexpected object in save sequence'. RETURN. ENDIF. lo_ecatt_td ?= ex_ecatt_object. lo_ecatt_td->params->delete_variants( '*' ). TRY. CALL METHOD ('GET_VARIANTS_FROM_DOM_NEW') EXPORTING im_params = lo_ecatt_td->params. CATCH cx_sy_dyn_call_error. get_variants_from_dom( lo_ecatt_td->params ). ENDTRY. lo_ecatt_td->save( ). CATCH cx_ecatt_apl INTO mx_ecatt_apl. RETURN. ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ECATT_DATA_DOWNL IMPLEMENTATION. METHOD download. " Downport DATA: lv_partyp TYPE string. load_help = im_load_help. TRY. cl_apl_ecatt_object=>show_object( EXPORTING im_obj_type = im_object_type im_name = im_object_name im_version = im_object_version IMPORTING re_object = ecatt_object ). CATCH cx_ecatt INTO ex_ecatt. RETURN. ENDTRY. typ = im_object_type. lv_partyp = cl_apl_ecatt_const=>params_type_par. ecatt_data ?= ecatt_object. set_attributes_to_template( ). get_general_params_data( im_params = ecatt_data->params im_ptyp = lv_partyp ). LOOP AT parm INTO wa_parm. set_general_params_data_to_dom( ). IF NOT wa_parm-val_type IS INITIAL. set_deep_stru_to_dom( ecatt_data->params ). set_deep_data_to_dom( im_params = ecatt_data->params im_pindex = wa_parm-pindex ). ENDIF. ENDLOOP. * MS180406 set_var_mode_to_dom( ). * ENDMS180406 set_variants_to_dom( ecatt_data->params ). download_data( ). ENDMETHOD. METHOD download_data. " Downport mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). ENDMETHOD. METHOD zif_abapgit_ecatt_download~get_xml_stream. rv_xml_stream = mv_xml_stream. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ECATT_CONFIG_UPL IMPLEMENTATION. METHOD upload_data_from_stream. " Downport template_over_all = zcl_abapgit_ecatt_helper=>upload_data_from_stream( mv_external_xml ). ENDMETHOD. METHOD zif_abapgit_ecatt_upload~set_stream_for_upload. " downport from CL_ABAPGIT_ECATT_DATA_UPLOAD SET_STREAM_FOR_UPLOAD mv_external_xml = iv_xml. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ECATT_CONFIG_DOWNL IMPLEMENTATION. METHOD download. " Downport DATA: lv_partyp TYPE string. load_help = im_load_help. typ = im_object_type. TRY. cl_apl_ecatt_object=>show_object( EXPORTING im_obj_type = im_object_type im_name = im_object_name im_version = im_object_version IMPORTING re_object = ecatt_object ). CATCH cx_ecatt INTO ex_ecatt. RETURN. ENDTRY. lv_partyp = cl_apl_ecatt_const=>params_type_par. set_attributes_to_template( ). ecatt_config ?= ecatt_object. CALL METHOD ('SET_ECATT_OBJECTS_TO_TEMPLATE'). " doesn't exist in 702 * MS180406 set_var_mode_to_dom( ). * ENDMS180406 get_general_params_data( im_params = ecatt_config->params im_ptyp = lv_partyp ). LOOP AT parm INTO wa_parm. set_general_params_data_to_dom( ). IF NOT wa_parm-val_type IS INITIAL. set_deep_stru_to_dom( ecatt_config->params ). set_deep_data_to_dom( im_params = ecatt_config->params im_pindex = wa_parm-pindex ). ENDIF. ENDLOOP. set_variants_to_dom( ecatt_config->params ). download_data( ). ENDMETHOD. METHOD download_data. " Downport mv_xml_stream = zcl_abapgit_ecatt_helper=>download_data( template_over_all ). ENDMETHOD. METHOD zif_abapgit_ecatt_download~get_xml_stream. rv_xml_stream = mv_xml_stream. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_tadir IMPLEMENTATION. METHOD add_local_packages. FIELD-SYMBOLS: LIKE LINE OF it_packages, LIKE LINE OF ct_tadir. LOOP AT it_packages ASSIGNING . " Local packages are not in TADIR, only in TDEVC, act as if they were IF CP '$*'. " OR CP 'T*' ). APPEND INITIAL LINE TO ct_tadir ASSIGNING . -pgmid = 'R3TR'. -object = 'DEVC'. -obj_name = . -devclass = . -srcsystem = sy-sysid. -masterlang = sy-langu. ENDIF. ENDLOOP. ENDMETHOD. METHOD add_namespace. DATA ls_tadir TYPE zif_abapgit_definitions=>ty_tadir. DATA ls_obj_with_namespace TYPE zif_abapgit_definitions=>ty_obj_namespace. TRY. ls_obj_with_namespace = zcl_abapgit_factory=>get_sap_namespace( )->split_by_name( iv_object ). CATCH zcx_abapgit_exception. "Ignore the exception like before the replacement of the FM RS_NAME_SPLIT_NAMESPACE RETURN. ENDTRY. IF ls_obj_with_namespace-namespace IS NOT INITIAL. READ TABLE ct_tadir_nspc TRANSPORTING NO FIELDS WITH KEY pgmid = 'R3TR' object = 'NSPC' obj_name = ls_obj_with_namespace-namespace. IF sy-subrc <> 0. ls_tadir-pgmid = 'R3TR'. ls_tadir-object = 'NSPC'. ls_tadir-obj_name = ls_obj_with_namespace-namespace. ls_tadir-devclass = iv_package. ls_tadir-srcsystem = sy-sysid. ls_tadir-masterlang = sy-langu. INSERT ls_tadir INTO TABLE ct_tadir. INSERT ls_tadir INTO TABLE ct_tadir_nspc. ENDIF. ENDIF. ENDMETHOD. METHOD add_namespaces. DATA lt_tadir_nspc TYPE zif_abapgit_definitions=>ty_tadir_tt. FIELD-SYMBOLS LIKE LINE OF ct_tadir. " Namespaces are not in TADIR, but are necessary for creating objects in transportable packages LOOP AT ct_tadir ASSIGNING WHERE obj_name(1) = '/'. add_namespace( EXPORTING iv_package = iv_package iv_object = -obj_name CHANGING ct_tadir = ct_tadir ct_tadir_nspc = lt_tadir_nspc ). ENDLOOP. " Root package of repo might not exist yet but needs to be considered, too IF iv_package CP '/*'. add_namespace( EXPORTING iv_package = iv_package iv_object = iv_package CHANGING ct_tadir = ct_tadir ct_tadir_nspc = lt_tadir_nspc ). ENDIF. ENDMETHOD. METHOD build. DATA lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. select_objects( EXPORTING iv_package = iv_package iv_ignore_subpackages = iv_ignore_subpackages iv_only_local_objects = iv_only_local_objects IMPORTING et_tadir = rt_tadir et_packages = lt_packages ). add_local_packages( EXPORTING it_packages = lt_packages CHANGING ct_tadir = rt_tadir ). add_namespaces( EXPORTING iv_package = iv_package CHANGING ct_tadir = rt_tadir ). determine_path( EXPORTING iv_package = iv_package io_dot = io_dot CHANGING ct_tadir = rt_tadir ). ENDMETHOD. METHOD check_exists. DATA: li_progress TYPE REF TO zif_abapgit_progress, ls_item TYPE zif_abapgit_definitions=>ty_item. FIELD-SYMBOLS: LIKE LINE OF it_tadir. li_progress = zcl_abapgit_progress=>get_instance( lines( it_tadir ) ). * rows from database table TADIR are not removed for * transportable objects until the transport is released LOOP AT it_tadir ASSIGNING . IF sy-tabix MOD 200 = 0. li_progress->show( iv_current = sy-tabix iv_text = |Check object exists { -object } { -obj_name }| ). ENDIF. ls_item-obj_type = -object. ls_item-obj_name = -obj_name. ls_item-devclass = -devclass. IF zcl_abapgit_objects=>exists( ls_item ) = abap_true. APPEND TO rt_tadir. ENDIF. ENDLOOP. li_progress->off( ). ENDMETHOD. METHOD determine_path. DATA: lv_path TYPE string, lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic, lv_last_package TYPE devclass VALUE cl_abap_char_utilities=>horizontal_tab. FIELD-SYMBOLS LIKE LINE OF ct_tadir. lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). LOOP AT ct_tadir ASSIGNING . IF lv_last_package <> -devclass. "Change in Package lv_last_package = -devclass. IF NOT io_dot IS INITIAL. lv_path = lo_folder_logic->package_to_path( iv_top = iv_package io_dot = io_dot iv_package = -devclass ). ENDIF. ENDIF. -path = lv_path. -korrnum = ''. ENDLOOP. ENDMETHOD. METHOD select_objects. DATA: lt_excludes TYPE RANGE OF trobjtype, ls_exclude LIKE LINE OF lt_excludes, lt_srcsystem TYPE RANGE OF tadir-srcsystem, ls_srcsystem LIKE LINE OF lt_srcsystem. " Determine packages to read IF iv_ignore_subpackages = abap_false. et_packages = zcl_abapgit_factory=>get_sap_package( iv_package )->list_subpackages( ). ENDIF. INSERT iv_package INTO et_packages INDEX 1. " Exclude object types with tadir entries that are included elsewhere ls_exclude-sign = 'I'. ls_exclude-option = 'EQ'. ls_exclude-low = 'SOTR'. " automatically created for SAP packages (DEVC) APPEND ls_exclude TO lt_excludes. ls_exclude-low = 'SOTS'. " automatically created for SAP packages (DEVC) APPEND ls_exclude TO lt_excludes. ls_exclude-low = 'SFB1'. " covered by business function sets (SFBS) APPEND ls_exclude TO lt_excludes. ls_exclude-low = 'SFB2'. " covered by business functions (SFBF) APPEND ls_exclude TO lt_excludes. ls_exclude-low = 'STOB'. " auto generated by core data services (DDLS) APPEND ls_exclude TO lt_excludes. " Limit to objects belonging to this system IF iv_only_local_objects = abap_true. ls_srcsystem-sign = 'I'. ls_srcsystem-option = 'EQ'. ls_srcsystem-low = sy-sysid. APPEND ls_srcsystem TO lt_srcsystem. ENDIF. IF et_packages IS NOT INITIAL. SELECT * FROM tadir INTO CORRESPONDING FIELDS OF TABLE et_tadir FOR ALL ENTRIES IN et_packages WHERE devclass = et_packages-table_line AND pgmid = 'R3TR' AND object NOT IN lt_excludes AND delflag = abap_false AND srcsystem IN lt_srcsystem ORDER BY PRIMARY KEY ##TOO_MANY_ITAB_FIELDS. "#EC CI_GENBUFF "#EC CI_SUBRC ENDIF. SORT et_tadir BY devclass pgmid object obj_name. ENDMETHOD. METHOD zif_abapgit_tadir~get_object_package. DATA: ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, ls_item TYPE zif_abapgit_definitions=>ty_item. ls_tadir = zif_abapgit_tadir~read_single( iv_pgmid = iv_pgmid iv_object = iv_object iv_obj_name = iv_obj_name ). IF ls_tadir-delflag = abap_true. RETURN. "Mark for deletion -> return nothing ENDIF. ls_item-obj_type = ls_tadir-object. ls_item-obj_name = ls_tadir-obj_name. ls_item-devclass = ls_tadir-devclass. IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. RETURN. ENDIF. rv_devclass = ls_tadir-devclass. ENDMETHOD. METHOD zif_abapgit_tadir~read. DATA li_exit TYPE REF TO zif_abapgit_exit. DATA lr_tadir TYPE REF TO zif_abapgit_definitions=>ty_tadir. DATA lt_filter TYPE zif_abapgit_definitions=>ty_tadir_tt. DATA ls_dot_data TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit. ASSERT iv_package IS NOT INITIAL. " Start recursion " hmm, some problems here, should TADIR also build path? rt_tadir = build( iv_package = iv_package io_dot = io_dot iv_ignore_subpackages = iv_ignore_subpackages iv_only_local_objects = iv_only_local_objects ). IF io_dot IS NOT INITIAL. ls_dot_data = io_dot->get_data( ). ENDIF. li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->change_tadir( EXPORTING iv_package = iv_package ii_log = ii_log is_dot_abapgit = ls_dot_data iv_ignore_subpackages = iv_ignore_subpackages iv_only_local_objects = iv_only_local_objects CHANGING ct_tadir = rt_tadir ). IF it_filter IS NOT INITIAL. "Apply filter manually instead of calling zcl_abapgit_repo_filter->apply, "so that we can execute a unit test. The method applies addition filtering "and does therefore additional selects lt_filter = it_filter. SORT lt_filter BY object obj_name. LOOP AT rt_tadir REFERENCE INTO lr_tadir. READ TABLE lt_filter TRANSPORTING NO FIELDS WITH KEY object = lr_tadir->object obj_name = lr_tadir->obj_name BINARY SEARCH. IF sy-subrc <> 0. DELETE rt_tadir. ENDIF. ENDLOOP. ENDIF. IF iv_check_exists = abap_true. rt_tadir = check_exists( rt_tadir ). ENDIF. ENDMETHOD. METHOD zif_abapgit_tadir~read_single. SELECT SINGLE * FROM tadir INTO CORRESPONDING FIELDS OF rs_tadir WHERE pgmid = iv_pgmid AND object = iv_object AND obj_name = iv_obj_name. "#EC CI_SUBRC CLEAR rs_tadir-korrnum. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_serialize IMPLEMENTATION. METHOD add_apack. DATA ls_apack_file TYPE zif_abapgit_git_definitions=>ty_file. FIELD-SYMBOLS LIKE LINE OF ct_files. ls_apack_file = zcl_abapgit_apack_helper=>to_file( iv_package ). IF ls_apack_file IS NOT INITIAL. APPEND INITIAL LINE TO ct_files ASSIGNING . -file = ls_apack_file. ENDIF. ENDMETHOD. METHOD add_data. DATA lt_files TYPE zif_abapgit_git_definitions=>ty_files_tt. DATA ls_file LIKE LINE OF lt_files. FIELD-SYMBOLS LIKE LINE OF ct_files. IF ii_data_config IS INITIAL. RETURN. ENDIF. lt_files = ii_data_config->to_json( ). LOOP AT lt_files INTO ls_file. APPEND INITIAL LINE TO ct_files ASSIGNING . -file = ls_file. " Derive object from config filename (namespace + escaping) zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = -file-filename iv_path = -file-path io_dot = mo_dot_abapgit IMPORTING es_item = -item ). -item-obj_type = zif_abapgit_data_config=>c_data_type-tabu. " todo ENDLOOP. lt_files = zcl_abapgit_data_factory=>get_serializer( )->serialize( ii_data_config ). LOOP AT lt_files INTO ls_file. APPEND INITIAL LINE TO ct_files ASSIGNING . -file = ls_file. " Derive object from data filename (namespace + escaping) zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = -file-filename iv_path = -file-path io_dot = mo_dot_abapgit IMPORTING es_item = -item ). ENDLOOP. ENDMETHOD. METHOD add_dot_abapgit. FIELD-SYMBOLS: LIKE LINE OF ct_files. APPEND INITIAL LINE TO ct_files ASSIGNING . -file = mo_dot_abapgit->to_file( ). ENDMETHOD. METHOD add_objects. DATA: lo_filter TYPE REF TO zcl_abapgit_repo_filter, lv_force TYPE abap_bool, lt_found LIKE ct_files, lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. lt_tadir = zcl_abapgit_factory=>get_tadir( )->read( iv_package = iv_package iv_ignore_subpackages = ms_local_settings-ignore_subpackages iv_only_local_objects = ms_local_settings-only_local_objects io_dot = mo_dot_abapgit ii_log = ii_log it_filter = it_filter ). CREATE OBJECT lo_filter. lo_filter->apply( EXPORTING it_filter = it_filter CHANGING ct_tadir = lt_tadir ). * if there are less than 10 objects run in single thread * this helps a lot when debugging, plus performance gain * with low number of objects does not matter much lv_force = boolc( lines( lt_tadir ) < 10 ). lt_found = serialize( iv_package = iv_package it_tadir = lt_tadir ii_log = ii_log iv_force_sequential = lv_force ). APPEND LINES OF lt_found TO ct_files. ENDMETHOD. METHOD add_to_return. FIELD-SYMBOLS: LIKE LINE OF is_file_item-files, LIKE LINE OF mt_files. LOOP AT is_file_item-files ASSIGNING . APPEND INITIAL LINE TO mt_files ASSIGNING . -file = . -file-path = iv_path. -item = is_file_item-item. ENDLOOP. ENDMETHOD. METHOD constructor. DATA li_exit TYPE REF TO zif_abapgit_exit. mv_group = 'parallel_generators'. li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->change_rfc_server_group( CHANGING cv_group = mv_group ). mo_dot_abapgit = io_dot_abapgit. ms_local_settings = is_local_settings. IF io_dot_abapgit IS BOUND. ms_i18n_params = io_dot_abapgit->determine_i18n_parameters( is_local_settings-main_language_only ). ELSE. ms_i18n_params-main_language = sy-langu. ms_i18n_params-main_language_only = is_local_settings-main_language_only. ENDIF. CREATE OBJECT mo_abap_language_version EXPORTING io_dot_abapgit = mo_dot_abapgit. ENDMETHOD. METHOD determine_max_processes. DATA: li_exit TYPE REF TO zif_abapgit_exit. IF iv_force_sequential = abap_true. rv_processes = 1. RETURN. ENDIF. IF gv_max_processes IS INITIAL AND is_parallelization_possible( ) = abap_true. gv_max_processes = zcl_abapgit_factory=>get_environment( )->init_parallel_processing( mv_group ). IF gv_max_processes > 1. gv_max_processes = gv_max_processes - 1. ENDIF. IF gv_max_processes > 32. " https://en.wikipedia.org/wiki/Amdahl%27s_law gv_max_processes = 32. ENDIF. ENDIF. IF gv_max_processes IS INITIAL. " fallback to running sequentially. gv_max_processes = 1. ENDIF. rv_processes = gv_max_processes. ASSERT rv_processes >= 1. li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->change_max_parallel_processes( EXPORTING iv_package = iv_package CHANGING cv_max_processes = rv_processes ). ASSERT rv_processes >= 1. " check exit above ENDMETHOD. METHOD files_local. * serializes objects, including .abapgit.xml, apack, and takes into account local settings add_dot_abapgit( CHANGING ct_files = rt_files ). add_apack( EXPORTING iv_package = iv_package CHANGING ct_files = rt_files ). add_data( EXPORTING ii_data_config = ii_data_config CHANGING ct_files = rt_files ). add_objects( EXPORTING iv_package = iv_package ii_log = ii_log it_filter = it_filter CHANGING ct_files = rt_files ). ENDMETHOD. METHOD filter_ignored_objects. DATA: ls_ignored_count TYPE ty_unsupported_count, lt_ignored_count TYPE ty_unsupported_count_tt, lo_folder_logic TYPE REF TO zcl_abapgit_folder_logic, ls_item TYPE zif_abapgit_definitions=>ty_item, lv_path TYPE string, lv_filename TYPE string. FIELD-SYMBOLS: LIKE LINE OF ct_tadir, TYPE ty_unsupported_count. " Ignore logic requires .abapGit.xml IF mo_dot_abapgit IS INITIAL OR iv_package IS INITIAL OR mi_log IS INITIAL. RETURN. ENDIF. lo_folder_logic = zcl_abapgit_folder_logic=>get_instance( ). LOOP AT ct_tadir ASSIGNING . CLEAR: ls_ignored_count. ls_item-obj_type = -object. ls_item-obj_name = -obj_name. IF -devclass IS NOT INITIAL. lv_path = lo_folder_logic->package_to_path( iv_top = iv_package io_dot = mo_dot_abapgit iv_package = -devclass ). ELSE. lv_path = mo_dot_abapgit->get_starting_folder( ). ENDIF. lv_filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ls_item iv_ext = '*' ). IF mo_dot_abapgit->is_ignored( iv_path = lv_path iv_filename = lv_filename ) = abap_false. CONTINUE. ENDIF. READ TABLE lt_ignored_count ASSIGNING WITH TABLE KEY obj_type = -object. IF sy-subrc <> 0. ls_ignored_count-obj_type = -object. ls_ignored_count-count = 1. ls_ignored_count-obj_name = -obj_name. INSERT ls_ignored_count INTO TABLE lt_ignored_count ASSIGNING . ELSE. CLEAR: -obj_name. -count = -count + 1. ENDIF. " init object so we can remove these entries afterward CLEAR -object. ENDLOOP. IF lt_ignored_count IS INITIAL. RETURN. ENDIF. " remove ignored objects DELETE ct_tadir WHERE object IS INITIAL. LOOP AT lt_ignored_count ASSIGNING . IF -count = 1. mi_log->add_warning( |Object { -obj_type } { -obj_name } ignored| ). ELSE. mi_log->add_warning( |Object type { -obj_type } with | && |{ -count } objects ignored| ). ENDIF. ENDLOOP. ENDMETHOD. METHOD filter_unsupported_objects. DATA: ls_unsupported_count TYPE ty_unsupported_count, lt_supported_types TYPE zcl_abapgit_objects=>ty_types_tt, lt_unsupported_count TYPE ty_unsupported_count_tt. FIELD-SYMBOLS: LIKE LINE OF ct_tadir, TYPE ty_unsupported_count. lt_supported_types = zcl_abapgit_objects=>supported_list( ). LOOP AT ct_tadir ASSIGNING . CLEAR: ls_unsupported_count. READ TABLE lt_supported_types WITH KEY table_line = -object TRANSPORTING NO FIELDS. IF sy-subrc = 0. CONTINUE. ENDIF. READ TABLE lt_unsupported_count ASSIGNING WITH TABLE KEY obj_type = -object. IF sy-subrc <> 0. ls_unsupported_count-obj_type = -object. ls_unsupported_count-count = 1. ls_unsupported_count-obj_name = -obj_name. INSERT ls_unsupported_count INTO TABLE lt_unsupported_count ASSIGNING . ELSE. CLEAR: -obj_name. -count = -count + 1. ENDIF. CLEAR: -object. ENDLOOP. IF lt_unsupported_count IS INITIAL. RETURN. ENDIF. DELETE ct_tadir WHERE object IS INITIAL. IF mi_log IS BOUND. LOOP AT lt_unsupported_count ASSIGNING . IF -count = 1. mi_log->add_error( |Object type { -obj_type } not supported, | && |{ -obj_name } ignored| ). ELSE. mi_log->add_error( |Object type { -obj_type } not supported, | && |{ -count } objects ignored| ). ENDIF. ENDLOOP. ENDIF. ENDMETHOD. METHOD is_parallelization_possible. rv_result = boolc( zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false AND zcl_abapgit_persist_factory=>get_settings( )->read( )->get_parallel_proc_disabled( ) = abap_false AND mv_group IS NOT INITIAL " The function module below should always exist here as is_merged evaluated to false above. " It does however not exist in the transpiled version which then causes unit tests to fail. " Therefore the check needs to stay. AND zcl_abapgit_factory=>get_function_module( )->function_exists( 'Z_ABAPGIT_SERIALIZE_PARALLEL' ) = abap_true ). ENDMETHOD. METHOD on_end_of_task. * this method will be called from the parallel processing, thus it must be public DATA: lv_result TYPE xstring, lv_path TYPE string, lv_mess TYPE c LENGTH 200, ls_file_item TYPE zif_abapgit_objects=>ty_serialization. RECEIVE RESULTS FROM FUNCTION 'Z_ABAPGIT_SERIALIZE_PARALLEL' IMPORTING ev_result = lv_result ev_path = lv_path EXCEPTIONS error = 1 system_failure = 2 MESSAGE lv_mess communication_failure = 3 MESSAGE lv_mess OTHERS = 4. IF sy-subrc <> 0. IF NOT mi_log IS INITIAL. IF NOT lv_mess IS INITIAL. mi_log->add_error( lv_mess ). ELSE. mi_log->add_error( |{ sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv3 }| ). ENDIF. ENDIF. ELSE. IMPORT data = ls_file_item FROM DATA BUFFER lv_result. "#EC CI_SUBRC ASSERT sy-subrc = 0. add_to_return( is_file_item = ls_file_item iv_path = lv_path ). ENDIF. mv_free = mv_free + 1. ENDMETHOD. METHOD run_parallel. DATA: lv_msg TYPE c LENGTH 100, lv_task TYPE c LENGTH 32, lv_free LIKE mv_free. DATA lv_abap_language_version TYPE zif_abapgit_aff_types_v1=>ty_abap_language_version. ASSERT mv_free > 0. lv_abap_language_version = mo_abap_language_version->get_repo_abap_language_version( ). DO. lv_task = |{ iv_task }-{ sy-index }|. CALL FUNCTION 'Z_ABAPGIT_SERIALIZE_PARALLEL' STARTING NEW TASK lv_task DESTINATION IN GROUP mv_group CALLING on_end_of_task ON END OF TASK EXPORTING iv_obj_type = is_tadir-object iv_obj_name = is_tadir-obj_name iv_devclass = is_tadir-devclass iv_path = is_tadir-path iv_srcsystem = is_tadir-srcsystem iv_abap_language_vers = lv_abap_language_version iv_language = ms_i18n_params-main_language iv_main_language_only = ms_i18n_params-main_language_only it_translation_langs = ms_i18n_params-translation_languages iv_use_lxe = ms_i18n_params-use_lxe EXCEPTIONS system_failure = 1 MESSAGE lv_msg communication_failure = 2 MESSAGE lv_msg resource_failure = 3 OTHERS = 4. IF sy-subrc = 3. lv_free = mv_free. WAIT UNTIL mv_free <> lv_free UP TO 1 SECONDS. CONTINUE. ELSEIF sy-subrc <> 0. ASSERT lv_msg = '' AND 0 = 1. ENDIF. EXIT. ENDDO. mv_free = mv_free - 1. ENDMETHOD. METHOD run_sequential. DATA: lx_error TYPE REF TO zcx_abapgit_exception, ls_file_item TYPE zif_abapgit_objects=>ty_serialization. ls_file_item-item-obj_type = is_tadir-object. ls_file_item-item-obj_name = is_tadir-obj_name. ls_file_item-item-devclass = is_tadir-devclass. ls_file_item-item-srcsystem = is_tadir-srcsystem. ls_file_item-item-abap_language_version = mo_abap_language_version->get_repo_abap_language_version( ). TRY. ls_file_item = zcl_abapgit_objects=>serialize( is_item = ls_file_item-item io_i18n_params = zcl_abapgit_i18n_params=>new( is_params = ms_i18n_params ) ). add_to_return( is_file_item = ls_file_item iv_path = is_tadir-path ). CATCH zcx_abapgit_exception INTO lx_error. IF NOT mi_log IS INITIAL. mi_log->add_exception( ix_exc = lx_error is_item = ls_file_item-item ). ENDIF. ENDTRY. ENDMETHOD. METHOD serialize. * serializes only objects DATA: lv_max TYPE i, lv_count TYPE i, li_progress TYPE REF TO zif_abapgit_progress, li_exit TYPE REF TO zif_abapgit_exit, lo_timer TYPE REF TO zcl_abapgit_timer, lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. FIELD-SYMBOLS: LIKE LINE OF it_tadir. CLEAR mt_files. lv_max = determine_max_processes( iv_force_sequential = iv_force_sequential iv_package = iv_package ). mv_free = lv_max. mi_log = ii_log. lt_tadir = it_tadir. filter_unsupported_objects( CHANGING ct_tadir = lt_tadir ). filter_ignored_objects( EXPORTING iv_package = iv_package CHANGING ct_tadir = lt_tadir ). lv_count = lines( lt_tadir ). li_progress = zcl_abapgit_progress=>get_instance( lv_count ). lo_timer = zcl_abapgit_timer=>create( iv_text = 'Serialize:' iv_count = lv_count )->start( ). LOOP AT lt_tadir ASSIGNING . IF lv_max = 1. li_progress->show( iv_current = sy-tabix iv_text = |Serialize { -obj_name }, { lv_max } thread| ). run_sequential( ). ELSE. li_progress->show( iv_current = sy-tabix iv_text = |Serialize { -obj_name }, { lv_max } threads| ). run_parallel( is_tadir = iv_task = |{ sy-tabix }| ). WAIT UNTIL mv_free > 0 UP TO 120 SECONDS. ENDIF. ENDLOOP. li_progress->off( ). WAIT UNTIL mv_free = lv_max UP TO 120 SECONDS. rt_files = mt_files. FREE mt_files. * Call postprocessing li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->serialize_postprocess( EXPORTING iv_package = iv_package ii_log = ii_log CHANGING ct_files = rt_files ). lo_timer->end( abap_true ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_objects_files IMPLEMENTATION. METHOD add. APPEND is_file TO mt_files. ENDMETHOD. METHOD add_abap. DATA: lv_source TYPE string, ls_file TYPE zif_abapgit_git_definitions=>ty_file. CONCATENATE LINES OF it_abap INTO lv_source SEPARATED BY cl_abap_char_utilities=>newline. * when editing files via eg. GitHub web interface it adds a newline at end of file lv_source = lv_source && cl_abap_char_utilities=>newline. ls_file-path = '/'. ls_file-filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_extra = iv_extra iv_ext = 'abap' ). ls_file-data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_source ). APPEND ls_file TO mt_files. ENDMETHOD. METHOD add_i18n_file. DATA ls_file TYPE zif_abapgit_git_definitions=>ty_file. ls_file-data = ii_i18n_file->render( ). IF ls_file-data IS INITIAL. RETURN. " Don't add empty files ENDIF. ls_file-path = '/'. ls_file-filename = zcl_abapgit_filename_logic=>object_to_i18n_file( is_item = ms_item iv_lang = ii_i18n_file->lang( ) iv_ext = ii_i18n_file->ext( ) ). APPEND ls_file TO mt_files. ENDMETHOD. METHOD add_raw. DATA: ls_file TYPE zif_abapgit_git_definitions=>ty_file. ls_file-path = '/'. ls_file-data = iv_data. ls_file-filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_extra = iv_extra iv_ext = iv_ext ). APPEND ls_file TO mt_files. ENDMETHOD. METHOD add_string. DATA: ls_file TYPE zif_abapgit_git_definitions=>ty_file. ls_file-path = '/'. ls_file-filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_extra = iv_extra iv_ext = iv_ext ). ls_file-data = zcl_abapgit_convert=>string_to_xstring_utf8( iv_string ). APPEND ls_file TO mt_files. ENDMETHOD. METHOD add_xml. DATA: lv_xml TYPE string, ls_file TYPE zif_abapgit_git_definitions=>ty_file. lv_xml = ii_xml->render( iv_normalize = iv_normalize is_metadata = is_metadata ). ls_file-path = '/'. ls_file-filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_extra = iv_extra iv_ext = 'xml' ). REPLACE FIRST OCCURRENCE OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' IN lv_xml WITH ''. ASSERT sy-subrc = 0. ls_file-data = zcl_abapgit_convert=>string_to_xstring_utf8_bom( lv_xml ). APPEND ls_file TO mt_files. ENDMETHOD. METHOD constructor. ms_item = is_item. mv_path = iv_path. ENDMETHOD. METHOD contains_file. DATA: lv_filename TYPE string. lv_filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_extra = iv_extra iv_ext = iv_ext ). IF mv_path IS NOT INITIAL. READ TABLE mt_files TRANSPORTING NO FIELDS WITH KEY file_path COMPONENTS path = mv_path filename = lv_filename. ELSE. READ TABLE mt_files TRANSPORTING NO FIELDS WITH KEY file COMPONENTS filename = lv_filename. ENDIF. IF sy-subrc = 0. rv_present = abap_true. ENDIF. ENDMETHOD. METHOD get_accessed_files. rt_files = mt_accessed_files. ENDMETHOD. METHOD get_files. rt_files = mt_files. ENDMETHOD. METHOD get_file_pattern. rv_pattern = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_ext = '*' ). " Escape special characters for use with 'covers pattern' (CP) REPLACE ALL OCCURRENCES OF '#' IN rv_pattern WITH '##'. REPLACE ALL OCCURRENCES OF '+' IN rv_pattern WITH '#+'. ENDMETHOD. METHOD is_json_metadata. DATA lv_pattern TYPE string. FIELD-SYMBOLS LIKE LINE OF mt_files. lv_pattern = |*.{ to_lower( ms_item-obj_type ) }.json|. LOOP AT mt_files ASSIGNING WHERE filename CP lv_pattern. rv_result = abap_true. EXIT. ENDLOOP. ENDMETHOD. METHOD mark_accessed. FIELD-SYMBOLS LIKE LINE OF mt_accessed_files. READ TABLE mt_accessed_files TRANSPORTING NO FIELDS WITH KEY path = iv_path filename = iv_file. IF sy-subrc > 0. " Not found ? -> Add APPEND INITIAL LINE TO mt_accessed_files ASSIGNING . -path = iv_path. -filename = iv_file. -sha1 = iv_sha1. ENDIF. ENDMETHOD. METHOD new. CREATE OBJECT ro_files EXPORTING is_item = is_item iv_path = iv_path. ENDMETHOD. METHOD read_abap. DATA: lv_filename TYPE string, lv_data TYPE xstring, lv_abap TYPE string. lv_filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_extra = iv_extra iv_ext = 'abap' ). lv_data = read_file( iv_filename = lv_filename iv_error = iv_error ). IF lv_data IS INITIAL. " Post-handling of iv_error = false RETURN. ENDIF. lv_abap = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). SPLIT lv_abap AT cl_abap_char_utilities=>newline INTO TABLE rt_abap. ENDMETHOD. METHOD read_file. FIELD-SYMBOLS LIKE LINE OF mt_files. IF mv_path IS NOT INITIAL. READ TABLE mt_files ASSIGNING WITH KEY file_path COMPONENTS path = mv_path filename = iv_filename. ELSE. READ TABLE mt_files ASSIGNING WITH KEY file COMPONENTS filename = iv_filename. ENDIF. IF sy-subrc <> 0. IF iv_error = abap_true. zcx_abapgit_exception=>raise( |File not found: { iv_filename }| ). ELSE. RETURN. ENDIF. ENDIF. " Update access table mark_accessed( iv_path = -path iv_file = -filename iv_sha1 = -sha1 ). rv_data = -data. ENDMETHOD. METHOD read_i18n_files. DATA: lv_lang TYPE laiso, lv_ext TYPE string, lo_po TYPE REF TO zcl_abapgit_po_file, lo_properties TYPE REF TO zcl_abapgit_properties_file. FIELD-SYMBOLS LIKE LINE OF mt_files. LOOP AT mt_files ASSIGNING . zcl_abapgit_filename_logic=>i18n_file_to_object( EXPORTING iv_path = -path iv_filename = -filename IMPORTING ev_lang = lv_lang ev_ext = lv_ext ). CASE lv_ext. WHEN 'po'. CREATE OBJECT lo_po EXPORTING iv_lang = lv_lang. lo_po->parse( -data ). APPEND lo_po TO rt_i18n_files. WHEN 'properties'. CREATE OBJECT lo_properties EXPORTING iv_lang = lv_lang. lo_properties->parse( -data ). APPEND lo_properties TO rt_i18n_files. WHEN OTHERS. CONTINUE. " Unsupported i18n file type ENDCASE. mark_accessed( iv_path = -path iv_file = -filename iv_sha1 = -sha1 ). ENDLOOP. ENDMETHOD. METHOD read_raw. DATA: lv_filename TYPE string. lv_filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_extra = iv_extra iv_ext = iv_ext ). rv_data = read_file( lv_filename ). ENDMETHOD. METHOD read_string. DATA: lv_filename TYPE string, lv_data TYPE xstring. lv_filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_extra = iv_extra iv_ext = iv_ext ). lv_data = read_file( lv_filename ). rv_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). ENDMETHOD. METHOD read_xml. DATA: lv_filename TYPE string, lv_data TYPE xstring, lv_xml TYPE string. lv_filename = zcl_abapgit_filename_logic=>object_to_file( is_item = ms_item iv_extra = iv_extra iv_ext = 'xml' ). lv_data = read_file( lv_filename ). lv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( lv_data ). CREATE OBJECT ri_xml TYPE zcl_abapgit_xml_input EXPORTING iv_xml = lv_xml iv_filename = lv_filename. ENDMETHOD. METHOD set_files. FIELD-SYMBOLS: LIKE LINE OF it_files. CLEAR mt_files. " Set only files matching the pattern for this object " If a path has been defined in the constructor, then the path has to match, too LOOP AT it_files ASSIGNING WHERE filename CP get_file_pattern( ). IF mv_path IS INITIAL. INSERT INTO TABLE mt_files. ELSEIF mv_path = -path. INSERT INTO TABLE mt_files. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_objects_check IMPLEMENTATION. 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_multiple_files. DATA: lv_msg TYPE string, lv_lstate TYPE c LENGTH 2, lv_rstate TYPE c LENGTH 2, lt_res_sort LIKE it_results, ls_result LIKE LINE OF it_results. FIELD-SYMBOLS LIKE LINE OF it_results. lt_res_sort = it_results. SORT lt_res_sort BY filename ASCENDING. " Prevent pulling if there is more than one file with the same name LOOP AT lt_res_sort ASSIGNING WHERE obj_type <> 'DEVC' AND packmove = abap_false AND filename IS NOT INITIAL. " Changing package and object at the same time is ok (state: Add + Delete) CONCATENATE -lstate ls_result-lstate INTO lv_lstate RESPECTING BLANKS. CONCATENATE -rstate ls_result-rstate INTO lv_rstate RESPECTING BLANKS. IF -filename = ls_result-filename AND lv_lstate <> 'AD' AND lv_lstate <> 'DA' AND lv_rstate <> 'AD' AND lv_rstate <> 'DA'. lv_msg = |Pull not possible since there are multiple files with same filename, { -filename }.| && | Keep one of the files and delete the other in the repository.|. zcx_abapgit_exception=>raise( lv_msg ). ENDIF. MOVE-CORRESPONDING TO ls_result. ENDLOOP. ENDMETHOD. METHOD class_constructor. gi_exit = zcl_abapgit_exit=>get_instance( ). ENDMETHOD. METHOD deserialize_checks. DATA: lt_results TYPE zif_abapgit_definitions=>ty_results_tt, li_package TYPE REF TO zif_abapgit_sap_package. " get unfiltered status to evaluate properly which warnings are required lt_results = zcl_abapgit_repo_status=>calculate( io_repo ). check_multiple_files( lt_results ). 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( ). rs_checks-transport-transport = determine_transport_request( io_repo = io_repo iv_transport_type = rs_checks-transport-type ). ENDIF. ENDIF. ENDMETHOD. METHOD determine_transport_request. " Use transport from repo settings if maintained, or determine via user exit. " If transport keeps empty here, it'll requested later via popup. rv_transport_request = io_repo->get_local_settings( )-transport_request. gi_exit->determine_transport_request( EXPORTING io_repo = io_repo iv_transport_type = iv_transport_type CHANGING cv_transport_request = rv_transport_request ). 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 = zif_abapgit_definitions=>c_no. 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_item TYPE zif_abapgit_definitions=>ty_item, lv_status TYPE c LENGTH 2, lt_changes TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_overwrite WITH DEFAULT KEY. FIELD-SYMBOLS: LIKE LINE OF it_results, LIKE LINE OF lt_changes. " collect all actions for object that have been changed LOOP AT it_results ASSIGNING WHERE NOT obj_type IS INITIAL. APPEND INITIAL LINE TO lt_changes ASSIGNING . MOVE-CORRESPONDING TO . -devclass = -package. MOVE-CORRESPONDING TO ls_item. IF -packmove = abap_true. -action = zif_abapgit_objects=>c_deserialize_action-packmove. -icon = icon_package_standard. -text = 'Change package assignment'. ELSEIF zcl_abapgit_objects=>is_supported( ls_item ) = abap_false AND ls_item-obj_type <> zif_abapgit_data_config=>c_data_type-tabu. -action = zif_abapgit_objects=>c_deserialize_action-no_support. -icon = icon_no_status. -text = 'Object type not supported'. ELSE. CONCATENATE -lstate -rstate INTO lv_status RESPECTING BLANKS. -state = lv_status. REPLACE ALL OCCURRENCES OF ` ` IN -state WITH '_'. CASE lv_status. WHEN ' '. " no changes -action = zif_abapgit_objects=>c_deserialize_action-none. WHEN ' A' OR 'D ' OR 'DM'. " added remotely or deleted locally -action = zif_abapgit_objects=>c_deserialize_action-add. -icon = icon_create. -text = 'Add local object'. WHEN 'A ' OR ' D' OR 'MD'. " added locally or deleted remotely -action = zif_abapgit_objects=>c_deserialize_action-delete. -icon = icon_delete. -text = 'Delete local object'. WHEN 'M ' OR 'MM'. " modified locally -action = zif_abapgit_objects=>c_deserialize_action-overwrite. -icon = icon_change. -text = 'Overwrite local object'. WHEN ' M'. " modified only remotely -action = zif_abapgit_objects=>c_deserialize_action-update. -icon = icon_change. -text = 'Update local object'. WHEN OTHERS. ASSERT 0 = 1. ENDCASE. ENDIF. ENDLOOP. " Remove duplicate actions SORT lt_changes. DELETE ADJACENT DUPLICATES FROM lt_changes. " Check if deletions are for complete object or just a part LOOP AT lt_changes ASSIGNING WHERE action = zif_abapgit_objects=>c_deserialize_action-delete. LOOP AT lt_changes TRANSPORTING NO FIELDS WHERE obj_type = -obj_type AND obj_name = -obj_name AND action <> zif_abapgit_objects=>c_deserialize_action-delete. EXIT. ENDLOOP. IF sy-subrc = 0. " There's some other action, so object will be recreated after deletion -action = zif_abapgit_objects=>c_deserialize_action-delete_add. -icon = icon_adopt. -text = 'Delete and recreate local object'. ENDIF. ENDLOOP. DELETE lt_changes WHERE action = zif_abapgit_objects=>c_deserialize_action-none. " If there are multiple changes in an object, keep highest priority action SORT lt_changes BY obj_type obj_name action DESCENDING. DELETE ADJACENT DUPLICATES FROM lt_changes COMPARING obj_type obj_name. rt_overwrite = lt_changes. 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 of package { -obj_type } { -obj_name } undecided| ). ENDIF. IF ls_overwrite-decision = zif_abapgit_definitions=>c_no. 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 WHERE match IS INITIAL AND packmove IS INITIAL. lv_package = lo_folder_logic->path_to_package( iv_top = io_repo->get_package( ) io_dot = io_repo->get_dot_abapgit( ) iv_path = -path iv_create_if_not_exists = abap_false ). 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. CONCATENATE -lstate -rstate INTO ls_overwrite-state RESPECTING BLANKS. REPLACE ALL OCCURRENCES OF ` ` IN ls_overwrite-state WITH '_'. ls_overwrite-obj_type = -obj_type. ls_overwrite-obj_name = -obj_name. ls_overwrite-devclass = ls_tadir-devclass. ls_overwrite-action = zif_abapgit_objects=>c_deserialize_action-overwrite. ls_overwrite-icon = icon_change. ls_overwrite-text = 'Overwrite local object'. INSERT ls_overwrite INTO TABLE lt_overwrite_unique. ENDIF. ENDLOOP. rt_overwrite = lt_overwrite_unique. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_objects_activation IMPLEMENTATION. METHOD activate. " Make sure that all changes are committed since any activation error will lead to a rollback COMMIT WORK AND WAIT. IF use_new_activation_logic( ) = abap_true. activate_new( iv_ddic = iv_ddic ii_log = ii_log ). ELSE. activate_old( iv_ddic = iv_ddic ii_log = ii_log ). ENDIF. update_where_used( ii_log ). ENDMETHOD. METHOD activate_ddic. DATA: lt_gentab TYPE STANDARD TABLE OF dcgentb, lv_rc TYPE sy-subrc, ls_gentab LIKE LINE OF lt_gentab, lt_deltab TYPE STANDARD TABLE OF dcdeltb, lt_action_tab TYPE STANDARD TABLE OF dctablres, lv_logname TYPE ddmass-logname. FIELD-SYMBOLS: LIKE LINE OF gt_objects. LOOP AT gt_objects ASSIGNING . " Filter types supported by mass activation IF is_ddic_type( -object ) = abap_false. CONTINUE. ENDIF. ls_gentab-tabix = sy-tabix. get_ddic_type( EXPORTING iv_obj_type = -object iv_obj_name = -obj_name IMPORTING ev_type = ls_gentab-type ev_name = ls_gentab-name ev_id = ls_gentab-indx ). INSERT ls_gentab INTO TABLE lt_gentab. ENDLOOP. IF lt_gentab IS NOT INITIAL. lv_logname = |ABAPGIT_{ sy-datum }_{ sy-uzeit }|. IF lines( lt_gentab ) = 1. ii_log->add_info( |> Mass activating 1 DDIC object| ). ELSE. ii_log->add_info( |> Mass activating { lines( lt_gentab ) } DDIC objects| ). ENDIF. ii_log->add_info( |Log name: { lv_logname }| ). CALL FUNCTION 'DD_MASS_ACT_C3' EXPORTING ddmode = 'O' " activate changes in Original System frcact = abap_true " force Activation medium = 'T' " transport order device = 'T' " saves to table DDRPH? version = 'M' " activate newest version logname = lv_logname write_log = abap_true log_head_tail = abap_true t_on = space prid = 1 IMPORTING act_rc = lv_rc TABLES gentab = lt_gentab deltab = lt_deltab cnvtab = lt_action_tab EXCEPTIONS access_failure = 1 no_objects = 2 locked = 3 internal_error = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF lv_rc > 0. add_errors_and_warnings_to_log( iv_logname = lv_logname ii_log = ii_log ). ENDIF. IF lv_rc > 4. zcx_abapgit_exception=>raise( 'Activation cancelled. Check the inactive objects.' ). ENDIF. " Remove objects from activation queue to avoid double activation in activate_old LOOP AT lt_gentab INTO ls_gentab. DELETE gt_objects WHERE object = ls_gentab-type AND obj_name = ls_gentab-name. ENDLOOP. DELETE gt_objects WHERE object = 'INDX' OR object = 'XINX' OR object = 'MCID'. ENDIF. ENDMETHOD. METHOD activate_new. IF gt_objects IS INITIAL. RETURN. ENDIF. IF iv_ddic = abap_true. activate_ddic( ii_log ). ELSE. activate_old( ii_log ). ENDIF. ENDMETHOD. METHOD activate_old. DATA: lv_popup TYPE abap_bool, lv_no_ui TYPE abap_bool, lv_try_again TYPE abap_bool, lv_msg TYPE string, lo_checklist TYPE REF TO cl_wb_checklist. IF gt_objects IS NOT INITIAL. IF zcl_abapgit_ui_factory=>get_frontend_services( )->gui_is_available( ) = abap_true. IF zcl_abapgit_persist_factory=>get_settings( )->read( )->get_activate_wo_popup( ) = abap_true. lv_popup = abap_false. ELSE. lv_popup = abap_true. ENDIF. ELSE. lv_popup = abap_false. ENDIF. lv_no_ui = boolc( lv_popup = abap_false ). IF iv_ddic = abap_true. lv_msg = |(with DDIC)|. ENDIF. IF lines( gt_objects ) = 1. ii_log->add_info( |> Activating 1 object { lv_msg }| ). ELSE. ii_log->add_info( |> Activating { lines( gt_objects ) } objects { lv_msg }| ). ENDIF. TRY. CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE' EXPORTING activate_ddic_objects = iv_ddic with_popup = lv_popup ui_decoupled = lv_no_ui IMPORTING p_checklist = lo_checklist TABLES objects = gt_objects EXCEPTIONS excecution_error = 1 cancelled = 2 insert_into_corr_error = 3 OTHERS = 4 ##SUBRC_OK. CATCH cx_sy_dyn_call_param_not_found. CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE' EXPORTING activate_ddic_objects = iv_ddic with_popup = lv_popup IMPORTING p_checklist = lo_checklist TABLES objects = gt_objects EXCEPTIONS excecution_error = 1 cancelled = 2 insert_into_corr_error = 3 OTHERS = 4 ##SUBRC_OK. ENDTRY. CASE sy-subrc. WHEN 1 OR 3 OR 4. zcx_abapgit_exception=>raise_t100( ). WHEN 2. lv_msg = 'Check the log and inactive objects.'. IF lv_popup = abap_false. lv_try_again = add_activation_errors_to_log( ii_log = ii_log io_checklist = lo_checklist ). IF lv_try_again = abap_true. lv_msg = 'Turn on "Activation Popup" in "Personal Settings" and try again'. ENDIF. ENDIF. zcx_abapgit_exception=>raise( |Activation cancelled. { lv_msg }| ). ENDCASE. ENDIF. ENDMETHOD. METHOD add. * function group SEWORKINGAREA * function module RS_INSERT_INTO_WORKING_AREA * class CL_WB_ACTIVATION_WORK_AREA FIELD-SYMBOLS: TYPE dwinactiv, LIKE LINE OF gt_classes. IF iv_type = 'CLAS' OR iv_type = 'INTF'. APPEND INITIAL LINE TO gt_classes ASSIGNING . -object = iv_type. -clsname = iv_name. ELSE. APPEND INITIAL LINE TO gt_objects ASSIGNING . -object = iv_type. -obj_name = iv_name. -delet_flag = iv_delete. ENDIF. ENDMETHOD. METHOD add_activation_errors_to_log. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, lt_message TYPE swbme_error_tab. FIELD-SYMBOLS: TYPE string, LIKE LINE OF lt_message. io_checklist->get_error_messages( IMPORTING p_error_tab = lt_message ). LOOP AT lt_message ASSIGNING WHERE mtype = 'E'. " When activating without popup, includes used in multiple main programs cause error " Run again WITH activation popup (see abapGit, Personal Settings) IF -message-msgid = 'EU' AND -message-msgno = '404'. rv_try_again = abap_true. ENDIF. CLEAR ls_item. IF strlen( -object_text ) > 5. ls_item-obj_type = -object_text(4). ls_item-obj_name = -object_text+5(*). ELSE. ls_item-obj_name = -show_req->object_name. SELECT SINGLE tadir FROM euobjedit INTO ls_item-obj_type WHERE type = -show_req->object_type. ENDIF. LOOP AT -mtext ASSIGNING . ii_log->add_error( iv_msg = is_item = ls_item ). ENDLOOP. ENDLOOP. ENDMETHOD. METHOD add_errors_and_warnings_to_log. DATA: lt_lines TYPE STANDARD TABLE OF trlog, lv_logname_db TYPE ddprh-protname. FIELD-SYMBOLS: LIKE LINE OF lt_lines. lv_logname_db = iv_logname. CALL FUNCTION 'TR_READ_LOG' EXPORTING iv_log_type = 'DB' iv_logname_db = lv_logname_db TABLES et_lines = lt_lines EXCEPTIONS invalid_input = 1 access_error = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. " Only error messages DELETE lt_lines WHERE severity <> 'E' AND severity <> 'W'. " Remove "Return code..." message DELETE lt_lines WHERE class = 'D0' AND number = '319'. LOOP AT lt_lines ASSIGNING . ii_log->add( iv_msg = -line iv_type = -severity ). ENDLOOP. ii_log->add_info( |View complete activation log in program RSPUTPRT (type D, log name { iv_logname })| ). ENDMETHOD. METHOD add_item. add( iv_type = is_item-obj_type iv_name = is_item-obj_name ). ENDMETHOD. METHOD clear. CLEAR gt_objects. CLEAR gt_classes. ENDMETHOD. METHOD get_ddic_type. DATA lv_obj_name TYPE e071-obj_name. ev_type = iv_obj_type. IF ev_type = 'INDX' OR ev_type = 'XINX' OR ev_type = 'MCID'. lv_obj_name = iv_obj_name. "cast CALL FUNCTION 'DD_E071_TO_DD' EXPORTING object = ev_type obj_name = lv_obj_name IMPORTING name = ev_name id = ev_id EXCEPTIONS illegal_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ELSE. ev_name = iv_obj_name. ENDIF. ENDMETHOD. METHOD is_active. " Checks if object is active or not " " Note: If object does not exist, this method returns true " is_not_inactive might be a better name but we avoid the double negative IF is_ddic_type( is_item-obj_type ) = abap_true AND c_para NS is_item-obj_type AND c_switches NS is_item-obj_type. rv_active = is_ddic_active( is_item ). ELSE. rv_active = is_non_ddic_active( is_item ). ENDIF. ENDMETHOD. METHOD is_ddic_active. DATA: lv_type TYPE ddobjtyp, lv_name TYPE ddobjname, lv_id TYPE ddobjectid, lv_state TYPE ddgotstate. get_ddic_type( EXPORTING iv_obj_type = is_item-obj_type iv_obj_name = is_item-obj_name IMPORTING ev_type = lv_type ev_name = lv_name ev_id = lv_id ). " Check if an inactive version of the DDIC object exists " state = 'A' checks if an active version exists but does not detect new or modified objects " state = 'M' checks for all possible versions so we can find out if an inactive one exists " See documentation of the function module CALL FUNCTION 'DDIF_STATE_GET' EXPORTING type = lv_type name = lv_name id = lv_id state = 'M' IMPORTING gotstate = lv_state EXCEPTIONS illegal_input = 1 OTHERS = 2. rv_active = boolc( sy-subrc = 0 AND ( lv_state = '' OR lv_state = 'A' ) ). ENDMETHOD. METHOD is_ddic_type. " Determine if object can be handled by mass activation (see RADMASUTC form ma_tab_check) rv_result = abap_true. IF c_domain NS iv_obj_type AND c_types NS iv_obj_type AND c_technset NS iv_obj_type AND c_f4_objects NS iv_obj_type AND c_enqueue NS iv_obj_type AND c_sqsc NS iv_obj_type AND c_stob NS iv_obj_type AND c_ntab NS iv_obj_type AND c_ddls NS iv_obj_type AND c_para NS iv_obj_type AND c_switches NS iv_obj_type AND iv_obj_type <> c_enhd. rv_result = abap_false. ENDIF. ENDMETHOD. METHOD is_non_ddic_active. DATA: lt_messages TYPE STANDARD TABLE OF sprot_u WITH DEFAULT KEY, ls_e071 TYPE e071, lt_e071 TYPE STANDARD TABLE OF e071 WITH DEFAULT KEY. ls_e071-object = is_item-obj_type. ls_e071-obj_name = is_item-obj_name. INSERT ls_e071 INTO TABLE lt_e071. CALL FUNCTION 'RS_INACTIVE_OBJECTS_WARNING' EXPORTING suppress_protocol = abap_false with_program_includes = abap_false suppress_dictionary_check = abap_false TABLES p_e071 = lt_e071 p_xmsg = lt_messages. rv_active = boolc( lt_messages IS INITIAL ). ENDMETHOD. METHOD update_where_used. DATA: ls_class LIKE LINE OF gt_classes, lo_cross TYPE REF TO cl_wb_crossreference, ls_item TYPE zif_abapgit_definitions=>ty_item, lv_msg TYPE string, lv_error TYPE c LENGTH 1, lv_include TYPE syrepid. LOOP AT gt_classes INTO ls_class. CASE ls_class-object. WHEN 'CLAS'. lv_include = cl_oo_classname_service=>get_classpool_name( ls_class-clsname ). WHEN 'INTF'. lv_include = cl_oo_classname_service=>get_interfacepool_name( ls_class-clsname ). ENDCASE. CREATE OBJECT lo_cross EXPORTING p_name = lv_include p_include = lv_include. lo_cross->index_actualize( IMPORTING p_error = lv_error ). IF lv_error = abap_true. ls_item-obj_type = ls_class-object. ls_item-obj_name = ls_class-clsname. lv_msg = |Error updating where-used list for { ls_item-obj_type } { ls_item-obj_name }.| && | Check for syntax errors|. ii_log->add( iv_msg = lv_msg is_item = ls_item ). ENDIF. ENDLOOP. ENDMETHOD. METHOD use_new_activation_logic. IF zcl_abapgit_factory=>get_function_module( )->function_exists( 'DD_MASS_ACT_C3' ) = abap_true. rv_use_new_activation_logic = abap_true. ENDIF. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ITEM_GRAPH IMPLEMENTATION. METHOD add_edge. DATA ls_edge LIKE LINE OF mt_edges. ASSERT is_from IS NOT INITIAL. ASSERT is_to IS NOT INITIAL. ls_edge-from = is_from. ls_edge-to = is_to. APPEND ls_edge TO mt_edges. ENDMETHOD. METHOD constructor. INSERT LINES OF it_items INTO TABLE mt_vertices. ENDMETHOD. METHOD get_next. * find a vertex with no inbound edges, if it does not exist pick anything DATA ls_vertex LIKE LINE OF mt_vertices. DATA lv_index TYPE i. LOOP AT mt_vertices INTO ls_vertex. lv_index = sy-tabix. READ TABLE mt_edges WITH KEY sec_to COMPONENTS to-obj_type = ls_vertex-obj_type to-obj_name = ls_vertex-obj_name TRANSPORTING NO FIELDS. IF sy-subrc <> 0. remove_vertex( lv_index ). rs_item = ls_vertex. RETURN. ENDIF. ENDLOOP. IF mv_warning = abap_false. * only issue the warning once per graph ii_log->add_warning( |Cycle detected in item graph| ). mv_warning = abap_true. ENDIF. READ TABLE mt_vertices INTO rs_item INDEX 1. ASSERT sy-subrc = 0. remove_vertex( 1 ). ENDMETHOD. METHOD has_vertices. rv_bool = boolc( lines( mt_vertices ) > 0 ). ENDMETHOD. METHOD remove_vertex. DATA ls_vertex LIKE LINE OF mt_vertices. READ TABLE mt_vertices INDEX iv_index INTO ls_vertex. ASSERT sy-subrc = 0. DELETE mt_vertices INDEX iv_index. DELETE mt_edges USING KEY sec_from WHERE from-obj_type = ls_vertex-obj_type AND from-obj_name = ls_vertex-obj_name. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_folder_logic IMPLEMENTATION. METHOD get_instance. CREATE OBJECT ro_instance. ENDMETHOD. METHOD get_parent. DATA: ls_parent LIKE LINE OF mt_parent. " Check that package is included in the TOP package hierarchy IF mt_top_subpackages IS INITIAL. mt_top_subpackages = zcl_abapgit_factory=>get_sap_package( iv_top )->list_subpackages( ). ENDIF. READ TABLE mt_top_subpackages TRANSPORTING NO FIELDS WITH KEY devclass = iv_package. IF sy-subrc <> 0. RETURN. ENDIF. "Determine Parent Package READ TABLE mt_parent INTO ls_parent WITH TABLE KEY devclass = iv_package. IF sy-subrc <> 0. rv_parent = zcl_abapgit_factory=>get_sap_package( iv_package )->read_parent( ). ls_parent-devclass = iv_package. ls_parent-parentcl = rv_parent. INSERT ls_parent INTO TABLE mt_parent. ELSE. rv_parent = ls_parent-parentcl. ENDIF. ENDMETHOD. METHOD package_to_path. DATA: lv_len TYPE i, lv_path TYPE string, lv_message TYPE string, lv_parentcl TYPE tdevc-parentcl, lv_folder_logic TYPE string. IF iv_top = iv_package. rv_path = io_dot->get_starting_folder( ). ELSE. lv_parentcl = get_parent( iv_top = iv_top iv_package = iv_package ). " If the parent package can not be determined, we return an initial path and handle " it outside of this class (in zcl_abapgit_file_status) IF lv_parentcl IS NOT INITIAL. lv_folder_logic = io_dot->get_folder_logic( ). CASE lv_folder_logic. WHEN zif_abapgit_dot_abapgit=>c_folder_logic-full. lv_len = 0. IF iv_package(1) = '$'. lv_len = 1. ENDIF. WHEN zif_abapgit_dot_abapgit=>c_folder_logic-prefix. lv_len = strlen( lv_parentcl ). IF iv_package(lv_len) <> lv_parentcl. " If abapGit project is installed in package ZZZ, all subpackages should be named " ZZZ_something. This will define the folder name in the zip file to be "something", " similarly with online projects. Alternatively change to FULL folder logic lv_message = |PREFIX: Unexpected package naming | && |(top: { iv_top }, parent: { lv_parentcl }, child: { iv_package }). | && |Try using the folder logic FULL|. zcx_abapgit_exception=>raise( lv_message ). ENDIF. WHEN zif_abapgit_dot_abapgit=>c_folder_logic-mixed. lv_len = strlen( iv_top ). IF iv_package(lv_len) <> iv_top. lv_message = |MIXED: Unexpected package naming | && |(top: { iv_top }, parent: { lv_parentcl }, child: { iv_package }). | && |Try using the folder logic FULL|. zcx_abapgit_exception=>raise( lv_message ). ENDIF. WHEN OTHERS. zcx_abapgit_exception=>raise( |Invalid folder logic: { lv_folder_logic }| ). ENDCASE. lv_path = iv_package+lv_len. IF strlen( lv_path ) = 0. zcx_abapgit_exception=>raise( |Folder logic: length = 0, parent: { lv_parentcl }, child: { iv_package }| ). ENDIF. IF lv_path(1) = '_'. lv_path = lv_path+1. ENDIF. IF strlen( lv_path ) = 0. zcx_abapgit_exception=>raise( |Folder logic: length = 0, parent: { lv_parentcl }, child: { iv_package }| ). ENDIF. TRANSLATE lv_path USING '/#'. TRANSLATE lv_path TO LOWER CASE. CONCATENATE lv_path '/' INTO lv_path. rv_path = package_to_path( iv_top = iv_top io_dot = io_dot iv_package = lv_parentcl ). CONCATENATE rv_path lv_path INTO rv_path. ENDIF. ENDIF. ENDMETHOD. METHOD path_to_package. DATA: lv_length TYPE i, lv_parent TYPE devclass, ls_package TYPE zif_abapgit_sap_package=>ty_create, lv_new TYPE string, lv_path TYPE string, lv_absolute_name TYPE string, lv_folder_logic TYPE string, lt_unique_package_names TYPE HASHED TABLE OF devclass WITH UNIQUE KEY table_line. lv_length = strlen( io_dot->get_starting_folder( ) ). IF lv_length > strlen( iv_path ). * treat as not existing locally RETURN. ENDIF. lv_path = iv_path+lv_length. lv_parent = iv_top. rv_package = iv_top. " Automatically create package using minimal properties " Details will be updated during deserialization IF iv_create_if_not_exists = abap_true. IF iv_top(1) = '$'. zcl_abapgit_factory=>get_sap_package( iv_top )->create_local( ). ELSE. ls_package-devclass = iv_top. ls_package-ctext = iv_top. ls_package-as4user = sy-uname. zcl_abapgit_factory=>get_sap_package( iv_top )->create( ls_package ). ENDIF. ENDIF. INSERT iv_top INTO TABLE lt_unique_package_names. WHILE lv_path CA '/'. SPLIT lv_path AT '/' INTO lv_new lv_path. lv_folder_logic = io_dot->get_folder_logic( ). CASE lv_folder_logic. WHEN zif_abapgit_dot_abapgit=>c_folder_logic-full. lv_absolute_name = lv_new. TRANSLATE lv_absolute_name USING '#/'. IF iv_top(1) = '$'. CONCATENATE '$' lv_absolute_name INTO lv_absolute_name. ENDIF. WHEN zif_abapgit_dot_abapgit=>c_folder_logic-prefix. CONCATENATE rv_package '_' lv_new INTO lv_absolute_name. WHEN zif_abapgit_dot_abapgit=>c_folder_logic-mixed. CONCATENATE iv_top '_' lv_new INTO lv_absolute_name. WHEN OTHERS. zcx_abapgit_exception=>raise( |Invalid folder logic: { lv_folder_logic }| ). ENDCASE. TRANSLATE lv_absolute_name TO UPPER CASE. IF strlen( lv_absolute_name ) > 30. zcx_abapgit_exception=>raise( |Package { lv_absolute_name } exceeds ABAP 30-characters name limit| ). ENDIF. rv_package = lv_absolute_name. READ TABLE lt_unique_package_names TRANSPORTING NO FIELDS WITH TABLE KEY table_line = rv_package. IF sy-subrc = 0. zcx_abapgit_exception=>raise( |Package { rv_package } has a subpackage with the same name| ). ELSE. INSERT rv_package INTO TABLE lt_unique_package_names. ENDIF. IF zcl_abapgit_factory=>get_sap_package( rv_package )->exists( ) = abap_false AND iv_create_if_not_exists = abap_true. zcl_abapgit_factory=>get_sap_package( lv_parent )->create_child( rv_package ). ENDIF. lv_parent = rv_package. ENDWHILE. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_filename_logic IMPLEMENTATION. METHOD detect_obj_definition. ev_is_xml = boolc( iv_ext = to_upper( c_package_file-extension ) AND strlen( iv_type ) = 4 ). ev_is_json = boolc( iv_ext = to_upper( c_json_file-extension ) AND strlen( iv_type ) = 4 ). ENDMETHOD. METHOD file_to_object. DATA: lv_name TYPE string, lv_type TYPE string, lv_ext TYPE string. " Guess object type and name SPLIT to_upper( iv_filename ) AT '.' INTO lv_name lv_type lv_ext. " Handle namespaces REPLACE ALL OCCURRENCES OF '#' IN lv_name WITH '/'. REPLACE ALL OCCURRENCES OF '#' IN lv_type WITH '/'. REPLACE ALL OCCURRENCES OF '#' IN lv_ext WITH '/'. " Assume AFF namespace convention IF go_aff_registry IS INITIAL. CREATE OBJECT go_aff_registry TYPE zcl_abapgit_aff_registry. ENDIF. IF go_aff_registry->is_supported_object_type( |{ lv_type }| ) = abap_true. REPLACE ALL OCCURRENCES OF '(' IN lv_name WITH '/'. REPLACE ALL OCCURRENCES OF ')' IN lv_name WITH '/'. ENDIF. " Get original object name lv_name = name_unescape( lv_name ). CLEAR es_item. es_item-obj_type = lv_type. es_item-obj_name = lv_name. " Get mapping specific to object type map_filename_to_object( EXPORTING iv_filename = iv_filename iv_path = iv_path io_dot = io_dot iv_package = iv_devclass CHANGING cs_item = es_item ). detect_obj_definition( EXPORTING iv_ext = lv_ext iv_type = lv_type IMPORTING ev_is_xml = ev_is_xml ev_is_json = ev_is_json ). ENDMETHOD. METHOD i18n_file_to_object. DATA lo_dot TYPE REF TO zcl_abapgit_dot_abapgit. lo_dot = zcl_abapgit_dot_abapgit=>build_default( ). file_to_object( EXPORTING iv_filename = iv_filename iv_path = iv_path io_dot = lo_dot IMPORTING es_item = es_item ). FIND FIRST OCCURRENCE OF REGEX 'i18n\.([^.]{2})\.([^.]+)$' IN iv_filename SUBMATCHES ev_lang ev_ext ##SUBRC_OK. ENDMETHOD. METHOD is_obj_definition_file. DATA: lv_xml TYPE abap_bool, lv_json TYPE abap_bool, lv_name TYPE string, lv_type TYPE string, lv_ext TYPE string. SPLIT to_upper( iv_filename ) AT '.' INTO lv_name lv_type lv_ext. detect_obj_definition( EXPORTING iv_ext = lv_ext iv_type = lv_type IMPORTING ev_is_xml = lv_xml ev_is_json = lv_json ). rv_yes = boolc( lv_json = abap_true OR lv_xml = abap_true ). ENDMETHOD. METHOD map_filename_to_object. DATA lv_class TYPE seoclsname. " TODO: Add check for supported object types to avoid calls to non-existing classes " zcl_abapgit_objects=>is_type_supported( is_item-obj_type ) " This will trigger class constructor of zcl_abapgit_objects_bridge reading table seometarel " which is currently not supported by abaplint test runner TRY. lv_class = 'ZCL_ABAPGIT_OBJECT_' && cs_item-obj_type. CALL METHOD (lv_class)=>('ZIF_ABAPGIT_OBJECT~MAP_FILENAME_TO_OBJECT') EXPORTING iv_filename = iv_filename iv_path = iv_path io_dot = io_dot iv_package = iv_package CHANGING cs_item = cs_item. CATCH cx_sy_dyn_call_illegal_class. " Map data config to TABU object type IF cs_item-obj_type = 'CONF'. cs_item-obj_type = 'TABU'. ENDIF. ENDTRY. ENDMETHOD. METHOD map_object_to_filename. DATA lv_class TYPE seoclsname. " TODO: Add check for supported object types to avoid calls to non-existing classes " zcl_abapgit_objects=>is_type_supported( is_item-obj_type ) " This will trigger class constructor of zcl_abapgit_objects_bridge reading table seometarel " which is currently not supported by abaplint test runner TRY. lv_class = 'ZCL_ABAPGIT_OBJECT_' && is_item-obj_type. CALL METHOD (lv_class)=>('ZIF_ABAPGIT_OBJECT~MAP_OBJECT_TO_FILENAME') EXPORTING is_item = is_item CHANGING cv_filename = cv_filename. CATCH cx_sy_dyn_call_illegal_class ##NO_HANDLER. ENDTRY. ENDMETHOD. METHOD name_escape. " Some characters in object names cause problems when identifying the object later " -> we escape these characters here " cl_http_utility=>escape_url doesn't do dots but escapes slash which we use for namespaces " -> we escape just some selected characters rv_name = iv_name. REPLACE ALL OCCURRENCES OF `#` IN rv_name WITH '%23'. REPLACE ALL OCCURRENCES OF `%` IN rv_name WITH '%25'. REPLACE ALL OCCURRENCES OF `.` IN rv_name WITH '%2e'. REPLACE ALL OCCURRENCES OF `<` IN rv_name WITH '%3c'. REPLACE ALL OCCURRENCES OF `=` IN rv_name WITH '%3d'. REPLACE ALL OCCURRENCES OF `>` IN rv_name WITH '%3e'. REPLACE ALL OCCURRENCES OF `?` IN rv_name WITH '%3f'. ENDMETHOD. METHOD name_unescape. " Replace all %xy with encoded character rv_name = cl_http_utility=>unescape_url( iv_name ). ENDMETHOD. METHOD object_to_file. DATA lv_obj_name TYPE string. DATA lv_nb_of_slash TYPE string. " Get escaped object name lv_obj_name = to_lower( name_escape( is_item-obj_name ) ). IF iv_extra IS INITIAL. CONCATENATE lv_obj_name '.' is_item-obj_type INTO rv_filename. ELSE. CONCATENATE lv_obj_name '.' is_item-obj_type '.' iv_extra INTO rv_filename. ENDIF. IF iv_ext IS NOT INITIAL. CONCATENATE rv_filename '.' iv_ext INTO rv_filename. ENDIF. " Get mapping specific to object type TRY. map_object_to_filename( EXPORTING is_item = is_item CHANGING cv_filename = rv_filename ). CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. " Handle namespaces CREATE OBJECT go_aff_registry TYPE zcl_abapgit_aff_registry. IF go_aff_registry->is_supported_object_type( is_item-obj_type ) = abap_true. FIND ALL OCCURRENCES OF `/` IN rv_filename MATCH COUNT lv_nb_of_slash. IF lv_nb_of_slash = 2. REPLACE FIRST OCCURRENCE OF `/` IN rv_filename WITH `(`. REPLACE `/` IN rv_filename WITH `)`. ENDIF. ELSE. REPLACE ALL OCCURRENCES OF '/' IN rv_filename WITH '#'. ENDIF. TRANSLATE rv_filename TO LOWER CASE. ENDMETHOD. METHOD object_to_i18n_file. rv_filename = object_to_file( is_item = is_item iv_extra = |i18n.{ iv_lang }| iv_ext = iv_ext ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_file_deserialize IMPLEMENTATION. 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. " Note: Moving the CHECK condition to the LOOP WHERE clause will lead to a " syntax warning in higher releases and syntax error in 702 LOOP AT lt_objects REFERENCE INTO lr_object. CHECK lr_object->obj_type IS INITIAL AND 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. "ignore objects that where deleted remotely DELETE rt_results WHERE rstate = zif_abapgit_definitions=>c_state-deleted. "log objects that exists only local or where deleted remotely 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. "ignore table content DELETE rt_results WHERE path = zif_abapgit_data_config=>c_default_path. 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_results. DATA lt_results TYPE zif_abapgit_definitions=>ty_results_tt. lt_results = filter_files_to_deserialize( it_results = zcl_abapgit_repo_status=>calculate( io_repo ) ii_log = ii_log ). rt_results = prioritize_deser( ii_log = ii_log it_results = lt_results ). 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 prioritize_deser. DATA lt_items TYPE zif_abapgit_definitions=>ty_items_tt. DATA ls_item LIKE LINE OF lt_items. DATA lt_requires TYPE zif_abapgit_definitions=>ty_items_tt. DATA ls_require LIKE LINE OF lt_requires. DATA ls_result LIKE LINE OF it_results. DATA lo_graph TYPE REF TO zcl_abapgit_item_graph. lt_items = map_results_to_items( it_results ). CREATE OBJECT lo_graph EXPORTING it_items = lt_items. LOOP AT lt_items INTO ls_item. CLEAR lt_requires. * TODO: BEGIN extract to object handler method in ZIF_ABAPGIT_OBJECT: * METHODS get_deserialize_order * IMPORTING * it_items TYPE ty_items_tt * RETURNING * VALUE(rt_requries) TYPE ty_items_tt CASE ls_item-obj_type. WHEN 'SPRX'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'WEBI'. WHEN 'CLAS'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'SPRX' AND obj_type <> 'INTF' AND obj_type <> 'XSLT'. WHEN 'PROG'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'XSLT'. WHEN 'INTF'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'SPRX' AND obj_type <> 'XSLT'. WHEN 'TABL'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'SPRX'. WHEN 'IARP'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'IASP'. WHEN 'IATU' OR 'IAXU' OR 'IAMU'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'IASP' AND obj_type <> 'PROG' AND obj_type <> 'IARP'. WHEN 'DCLS'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'DDLS'. WHEN 'ODSO'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'IOBJ'. WHEN 'SCP1'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'TOBJ'. WHEN 'CHAR'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'OTGR'. WHEN 'PINF'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'CLAS' AND obj_type <> 'INTF' AND obj_type <> 'TABL' AND obj_type <> 'DOMA' AND obj_type <> 'DTEL'. WHEN 'DEVC'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'PINF'. WHEN 'ENHC'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'ENHO'. WHEN 'ENHO'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'ENSC' AND obj_type <> 'ENHS'. WHEN 'ENSC'. lt_requires = lt_items. DELETE lt_requires WHERE obj_type <> 'ENHS'. ENDCASE. * TODO: END extract to object handler method LOOP AT lt_requires INTO ls_require. lo_graph->add_edge( is_from = ls_require is_to = ls_item ). ENDLOOP. ENDLOOP. WHILE lo_graph->has_vertices( ) = abap_true. ls_item = lo_graph->get_next( ii_log ). READ TABLE it_results INTO ls_result WITH KEY sec_key COMPONENTS obj_name = ls_item-obj_name obj_type = ls_item-obj_type. ASSERT sy-subrc = 0. APPEND ls_result TO rt_results. ENDWHILE. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_dependencies IMPLEMENTATION. METHOD get_ddls_dependencies. DATA: lt_ddls_name TYPE TABLE OF ddsymtab, ls_ddls_name TYPE ddsymtab. ls_ddls_name-name = iv_ddls_name. INSERT ls_ddls_name INTO TABLE lt_ddls_name. PERFORM ('DDLS_GET_DEP') IN PROGRAM ('RADMASDL') TABLES lt_ddls_name rt_dependency. ENDMETHOD. METHOD resolve. DATA: lv_tabclass TYPE dd02l-tabclass. FIELD-SYMBOLS: LIKE LINE OF ct_tadir. " misuse field KORRNUM to fix deletion sequence " higher value means later deletion LOOP AT ct_tadir ASSIGNING . CASE -object. WHEN 'DEVC'. " Packages last -korrnum = '999000'. WHEN 'DOMA'. -korrnum = '900000'. WHEN 'SPRX'. -korrnum = '850000'. WHEN 'WEBI'. -korrnum = '840000'. WHEN 'PARA'. " PARA after DTEL -korrnum = '810000'. WHEN 'DTEL'. -korrnum = '800000'. WHEN 'SHLP'. " SHLP after TABL -korrnum = '760000'. WHEN 'TTYP' OR 'TABL' OR 'VIEW'. SELECT SINGLE tabclass FROM dd02l INTO lv_tabclass WHERE tabname = -obj_name AND as4local = 'A' AND as4vers = '0000'. IF sy-subrc = 0 AND lv_tabclass = 'APPEND'. " delete append structures before database tables -korrnum = '730000'. ELSE. -korrnum = '750000'. ENDIF. WHEN 'ENQU'. " ENQU before TABL -korrnum = '725000'. WHEN 'DDLS'. " DDLS after DCLS but before other DDIC -korrnum = '720000'. WHEN 'DDLX'. " DDLX before DDLS -korrnum = '719000'. WHEN 'AUTH'. " AUTH after DCLS -korrnum = '715000'. WHEN 'SUSH'. " SUSH after SUSC -korrnum = '712000'. WHEN 'SUSC'. " SUSC after SUSO -korrnum = '711000'. WHEN 'SUSO'. " SUSO after DCLS -korrnum = '710000'. WHEN 'DCLS'. " AUTH and SUSO after DCLS -korrnum = '705000'. WHEN 'IASP'. -korrnum = '552000'. WHEN 'IARP'. -korrnum = '551000'. WHEN 'IATU'. -korrnum = '550000'. WHEN 'ACID'. " ACID after PROG/FUGR/CLAS -korrnum = '300000'. WHEN 'FUGR'. -korrnum = '260000'. WHEN 'PROG'. " delete includes after main programs SELECT COUNT(*) FROM reposrc WHERE progname = -obj_name AND r3state = 'A' AND subc = 'I'. IF sy-subrc = 0. -korrnum = '250000'. ELSE. -korrnum = '240000'. ENDIF. WHEN 'INTF'. -korrnum = '230000'. WHEN 'CLAS'. -korrnum = '220000'. WHEN 'IDOC'. -korrnum = '200000'. WHEN 'IOBJ'. -korrnum = '195000'. WHEN 'ODSO'. -korrnum = '190000'. WHEN 'WDCA'. -korrnum = '174000'. WHEN 'WDYA'. -korrnum = '173000'. WHEN 'WDCC'. -korrnum = '172000'. WHEN 'WDYN'. -korrnum = '171000'. WHEN 'IEXT'. -korrnum = '150000'. WHEN 'SAPC'. " SAPC after SICF -korrnum = '140000'. WHEN 'PINF'. " PINF before exposed objects -korrnum = '130000'. WHEN OTHERS. -korrnum = '100000'. ENDCASE. ENDLOOP. resolve_ddic( CHANGING ct_tadir = ct_tadir ). resolve_packages( CHANGING ct_tadir = ct_tadir ). SORT ct_tadir BY korrnum ASCENDING. ENDMETHOD. METHOD resolve_ddic. * this will make sure the deletion sequence of structures/tables work * in case they have dependencies with .INCLUDE TYPES: BEGIN OF ty_edge, from TYPE ty_item, to TYPE ty_item, END OF ty_edge. DATA: lt_nodes TYPE TABLE OF ty_item, lt_edges TYPE TABLE OF ty_edge, lt_findstrings TYPE TABLE OF rsfind, lv_plus TYPE i VALUE 1, lv_find_obj_cls TYPE euobj-id, lv_index TYPE i, lv_before TYPE i, lt_founds TYPE TABLE OF rsfindlst, lt_scope TYPE STANDARD TABLE OF seu_obj, lt_dependency TYPE ty_dedenpencies. FIELD-SYMBOLS: TYPE zif_abapgit_definitions=>ty_tadir, TYPE ty_dependency, TYPE zif_abapgit_definitions=>ty_tadir, LIKE LINE OF ct_tadir, LIKE LINE OF lt_edges, LIKE LINE OF lt_founds, LIKE LINE OF lt_nodes. " build nodes LOOP AT ct_tadir ASSIGNING WHERE object = 'TABL' OR object = 'VIEW' OR object = 'TTYP'. APPEND INITIAL LINE TO lt_nodes ASSIGNING . -obj_name = -obj_name. -obj_type = -object. ENDLOOP. APPEND 'TABL' TO lt_scope. APPEND 'VIEW' TO lt_scope. APPEND 'STRU' TO lt_scope. APPEND 'TTYP' TO lt_scope. " build edges LOOP AT lt_nodes ASSIGNING . CLEAR lt_findstrings. APPEND -obj_name TO lt_findstrings. lv_find_obj_cls = -obj_type. CALL FUNCTION 'RS_EU_CROSSREF' EXPORTING i_find_obj_cls = lv_find_obj_cls TABLES i_findstrings = lt_findstrings o_founds = lt_founds i_scope_object_cls = lt_scope EXCEPTIONS not_executed = 1 not_found = 2 illegal_object = 3 no_cross_for_this_object = 4 batch = 5 batchjob_error = 6 wrong_type = 7 object_not_exist = 8 OTHERS = 9. IF sy-subrc <> 0. CONTINUE. ENDIF. LOOP AT lt_founds ASSIGNING . APPEND INITIAL LINE TO lt_edges ASSIGNING . -from = . -to-obj_name = -object. CASE -object_cls. WHEN 'DS' OR 'DT'. -to-obj_type = 'TABL'. WHEN 'DV'. -to-obj_type = 'VIEW'. WHEN 'DA'. -to-obj_type = 'TTYP'. WHEN OTHERS. zcx_abapgit_exception=>raise( 'resolve_ddic, unknown object_cls' ). ENDCASE. ENDLOOP. ENDLOOP. " build DDLS edges SORT ct_tadir. "binary search LOOP AT ct_tadir ASSIGNING WHERE object = 'DDLS'. CLEAR: lt_dependency. APPEND INITIAL LINE TO lt_nodes ASSIGNING . -obj_name = -obj_name. -obj_type = -object. lt_dependency = get_ddls_dependencies( -obj_name ). LOOP AT lt_dependency ASSIGNING WHERE deptyp = 'DDLS' AND refname = -obj_name. READ TABLE ct_tadir ASSIGNING WITH KEY pgmid = 'R3TR' object = 'DDLS' obj_name = -depname BINARY SEARCH. CHECK sy-subrc = 0. APPEND INITIAL LINE TO lt_edges ASSIGNING . -from = . -to-obj_name = -depname. -to-obj_type = 'DDLS'. ENDLOOP. ENDLOOP. DO. lv_before = lines( lt_nodes ). LOOP AT lt_nodes ASSIGNING . lv_index = sy-tabix. READ TABLE lt_edges WITH KEY from-obj_name = -obj_name from-obj_type = -obj_type TRANSPORTING NO FIELDS. IF sy-subrc <> 0. LOOP AT ct_tadir ASSIGNING WHERE obj_name = -obj_name AND object = -obj_type. -korrnum = -korrnum + lv_plus. CONDENSE -korrnum. ENDLOOP. DELETE lt_edges WHERE to-obj_name = -obj_name AND to-obj_type = -obj_type. DELETE lt_nodes INDEX lv_index. EXIT. " make sure the sequence is fixed ENDIF. ENDLOOP. IF lv_before = lines( lt_nodes ). EXIT. ENDIF. lv_plus = lv_plus + 1. ENDDO. ENDMETHOD. METHOD resolve_packages. DATA: lt_subpackages TYPE zif_abapgit_sap_package=>ty_devclass_tt. FIELD-SYMBOLS: LIKE LINE OF ct_tadir, LIKE LINE OF lt_subpackages, LIKE LINE OF ct_tadir. " List subpackage before corresponding superpackage LOOP AT ct_tadir ASSIGNING WHERE object = 'DEVC'. lt_subpackages = zcl_abapgit_factory=>get_sap_package( |{ -obj_name }| )->list_subpackages( ). LOOP AT lt_subpackages ASSIGNING . READ TABLE ct_tadir ASSIGNING WITH KEY object = 'DEVC' obj_name = . IF sy-subrc = 0. -korrnum = condense( |{ -korrnum - 1 }| ). ENDIF. ENDLOOP. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_UIST IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lo_db_api TYPE REF TO object, lr_data TYPE REF TO data, lv_object_key TYPE seu_objkey, lx_root TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE OBJECT lo_db_api TYPE ('/UI2/CL_UIST_SVAL_SQL'). CREATE DATA lr_data TYPE ('CL_BLUE_AFF_WB_ACCESS=>TY_METADATA'). ASSIGN lr_data->* TO . CATCH cx_sy_create_object_error cx_sy_create_data_error. zcx_abapgit_exception=>raise( 'Object UIST not supported' ). ENDTRY. TRY. lv_object_key = ms_item-obj_name. CALL METHOD lo_db_api->('/UI2/IF_UIST_SVAL~GET_METADATA') EXPORTING object_name = lv_object_key version = 'A' language = mv_language RECEIVING result = . ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . rv_user = . CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_UIPG IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lo_db_api TYPE REF TO object, lr_data TYPE REF TO data, lv_object_key TYPE c LENGTH 35, lx_root TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CALL METHOD ('/UI2/CL_UIPG_DB_ACCESS')=>('GET_INSTANCE') RECEIVING ro_instance = lo_db_api. CREATE DATA lr_data TYPE ('CL_BLUE_AFF_WB_ACCESS=>TY_METADATA'). ASSIGN lr_data->* TO . CATCH cx_sy_create_object_error cx_sy_create_data_error. zcx_abapgit_exception=>raise( 'Object UIPG not supported' ). ENDTRY. TRY. lv_object_key = ms_item-obj_name. CALL METHOD lo_db_api->('/UI2/IF_UIPG_DB_ACCESS~READ_WB_METADATA') EXPORTING iv_page_id = lv_object_key iv_version = 'A' iv_language = mv_language RECEIVING rs_metadata = . ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . rv_user = . CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise_with_text( lx_root ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_SMBC IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lo_handler TYPE REF TO object, lo_db_api TYPE REF TO object, lr_data TYPE REF TO data, lv_technical_id TYPE c LENGTH 30. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE OBJECT lo_handler TYPE ('CL_SMBC_AFF_OBJECT_HANDLER'). CREATE OBJECT lo_db_api TYPE ('CL_MBC_BUSINESS_CONFIG_DB'). CREATE DATA lr_data TYPE ('SMBC_CONFIG'). ASSIGN lr_data->* TO . CATCH cx_sy_create_object_error cx_sy_create_data_error. zcx_abapgit_exception=>raise( 'SMBC not supported' ). ENDTRY. lv_technical_id = ms_item-obj_name. CALL METHOD lo_db_api->('IF_MBC_BUSINESS_CONFIG_DB~READ') EXPORTING iv_technical_id = lv_technical_id version = 'I' RECEIVING rs_config = . IF IS INITIAL. CALL METHOD lo_db_api->('IF_MBC_BUSINESS_CONFIG_DB~READ') EXPORTING iv_technical_id = lv_technical_id version = 'A' RECEIVING rs_config = . ENDIF. ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . rv_user = . ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_ront IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lv_user TYPE string, lx_error TYPE REF TO cx_root. TRY. SELECT SINGLE changed_by INTO lv_user FROM (c_table_name) WHERE ront_name = ms_item-obj_name AND version = 'I'. IF lv_user IS INITIAL. SELECT SINGLE changed_by INTO lv_user FROM (c_table_name) WHERE ront_name = ms_item-obj_name AND version = 'A'. ENDIF. rv_user = lv_user. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_nont IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lv_user TYPE string, lx_error TYPE REF TO cx_root. TRY. SELECT SINGLE changed_by INTO lv_user FROM (c_table_name) WHERE nont_name = ms_item-obj_name AND version = 'I'. IF lv_user IS INITIAL. SELECT SINGLE changed_by INTO lv_user FROM (c_table_name) WHERE nont_name = ms_item-obj_name AND version = 'A'. ENDIF. rv_user = lv_user. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_GSMP IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA lv_name TYPE c LENGTH 180. DATA lv_user TYPE string. DATA lx_root TYPE REF TO cx_root. TRY. lv_name = ms_item-obj_name. SELECT SINGLE changed_by INTO lv_user FROM ('GSM_MD_PRV_W') WHERE provider_id = lv_name AND version = 'I'. IF lv_user IS INITIAL. SELECT SINGLE changed_by INTO lv_user FROM ('GSM_MD_PRV_W') WHERE provider_id = lv_name AND version = 'A'. ENDIF. rv_user = lv_user. CATCH cx_root INTO lx_root. zcx_abapgit_exception=>raise( iv_text = lx_root->get_text( ) ix_previous = lx_root ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_evtb IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lv_user TYPE string, lx_error TYPE REF TO cx_root. TRY. SELECT SINGLE changed_by INTO lv_user FROM (c_table_name) WHERE evtb_name = ms_item-obj_name AND version = 'I'. IF lv_user IS INITIAL. SELECT SINGLE changed_by INTO lv_user FROM (c_table_name) WHERE evtb_name = ms_item-obj_name AND version = 'A'. ENDIF. rv_user = lv_user. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_eeec IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lr_data TYPE REF TO data, lo_registry_adapter TYPE REF TO object, lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE OBJECT lo_registry_adapter TYPE ('/IWXBE/CL_EEEC_REG_ADAPTER'). CREATE DATA lr_data TYPE ('/IWXBE/IF_REGISTRY_TYPES=>TY_S_CONSUMER'). ASSIGN lr_data->* TO . lv_object_key = ms_item-obj_name. TRY. CALL METHOD lo_registry_adapter->('/IWXBE/IF_EEEC_REG_ADAPTER_WB~GET_METADATA') EXPORTING iv_object_key = lv_object_key iv_state = 'I' RECEIVING rs_consumer = . CATCH cx_root. CALL METHOD lo_registry_adapter->('/IWXBE/IF_EEEC_REG_ADAPTER_WB~GET_METADATA') EXPORTING iv_object_key = lv_object_key iv_state = 'A' RECEIVING rs_consumer = . ENDTRY. ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . rv_user = . CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise( iv_text = lx_error->get_text( ) ix_previous = lx_error ). ENDTRY. ENDMETHOD. METHOD get_object_handler. DATA lx_error TYPE REF TO cx_root. ro_object_handler = super->get_object_handler( ). IF ro_object_handler IS NOT BOUND. TRY. CREATE OBJECT ro_object_handler TYPE ('/IWXBE/CL_EEEC_AFF_OBJECTHANDL'). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise( iv_text = lx_error->get_text( ) ix_previous = lx_error ). ENDTRY. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_dteb IMPLEMENTATION. METHOD get_additional_extensions. DATA ls_additional_extension LIKE LINE OF rv_additional_extensions. ls_additional_extension-extension = 'acds'. CALL METHOD ('CL_CDS_AFF_FILE_NAME_MAPPER')=>for_cds RECEIVING result = ls_additional_extension-file_name_mapper. APPEND ls_additional_extension TO rv_additional_extensions. ENDMETHOD. METHOD zif_abapgit_object~changed_by. DATA: lo_dteb_handler TYPE REF TO object, lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. TRY. lv_object_key = ms_item-obj_name. CALL METHOD ('CL_DDIC_ADT_DT_UTILITY')=>('CREATE_DD_DTEB_HANDLER') EXPORTING object_key = lv_object_key RECEIVING handler = lo_dteb_handler. CALL METHOD lo_dteb_handler->('GET_CHANGED_BY') RECEIVING rv_changed_by = rv_user. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_drty IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lo_drty_handler TYPE REF TO object, lv_object_key TYPE seu_objkey, lx_error TYPE REF TO cx_root. TRY. lv_object_key = ms_item-obj_name. CALL METHOD ('CL_DRTY_AFF_OBJECT_HANDLER')=>('GET_DDIC_HANDLER') EXPORTING object_key = lv_object_key RECEIVING handler = lo_drty_handler. CALL METHOD lo_drty_handler->('GET_CHANGED_BY') RECEIVING rv_changed_by = rv_user. CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-ddic TO rt_steps. ENDMETHOD. METHOD get_additional_extensions. DATA ls_additional_extension LIKE LINE OF rv_additional_extensions. ls_additional_extension-extension = 'acds'. CALL METHOD ('CL_CDS_AFF_FILE_NAME_MAPPER')=>for_cds RECEIVING result = ls_additional_extension-file_name_mapper. APPEND ls_additional_extension TO rv_additional_extensions. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_object_common_aff IMPLEMENTATION. METHOD constructor. DATA: lv_is_supported TYPE abap_bool, li_aff_registry TYPE REF TO zif_abapgit_aff_registry, lo_handler TYPE REF TO object. super->constructor( is_item = is_item iv_language = iv_language io_files = io_files io_i18n_params = io_i18n_params ). " Check if AFF handler exists and if object type is registered and supported TRY. lo_handler = get_object_handler( ). CREATE OBJECT li_aff_registry TYPE zcl_abapgit_aff_registry. lv_is_supported = li_aff_registry->is_supported_object_type( is_item-obj_type ). CATCH cx_root. lv_is_supported = abap_false. ENDTRY. IF lv_is_supported IS INITIAL. zcx_abapgit_exception=>raise( |Object type { is_item-obj_type } is not supported by this system| ). ENDIF. ENDMETHOD. METHOD get_additional_extensions. RETURN. ENDMETHOD. METHOD get_object_handler. DATA lo_handler_factory TYPE REF TO object. CREATE OBJECT lo_handler_factory TYPE ('CL_AFF_OBJECT_HANDLER_FACTORY'). CALL METHOD lo_handler_factory->('IF_AFF_OBJECT_HANDLER_FACTORY~GET_OBJECT_HANDLER') EXPORTING object_type = ms_item-obj_type RECEIVING result = ro_object_handler. ENDMETHOD. METHOD is_file_empty. CALL METHOD io_object_json_file->('IF_AFF_FILE~IS_DELETION') RECEIVING result = rv_is_empty. ENDMETHOD. METHOD remove_abap_language_version. DATA lv_json TYPE string. DATA lv_json_wo_alv TYPE string. DATA li_json TYPE REF TO zif_abapgit_ajson. lv_json = zcl_abapgit_convert=>xstring_to_string_utf8( iv_json_as_xstring ). TRY. li_json = zcl_abapgit_ajson=>parse( iv_json = lv_json iv_keep_item_order = abap_true ). li_json->delete( '/header/abapLanguageVersion' ). lv_json_wo_alv = li_json->stringify( 2 ). rv_json_as_xstring_wo_alv = zcl_abapgit_convert=>string_to_xstring_utf8( lv_json_wo_alv ). CATCH zcx_abapgit_ajson_error. rv_json_as_xstring_wo_alv = iv_json_as_xstring. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~delete. DATA: lr_intf_aff_obj TYPE REF TO data, lr_intf_aff_log TYPE REF TO data, lr_messages TYPE REF TO data, lo_object_handler TYPE REF TO object, lo_object_aff TYPE REF TO object, lo_aff_factory TYPE REF TO object, lv_name TYPE c LENGTH 120, lx_error TYPE REF TO cx_root, lo_aff_log TYPE REF TO object. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE ANY TABLE, TYPE any, TYPE symsg. lv_name = ms_item-obj_name. TRY. lo_object_handler = get_object_handler( ). CREATE OBJECT lo_object_aff TYPE ('CL_AFF_OBJ') EXPORTING package = iv_package name = lv_name type = ms_item-obj_type. CREATE DATA lr_intf_aff_obj TYPE REF TO ('IF_AFF_OBJ'). ASSIGN lr_intf_aff_obj->* TO . ?= lo_object_aff. CREATE OBJECT lo_aff_factory TYPE ('CL_AFF_FACTORY'). CALL METHOD lo_aff_factory->('CREATE_LOG') RECEIVING result = lo_aff_log. CREATE DATA lr_intf_aff_log TYPE REF TO ('IF_AFF_LOG'). ASSIGN lr_intf_aff_log->* TO . ?= lo_aff_log. CALL METHOD lo_object_handler->('IF_AFF_OBJECT_HANDLER~DELETE') EXPORTING object = log = . CREATE DATA lr_messages TYPE ('IF_AFF_LOG=>TT_LOG_OUT'). ASSIGN lr_messages->* TO . CALL METHOD lo_aff_log->('IF_AFF_LOG~GET_MESSAGES') RECEIVING messages = . LOOP AT ASSIGNING . ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE TO . IF -msgty = 'E'. zcx_abapgit_exception=>raise_t100( iv_msgid = -msgid iv_msgno = -msgno iv_msgv1 = -msgv1 iv_msgv2 = -msgv2 iv_msgv3 = -msgv3 iv_msgv4 = -msgv4 ). ENDIF. ENDLOOP. tadir_delete( ). CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~deserialize. DATA: lr_intf_aff_obj TYPE REF TO data, lr_intf_aff_file TYPE REF TO data, lr_intf_files_container TYPE REF TO data, lr_intf_aff_log TYPE REF TO data, lr_intf_aff_settings TYPE REF TO data, lo_object_handler TYPE REF TO object, lo_object_aff TYPE REF TO object, lo_object_json_file TYPE REF TO object, lo_object_file TYPE REF TO object, lo_files_container TYPE REF TO object, lo_settings TYPE REF TO object, lo_aff_log TYPE REF TO object, lo_aff_factory TYPE REF TO object, lr_messages TYPE REF TO data, lv_json_as_xstring TYPE xstring, lx_exception TYPE REF TO cx_root, lv_file_name TYPE string, lo_file_name_mapper TYPE REF TO object, lv_name TYPE c LENGTH 120, lv_file_as_xstring TYPE xstring, ls_additional_extensions TYPE ty_extension_mapper_pairs. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any, TYPE any, TYPE any, TYPE ANY TABLE, TYPE any, TYPE any, TYPE any, TYPE symsg, LIKE LINE OF ls_additional_extensions. lv_json_as_xstring = mo_files->read_raw( 'json' ). lv_name = ms_item-obj_name. " beyond here there will be dragons.... TRY. lo_object_handler = get_object_handler( ). CREATE OBJECT lo_object_aff TYPE ('CL_AFF_OBJ') EXPORTING package = ms_item-devclass name = lv_name type = ms_item-obj_type. CREATE DATA lr_intf_aff_obj TYPE REF TO ('IF_AFF_OBJ'). ASSIGN lr_intf_aff_obj->* TO . ?= lo_object_aff. CREATE OBJECT lo_files_container TYPE ('CL_AFF_FILES_CONTAINER') EXPORTING object = . CALL METHOD ('CL_AFF_FILE_NAME_MAPPER')=>for_json RECEIVING result = lo_file_name_mapper. CALL METHOD lo_file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') EXPORTING object = RECEIVING result = lv_file_name. lo_settings = create_aff_setting_deserialize( ). CREATE OBJECT lo_object_json_file TYPE ('CL_AFF_FILE') EXPORTING name = lv_file_name content = lv_json_as_xstring. CREATE DATA lr_intf_aff_file TYPE REF TO ('IF_AFF_FILE'). ASSIGN lr_intf_aff_file->* TO . ?= lo_object_json_file. CALL METHOD lo_files_container->('ADD_FILE') EXPORTING file = . ls_additional_extensions = get_additional_extensions( ). LOOP AT ls_additional_extensions ASSIGNING . lv_file_as_xstring = mo_files->read_raw( -extension ). CALL METHOD -file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') EXPORTING object = RECEIVING result = lv_file_name. CREATE OBJECT lo_object_file TYPE ('CL_AFF_FILE') EXPORTING name = lv_file_name content = lv_file_as_xstring. CREATE DATA lr_intf_aff_file TYPE REF TO ('IF_AFF_FILE'). ASSIGN lr_intf_aff_file->* TO . ?= lo_object_file. CALL METHOD lo_files_container->('ADD_FILE') EXPORTING file = . ENDLOOP. CREATE OBJECT lo_aff_factory TYPE ('CL_AFF_FACTORY'). CALL METHOD lo_aff_factory->('CREATE_LOG') RECEIVING result = lo_aff_log. CREATE DATA lr_intf_files_container TYPE REF TO ('IF_AFF_FILES_CONTAINER'). ASSIGN lr_intf_files_container->* TO . ?= lo_files_container. CREATE DATA lr_intf_aff_log TYPE REF TO ('IF_AFF_LOG'). ASSIGN lr_intf_aff_log->* TO . ?= lo_aff_log. CREATE DATA lr_intf_aff_settings TYPE REF TO ('IF_AFF_SETTINGS_DESERIALIZE'). ASSIGN lr_intf_aff_settings->* TO . ?= lo_settings. CALL METHOD lo_object_handler->('IF_AFF_OBJECT_HANDLER~DESERIALIZE') EXPORTING files_container = log = settings = . CREATE DATA lr_messages TYPE ('IF_AFF_LOG=>TT_LOG_OUT'). ASSIGN lr_messages->* TO . CALL METHOD lo_aff_log->('IF_AFF_LOG~GET_MESSAGES') RECEIVING messages = . LOOP AT ASSIGNING . ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE TO . ASSIGN COMPONENT 'TEXT' OF STRUCTURE TO . ASSIGN COMPONENT 'TYPE' OF STRUCTURE TO . ii_log->add( iv_msg = iv_type = is_item = ms_item ). IF -msgty = 'E'. zcx_abapgit_exception=>raise_t100( iv_msgid = -msgid iv_msgno = -msgno iv_msgv1 = -msgv1 iv_msgv2 = -msgv2 iv_msgv3 = -msgv3 iv_msgv4 = -msgv4 ). ENDIF. ENDLOOP. IF is_active( ) = abap_false. " as DDIC-object e.g. are not deserialized in active state, activation must be performed zcl_abapgit_objects_activation=>add_item( ms_item ). ENDIF. tadir_insert( ms_item-devclass ). CATCH cx_root INTO lx_exception. ii_log->add_error( is_item = ms_item iv_msg = 'Error at deserialize' ). ii_log->add_exception( ix_exc = lx_exception is_item = ms_item ). ENDTRY. ENDMETHOD. METHOD create_aff_setting_deserialize. IF ms_item-abap_language_version <> zcl_abapgit_abap_language_vers=>c_any_abap_language_version AND ms_item-abap_language_version <> zcl_abapgit_abap_language_vers=>c_no_abap_language_version. CREATE OBJECT ro_settings_deserialize TYPE ('CL_AFF_SETTINGS_DESERIALIZE') EXPORTING version = 'A' language = mv_language user = sy-uname abap_language_version = ms_item-abap_language_version. ELSE. CREATE OBJECT ro_settings_deserialize TYPE ('CL_AFF_SETTINGS_DESERIALIZE') EXPORTING version = 'A' language = mv_language user = sy-uname. ENDIF. ENDMETHOD. METHOD zif_abapgit_object~exists. DATA: lr_intf_aff_obj TYPE REF TO data, lo_object_handler TYPE REF TO object, lo_object_aff TYPE REF TO object, lv_name TYPE c LENGTH 120, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any. lv_name = ms_item-obj_name. TRY. lo_object_handler = get_object_handler( ). CREATE OBJECT lo_object_aff TYPE ('CL_AFF_OBJ') EXPORTING package = ms_item-devclass name = lv_name type = ms_item-obj_type. CREATE DATA lr_intf_aff_obj TYPE REF TO ('IF_AFF_OBJ'). ASSIGN lr_intf_aff_obj->* TO . ?= lo_object_aff. CALL METHOD lo_object_handler->('IF_AFF_OBJECT_HANDLER~EXISTS') EXPORTING object = RECEIVING result = rv_bool. CATCH cx_root INTO lx_error. " return false instead of raising exception, because abapGit assumes " that raising exception = existing object rv_bool = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_object~get_comparator. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_order. RETURN. ENDMETHOD. METHOD zif_abapgit_object~get_deserialize_steps. APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps. ENDMETHOD. METHOD zif_abapgit_object~get_metadata. rs_metadata = get_metadata( ). ENDMETHOD. METHOD zif_abapgit_object~is_active. rv_active = is_active( ). ENDMETHOD. METHOD zif_abapgit_object~is_locked. DATA lv_lock_object TYPE string. DATA lv_argument TYPE seqg3-garg. lv_lock_object = |{ ms_item-obj_type }{ ms_item-obj_name }*|. lv_argument = lv_lock_object. rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'ESWB_EO' iv_argument = lv_argument ). ENDMETHOD. METHOD zif_abapgit_object~jump. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_filename_to_object. RETURN. ENDMETHOD. METHOD zif_abapgit_object~map_object_to_filename. RETURN. ENDMETHOD. METHOD zif_abapgit_object~serialize. DATA: lr_intf_aff_obj TYPE REF TO data, lr_intf_aff_log TYPE REF TO data, lr_intf_aff_settings TYPE REF TO data, lr_messages TYPE REF TO data, lo_object_handler TYPE REF TO object, lo_object_aff TYPE REF TO object, lo_object_json_file TYPE REF TO object, lo_files_container TYPE REF TO object, lo_settings TYPE REF TO object, lo_aff_log TYPE REF TO object, lo_aff_factory TYPE REF TO object, lo_object_file TYPE REF TO object, lv_json_as_xstring TYPE xstring, lv_json_as_xstring_wo_alv TYPE xstring, lx_exception TYPE REF TO cx_root, lv_name TYPE c LENGTH 120, lv_file_name TYPE string, lo_file_name_mapper TYPE REF TO object, ls_additional_extensions TYPE ty_extension_mapper_pairs, lv_file_as_xstring TYPE xstring. FIELD-SYMBOLS: TYPE any, TYPE any, TYPE any, TYPE ANY TABLE, TYPE any, TYPE symsg, LIKE LINE OF ls_additional_extensions. lv_name = ms_item-obj_name. TRY. lo_object_handler = get_object_handler( ). CREATE OBJECT lo_object_aff TYPE ('CL_AFF_OBJ') EXPORTING package = ms_item-devclass name = lv_name type = ms_item-obj_type. CREATE OBJECT lo_settings TYPE ('CL_AFF_SETTINGS_SERIALIZE') EXPORTING version = 'A' language = mv_language. CREATE OBJECT lo_aff_factory TYPE ('CL_AFF_FACTORY'). CALL METHOD lo_aff_factory->('CREATE_LOG') RECEIVING result = lo_aff_log. CREATE DATA lr_intf_aff_log TYPE REF TO ('IF_AFF_LOG'). ASSIGN lr_intf_aff_log->* TO . ?= lo_aff_log. CREATE DATA lr_intf_aff_settings TYPE REF TO ('IF_AFF_SETTINGS_SERIALIZE'). ASSIGN lr_intf_aff_settings->* TO . ?= lo_settings. CREATE DATA lr_intf_aff_obj TYPE REF TO ('IF_AFF_OBJ'). ASSIGN lr_intf_aff_obj->* TO . ?= lo_object_aff. CALL METHOD lo_object_handler->('IF_AFF_OBJECT_HANDLER~SERIALIZE') EXPORTING object = log = settings = RECEIVING result = lo_files_container. CREATE DATA lr_messages TYPE ('IF_AFF_LOG=>TT_LOG_OUT'). ASSIGN lr_messages->* TO . CALL METHOD lo_aff_log->('IF_AFF_LOG~GET_MESSAGES') RECEIVING messages = . LOOP AT ASSIGNING . ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE TO . IF -msgty = 'E'. zcx_abapgit_exception=>raise_t100( iv_msgid = -msgid iv_msgno = -msgno iv_msgv1 = -msgv1 iv_msgv2 = -msgv2 iv_msgv3 = -msgv3 iv_msgv4 = -msgv4 ). ENDIF. ENDLOOP. CALL METHOD ('CL_AFF_FILE_NAME_MAPPER')=>for_json RECEIVING result = lo_file_name_mapper. CALL METHOD lo_file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') EXPORTING object = RECEIVING result = lv_file_name. CALL METHOD lo_files_container->('IF_AFF_FILES_CONTAINER~GET_FILE') EXPORTING name = lv_file_name RECEIVING result = lo_object_json_file. " avoid to serialize empty content (object was never activated, exists inactive only). IF is_file_empty( lo_object_json_file ) = abap_true. MESSAGE s821(eu) WITH lv_name INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL METHOD lo_object_json_file->('IF_AFF_FILE~GET_CONTENT') RECEIVING result = lv_json_as_xstring. " Only remove ABAP language version if repository is set to ignore it IF ms_item-abap_language_version = zcl_abapgit_abap_language_vers=>c_no_abap_language_version. lv_json_as_xstring_wo_alv = remove_abap_language_version( lv_json_as_xstring ). mo_files->add_raw( iv_ext = 'json' iv_data = lv_json_as_xstring_wo_alv ). ELSE. mo_files->add_raw( iv_ext = 'json' iv_data = lv_json_as_xstring ). ENDIF. ls_additional_extensions = get_additional_extensions( ). LOOP AT ls_additional_extensions ASSIGNING . CALL METHOD -file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') EXPORTING object = RECEIVING result = lv_file_name. CALL METHOD lo_files_container->('IF_AFF_FILES_CONTAINER~GET_FILE') EXPORTING name = lv_file_name RECEIVING result = lo_object_file. CALL METHOD lo_object_file->('IF_AFF_FILE~GET_CONTENT') RECEIVING result = lv_file_as_xstring. mo_files->add_raw( iv_ext = -extension iv_data = lv_file_as_xstring ). ENDLOOP. CATCH cx_root INTO lx_exception. zcx_abapgit_exception=>raise_with_text( lx_exception ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_CHKV IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lr_data TYPE REF TO data, lo_chkv_db_api TYPE REF TO object, lv_name TYPE c LENGTH 180, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE OBJECT lo_chkv_db_api TYPE ('CL_CHKV_DB_API'). CREATE DATA lr_data TYPE ('CL_CHKV_DB_API=>TY_HEADER'). ASSIGN lr_data->* TO . lv_name = ms_item-obj_name. CALL METHOD lo_chkv_db_api->('GET_HEADER') EXPORTING object_key = lv_name version = 'I' RECEIVING header = . IF IS INITIAL. CALL METHOD lo_chkv_db_api->('GET_HEADER') EXPORTING object_key = lv_name version = 'A' RECEIVING header = . ENDIF. ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . rv_user = . CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_CHKO IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lr_data TYPE REF TO data, lo_chko_db_api TYPE REF TO object, lv_name TYPE c LENGTH 30, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE OBJECT lo_chko_db_api TYPE ('CL_CHKO_DB_API'). CREATE DATA lr_data TYPE ('CL_CHKO_DB_API=>TY_HEADER'). ASSIGN lr_data->* TO . lv_name = ms_item-obj_name. CALL METHOD lo_chko_db_api->('GET_HEADER') EXPORTING name = lv_name version = 'I' RECEIVING header = . IF IS INITIAL. CALL METHOD lo_chko_db_api->('GET_HEADER') EXPORTING name = lv_name version = 'A' RECEIVING header = . ENDIF. ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . rv_user = . CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_OBJECT_CHKC IMPLEMENTATION. METHOD zif_abapgit_object~changed_by. DATA: lr_data TYPE REF TO data, lo_chkc_db_api TYPE REF TO object, lv_name TYPE c LENGTH 30, lx_error TYPE REF TO cx_root. FIELD-SYMBOLS: TYPE any, TYPE any. TRY. CREATE OBJECT lo_chkc_db_api TYPE ('CL_CHKC_DB_API'). CREATE DATA lr_data TYPE ('CL_CHKC_DB_API=>TY_HEADER'). ASSIGN lr_data->* TO . lv_name = ms_item-obj_name. CALL METHOD lo_chkc_db_api->('GET_HEADER') EXPORTING name = lv_name version = 'I' RECEIVING header = . IF IS INITIAL. CALL METHOD lo_chkc_db_api->('GET_HEADER') EXPORTING name = lv_name version = 'A' RECEIVING header = . ENDIF. ASSIGN COMPONENT 'CHANGED_BY' OF STRUCTURE TO . rv_user = . CATCH cx_root INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. ENDMETHOD. ENDCLASS. CLASS kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh DEFINITION DEFERRED. *"* use this source file for the definition and implementation of *"* local helper classes, interface definitions and type *"* declarations * renamed: zcl_abapgit_json_path :: lcl_json_path CLASS kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh DEFINITION CREATE PUBLIC. PUBLIC SECTION. METHODS: serialize_rec IMPORTING io_reader TYPE REF TO if_sxml_reader it_path TYPE string_table CHANGING ct_json_paths TYPE string_table. CLASS-METHODS: deserialize IMPORTING it_json_path TYPE string_table RETURNING VALUE(rv_result) TYPE string RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. METHODS: is_array IMPORTING io_reader TYPE REF TO if_sxml_reader RETURNING VALUE(rv_result) TYPE abap_bool. METHODS: is_string_open IMPORTING io_reader TYPE REF TO if_sxml_reader RETURNING VALUE(rv_result) TYPE abap_bool. METHODS: is_object IMPORTING io_reader TYPE REF TO if_sxml_reader RETURNING VALUE(rv_result) TYPE abap_bool. METHODS: serialize_rec_array IMPORTING io_reader TYPE REF TO if_sxml_reader it_path TYPE string_table CHANGING ct_json_paths TYPE string_table. METHODS: get_json_path IMPORTING it_path TYPE string_table RETURNING VALUE(rv_result) TYPE string. CLASS-METHODS get_path_elements IMPORTING iv_path TYPE string RETURNING VALUE(rt_result) TYPE string_table RAISING zcx_abapgit_exception. CLASS-METHODS build_json IMPORTING it_path_elements TYPE string_table iv_value TYPE string CHANGING cv_json_string TYPE string. CLASS-METHODS path_contains_array IMPORTING iv_path TYPE string RETURNING VALUE(rv_result) TYPE abap_bool. CLASS-METHODS: to_json IMPORTING iv_json_path TYPE string RETURNING VALUE(ro_result) TYPE REF TO zcl_abapgit_ajson RAISING zcx_abapgit_ajson_error zcx_abapgit_exception. CLASS-METHODS: is_primitiv IMPORTING iv_string TYPE string RETURNING VALUE(rv_result) TYPE abap_bool. CLASS-METHODS: is_comment_or_empty_line IMPORTING iv_line TYPE string RETURNING VALUE(rv_result) TYPE abap_bool. ENDCLASS. CLASS kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh IMPLEMENTATION. METHOD to_json. DATA: lv_path TYPE string, lv_value TYPE string, lt_path_elements TYPE string_table, lv_json TYPE string. FIND REGEX `(.*)=(.*$)` IN iv_json_path SUBMATCHES lv_path lv_value. IF path_contains_array( lv_path ) = abap_true. lt_path_elements = get_path_elements( lv_path ). build_json( EXPORTING it_path_elements = lt_path_elements iv_value = lv_value CHANGING cv_json_string = lv_json ). ro_result = zcl_abapgit_ajson=>parse( lv_json ). ELSE. REPLACE FIRST OCCURRENCE OF '$.' IN lv_path WITH ''. REPLACE '.' IN lv_path WITH '/'. ro_result = zcl_abapgit_ajson=>create_empty( iv_keep_item_order = abap_true ). ro_result->set( iv_path = lv_path iv_val = lv_value ). ENDIF. ENDMETHOD. METHOD path_contains_array. DATA lv_array_pattern TYPE string VALUE `.*\[.*\].*`. rv_result = boolc( matches( val = iv_path regex = lv_array_pattern ) ). ENDMETHOD. METHOD build_json. DATA: lt_new_path_element TYPE string_table, lv_sub_match TYPE string, lv_key_name TYPE string, lv_key_value TYPE string, lv_name TYPE string, lv_first_elem TYPE string. lt_new_path_element = it_path_elements. IF lines( lt_new_path_element ) = 0. RETURN. ENDIF. READ TABLE lt_new_path_element INTO lv_first_elem INDEX 1. IF lv_first_elem = `$`. " is root level DELETE lt_new_path_element INDEX 1. build_json( EXPORTING it_path_elements = lt_new_path_element iv_value = iv_value CHANGING cv_json_string = cv_json_string ). ELSEIF is_primitiv( lv_first_elem ) = abap_true. cv_json_string = cv_json_string && | \{"{ lv_first_elem+1 }": |. DELETE lt_new_path_element INDEX 1. build_json( EXPORTING it_path_elements = lt_new_path_element iv_value = iv_value CHANGING cv_json_string = cv_json_string ). cv_json_string = cv_json_string && ` }`. ELSE. " is array FIND REGEX `\[(.*)\]` IN lv_first_elem SUBMATCHES lv_sub_match. FIND REGEX `(\w+)(?==='([^']*)')` IN lv_sub_match SUBMATCHES lv_key_name lv_key_value. READ TABLE lt_new_path_element INTO lv_name INDEX 2. DELETE lt_new_path_element INDEX 1. DELETE lt_new_path_element INDEX 1. IF lines( lt_new_path_element ) = 0. cv_json_string = cv_json_string && |[ \{ "{ lv_key_name }": "{ lv_key_value }", "{ lv_name+1 }": "{ iv_value }"\} ]|. ELSE. cv_json_string = cv_json_string && |[ \{ "{ lv_key_name }": "{ lv_key_value }", "{ lv_name+1 }":|. build_json( EXPORTING it_path_elements = lt_new_path_element iv_value = iv_value CHANGING cv_json_string = cv_json_string ). cv_json_string = cv_json_string && `} ] `. ENDIF. ENDIF. ENDMETHOD. METHOD is_primitiv. FIND REGEX `^.\w+` IN iv_string. " string start with . rv_result = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD get_path_elements. DATA: lv_pcre_pattern TYPE string, lt_match_result TYPE match_result_tab, lv_match TYPE match_result, lv_hit TYPE string, lx_find TYPE REF TO cx_root. lv_pcre_pattern = `(^\$)|(\.\w+)|(\[[^\]]*\])`. TRY. FIND ALL OCCURRENCES OF REGEX lv_pcre_pattern IN iv_path RESULTS lt_match_result. CATCH cx_sy_find_infinite_loop cx_sy_range_out_of_bounds cx_sy_invalid_regex cx_sy_regex_too_complex INTO lx_find. zcx_abapgit_exception=>raise_with_text( lx_find ). ENDTRY. LOOP AT lt_match_result INTO lv_match. lv_hit = substring( val = iv_path off = lv_match-offset len = lv_match-length ). APPEND lv_hit TO rt_result. ENDLOOP. ENDMETHOD. METHOD is_array. rv_result = boolc( io_reader->name = 'array' ). ENDMETHOD. METHOD is_string_open. rv_result = boolc( io_reader->name = 'str' AND io_reader->node_type = if_sxml_node=>co_nt_element_open ). ENDMETHOD. METHOD is_object. rv_result = boolc( io_reader->name = 'object' ). ENDMETHOD. METHOD serialize_rec. DATA: lt_new_path TYPE string_table, lv_key TYPE string. lt_new_path = it_path. IF io_reader->read_next_node( ) IS INITIAL. RETURN. ENDIF. IF is_string_open( io_reader ) = abap_true. APPEND io_reader->value TO lt_new_path. lv_key = get_json_path( lt_new_path ). io_reader->read_next_node( ). lv_key = |{ lv_key }={ io_reader->value }|. APPEND lv_key TO ct_json_paths. io_reader->read_next_node( ). DELETE lt_new_path INDEX lines( lt_new_path ). serialize_rec( EXPORTING io_reader = io_reader it_path = lt_new_path CHANGING ct_json_paths = ct_json_paths ). ELSEIF is_object( io_reader ) = abap_true AND io_reader->node_type = if_sxml_node=>co_nt_element_open. APPEND io_reader->value TO lt_new_path. serialize_rec( EXPORTING io_reader = io_reader it_path = lt_new_path CHANGING ct_json_paths = ct_json_paths ). ELSEIF is_array( io_reader ) = abap_true AND io_reader->node_type = if_sxml_node=>co_nt_element_open. APPEND io_reader->value TO lt_new_path. serialize_rec_array( EXPORTING io_reader = io_reader it_path = lt_new_path CHANGING ct_json_paths = ct_json_paths ). ELSEIF ( is_object( io_reader ) = abap_true OR is_array( io_reader ) = abap_true ) AND io_reader->node_type = if_sxml_node=>co_nt_element_close. DELETE lt_new_path INDEX lines( lt_new_path ). serialize_rec( EXPORTING io_reader = io_reader it_path = lt_new_path CHANGING ct_json_paths = ct_json_paths ). ENDIF. ENDMETHOD. METHOD serialize_rec_array. DATA: lt_new_path TYPE string_table, lv_json_path TYPE string, lv_array_key TYPE string. lt_new_path = it_path. IF io_reader->read_next_node( ) IS INITIAL. RETURN. ENDIF. IF is_string_open( io_reader ) = abap_true. APPEND io_reader->value TO lt_new_path. lv_json_path = get_json_path( lt_new_path ). io_reader->read_next_node( ). lv_json_path = |{ lv_json_path }={ io_reader->value }|. APPEND lv_json_path TO ct_json_paths. io_reader->read_next_node( ). serialize_rec( EXPORTING io_reader = io_reader it_path = lt_new_path CHANGING ct_json_paths = ct_json_paths ). ELSEIF is_object( io_reader ) = abap_true AND io_reader->node_type = if_sxml_node=>co_nt_element_open. io_reader->read_next_node( ). lv_array_key = io_reader->value. io_reader->read_next_node( ). lv_array_key = |[?(@.{ lv_array_key }=='{ io_reader->value }')]|. APPEND lv_array_key TO lt_new_path. io_reader->read_next_node( ). io_reader->read_next_node( ). APPEND io_reader->value TO lt_new_path. lv_json_path = get_json_path( lt_new_path ). io_reader->read_next_node( ). lv_json_path = |{ lv_json_path }={ io_reader->value }|. APPEND lv_json_path TO ct_json_paths. io_reader->read_next_node( ). DELETE lt_new_path INDEX lines( lt_new_path ). serialize_rec_array( EXPORTING io_reader = io_reader it_path = lt_new_path CHANGING ct_json_paths = ct_json_paths ). ELSEIF is_array( io_reader ) = abap_true AND io_reader->node_type = if_sxml_node=>co_nt_element_open. APPEND io_reader->value TO lt_new_path. serialize_rec_array( EXPORTING io_reader = io_reader it_path = lt_new_path CHANGING ct_json_paths = ct_json_paths ). ELSEIF ( is_object( io_reader ) = abap_true OR is_array( io_reader ) = abap_true ) AND io_reader->node_type = if_sxml_node=>co_nt_element_close. DELETE lt_new_path INDEX lines( lt_new_path ). serialize_rec_array( EXPORTING io_reader = io_reader it_path = lt_new_path CHANGING ct_json_paths = ct_json_paths ). ENDIF. ENDMETHOD. METHOD get_json_path. rv_result = concat_lines_of( table = it_path sep = `.` ). REPLACE ALL OCCURRENCES OF `.[` IN rv_result WITH `[`. ENDMETHOD. METHOD deserialize. DATA: lo_merged TYPE REF TO zif_abapgit_ajson, lv_json_path TYPE string, lo_deserialization_result TYPE REF TO zif_abapgit_ajson, lx_ajson TYPE REF TO zcx_abapgit_ajson_error. TRY. lo_merged = zcl_abapgit_ajson=>parse( `` ). CATCH zcx_abapgit_ajson_error INTO lx_ajson. zcx_abapgit_exception=>raise_with_text( lx_ajson ). ENDTRY. LOOP AT it_json_path INTO lv_json_path. IF is_comment_or_empty_line( lv_json_path ) = abap_true. CONTINUE. ENDIF. TRY. lo_deserialization_result = to_json( lv_json_path ). CATCH zcx_abapgit_ajson_error INTO lx_ajson. zcx_abapgit_exception=>raise_with_text( lx_ajson ). ENDTRY. TRY. lo_merged = zcl_abapgit_ajson_utilities=>new( )->merge( io_json_a = lo_merged io_json_b = lo_deserialization_result ). CATCH zcx_abapgit_ajson_error INTO lx_ajson. zcx_abapgit_exception=>raise_with_text( lx_ajson ). ENDTRY. ENDLOOP. TRY. rv_result = lo_merged->stringify( 2 ). CATCH zcx_abapgit_ajson_error INTO lx_ajson. zcx_abapgit_exception=>raise_with_text( lx_ajson ). ENDTRY. ENDMETHOD. METHOD is_comment_or_empty_line. IF iv_line IS INITIAL. rv_result = abap_true. RETURN. ENDIF. FIND REGEX `^!` IN iv_line. IF sy-subrc = 0. rv_result = abap_true. RETURN. ENDIF. FIND REGEX `^#` IN iv_line. IF sy-subrc = 0. rv_result = abap_true. RETURN. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_json_path IMPLEMENTATION. METHOD deserialize. rv_result = kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh=>deserialize( it_json_path ). ENDMETHOD. METHOD serialize. DATA: lo_json_path TYPE REF TO kHGwlkJTcmlzoyoRjDzlhrhxuWcvUh, lv_json_xstring TYPE xstring, lt_root_path TYPE string_table, lo_reader TYPE REF TO if_sxml_reader, lx_parse_error TYPE REF TO cx_sxml_parse_error. lv_json_xstring = zcl_abapgit_convert=>string_to_xstring_utf8( iv_json ). lo_reader = cl_sxml_string_reader=>create( input = lv_json_xstring ). TRY. IF lo_reader->read_next_node( ) IS INITIAL. RETURN. ENDIF. CATCH cx_sxml_parse_error INTO lx_parse_error. zcx_abapgit_exception=>raise_with_text( lx_parse_error ). ENDTRY. APPEND `$` TO lt_root_path. CREATE OBJECT lo_json_path. lo_json_path->serialize_rec( EXPORTING io_reader = lo_reader it_path = lt_root_path CHANGING ct_json_paths = rt_result ). ENDMETHOD. ENDCLASS. CLASS kHGwlbVxgSjWYXcuzxmbrHxeswZCbe DEFINITION DEFERRED. * renamed: zcl_abapgit_json_handler :: lcl_aff_filter CLASS kHGwlbVxgSjWYXcuzxmbrHxeswZCbe DEFINITION FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_filter. TYPES: BEGIN OF ty_path_value_pair, path TYPE string, value TYPE string, END OF ty_path_value_pair, ty_skip_paths TYPE STANDARD TABLE OF ty_path_value_pair WITH KEY path. METHODS constructor IMPORTING iv_skip_paths TYPE ty_skip_paths OPTIONAL RAISING zcx_abapgit_ajson_error. PRIVATE SECTION. DATA mt_skip_paths TYPE ty_skip_paths. ENDCLASS. CLASS kHGwlbVxgSjWYXcuzxmbrHxeswZCbe IMPLEMENTATION. METHOD zif_abapgit_ajson_filter~keep_node. DATA lv_path TYPE string. lv_path = is_node-path && is_node-name. READ TABLE mt_skip_paths WITH KEY path = lv_path value = is_node-value TRANSPORTING NO FIELDS. IF boolc( sy-subrc = 0 ) = abap_true AND iv_visit = zif_abapgit_ajson_filter=>visit_type-value. rv_keep = abap_false. RETURN. ELSE. READ TABLE mt_skip_paths WITH KEY path = lv_path TRANSPORTING NO FIELDS. IF boolc( sy-subrc = 0 ) = abap_true AND iv_visit = zif_abapgit_ajson_filter=>visit_type-value. rv_keep = abap_true. RETURN. ENDIF. ENDIF. IF is_node-type = 'bool' AND is_node-value = 'false' AND iv_visit = zif_abapgit_ajson_filter=>visit_type-value. rv_keep = abap_false. RETURN. ENDIF. " AFF: if INTEGER type is initial (0) then is will be skipped " However, if type is $required, it should be serialized. IF NOT ( ( iv_visit = zif_abapgit_ajson_filter=>visit_type-value AND is_node-value IS NOT INITIAL ) OR ( iv_visit <> zif_abapgit_ajson_filter=>visit_type-value AND is_node-children > 0 ) ). rv_keep = abap_false. RETURN. ENDIF. rv_keep = abap_true. ENDMETHOD. METHOD constructor. " extract annotations and build table for values to be skipped ( path/name | value ) DATA lo_abap_language_pair TYPE ty_path_value_pair. lo_abap_language_pair-path = `/header/abapLanguageVersion`. lo_abap_language_pair-value = 'standard'. APPEND lo_abap_language_pair TO mt_skip_paths. IF iv_skip_paths IS NOT INITIAL. APPEND LINES OF iv_skip_paths TO mt_skip_paths. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_json_handler IMPLEMENTATION. METHOD deserialize. DATA lo_ajson TYPE REF TO zif_abapgit_ajson. CLEAR ev_data. lo_ajson = zcl_abapgit_ajson=>parse( iv_content )->map( zcl_abapgit_ajson_mapping=>create_to_snake_case( ) ). map2abap_original_language( CHANGING co_ajson = lo_ajson ). set_defaults( EXPORTING it_defaults = iv_defaults CHANGING co_ajson = lo_ajson ). map2abap_abap_language_version( CHANGING co_ajson = lo_ajson ). map2abap_custom_enum( EXPORTING it_enum_mappings = iv_enum_mappings CHANGING co_ajson = lo_ajson ). lo_ajson->to_abap( IMPORTING ev_container = ev_data ). ENDMETHOD. METHOD map2abap_abap_language_version. DATA: lv_enum_abap TYPE string, lv_enum_json TYPE string. lv_enum_json = co_ajson->get_string( '/header/abap_language_version' ). IF lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-standard. lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard. ELSEIF lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development. lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-cloud_development. ELSEIF lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user. lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-key_user. ENDIF. co_ajson->set_string( iv_path = '/header/abap_language_version' iv_val = lv_enum_abap ). ENDMETHOD. METHOD map2abap_custom_enum. DATA: lv_enum_json TYPE string, ls_enum_mapping TYPE ty_enum_mapping, ls_mapping TYPE ty_json_abap_mapping. LOOP AT it_enum_mappings INTO ls_enum_mapping. lv_enum_json = co_ajson->get_string( ls_enum_mapping-path ). READ TABLE ls_enum_mapping-mappings WITH KEY json = lv_enum_json INTO ls_mapping. IF sy-subrc = 0. co_ajson->set_string( iv_path = ls_enum_mapping-path iv_val = ls_mapping-abap ). ENDIF. ENDLOOP. ENDMETHOD. METHOD map2abap_original_language. DATA: lv_bcp47_language TYPE string, lv_original_language TYPE sy-langu. lv_bcp47_language = co_ajson->get_string( '/header/original_language' ). lv_original_language = zcl_abapgit_convert=>language_bcp47_to_sap1( lv_bcp47_language ). co_ajson->set_string( iv_path = '/header/original_language' iv_val = lv_original_language ). ENDMETHOD. METHOD map2json_abap_language_version. DATA: lv_enum_abap TYPE string, lv_enum_json TYPE string. lv_enum_abap = co_ajson->get_string( '/header/abapLanguageVersion' ). IF lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard OR lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-standard. lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-standard. ELSEIF lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-cloud_development. lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development. ELSEIF lv_enum_abap = zif_abapgit_aff_types_v1=>co_abap_language_version-key_user. lv_enum_json = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user. ENDIF. co_ajson->set_string( iv_path = '/header/abapLanguageVersion' iv_val = lv_enum_json ). ENDMETHOD. METHOD map2json_custom_enum. DATA: lv_enum_abap TYPE string, ls_enum_mapping TYPE ty_enum_mapping, ls_mapping TYPE ty_json_abap_mapping. LOOP AT it_enum_mappings INTO ls_enum_mapping. lv_enum_abap = co_ajson->get_string( ls_enum_mapping-path ). READ TABLE ls_enum_mapping-mappings WITH KEY abap = lv_enum_abap INTO ls_mapping. IF sy-subrc = 0. co_ajson->set_string( iv_path = ls_enum_mapping-path iv_val = ls_mapping-json ). ENDIF. ENDLOOP. ENDMETHOD. METHOD map2json_original_language. DATA: lv_bcp47_language TYPE string, lv_original_language TYPE sy-langu. lv_original_language = co_ajson->get_string( '/header/originalLanguage' ). lv_bcp47_language = zcl_abapgit_convert=>language_sap1_to_bcp47( lv_original_language ). co_ajson->set_string( iv_path = '/header/originalLanguage' iv_val = lv_bcp47_language ). ENDMETHOD. METHOD serialize. DATA: lt_st_source TYPE abap_trans_srcbind_tab, lv_json TYPE string, lo_ajson TYPE REF TO zif_abapgit_ajson, lo_filter TYPE REF TO kHGwlbVxgSjWYXcuzxmbrHxeswZCbe. FIELD-SYMBOLS: LIKE LINE OF lt_st_source. APPEND INITIAL LINE TO lt_st_source ASSIGNING . GET REFERENCE OF iv_data INTO -value. lo_ajson = zcl_abapgit_ajson=>new( iv_keep_item_order = abap_true )->set( iv_path = '/' iv_val = iv_data )->map( zcl_abapgit_ajson_mapping=>create_to_camel_case( ) ). map2json_original_language( CHANGING co_ajson = lo_ajson ). map2json_abap_language_version( CHANGING co_ajson = lo_ajson ). map2json_custom_enum( EXPORTING it_enum_mappings = iv_enum_mappings CHANGING co_ajson = lo_ajson ). CREATE OBJECT lo_filter EXPORTING iv_skip_paths = iv_skip_paths. " files end with an empty line (EOF) lv_json = lo_ajson->clone( )->filter( lo_filter )->stringify( 2 ) && cl_abap_char_utilities=>newline. rv_result = zcl_abapgit_convert=>string_to_xstring_utf8( lv_json ). ENDMETHOD. METHOD set_defaults. DATA: lv_enum_json TYPE string, ls_default TYPE ty_path_value_pair. LOOP AT it_defaults INTO ls_default. lv_enum_json = co_ajson->get_string( ls_default-path ). IF lv_enum_json = ``. co_ajson->set_string( iv_path = ls_default-path iv_val = ls_default-value ). ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_aff_registry IMPLEMENTATION. METHOD constructor. mv_aff_enabled = zcl_abapgit_feature=>is_enabled( c_aff_feature ). ENDMETHOD. METHOD initialize_registry_table. register( 'CHKC' ). register( 'CHKO' ). register( 'CHKV' ). register( 'DRTY' ). register( 'DTEB' ). register( 'EVTB' ). register( 'EEEC' ). register( 'GSMP' ). register( iv_obj_type = 'INTF' iv_experimental = abap_true ). register( 'SMBC' ). register( 'NONT' ). register( 'RONT' ). register( 'UIPG' ). register( 'UIST' ). ENDMETHOD. METHOD register. DATA ls_registry_entry TYPE ty_registry_entry. ls_registry_entry-obj_type = iv_obj_type. ls_registry_entry-experimental = iv_experimental. INSERT ls_registry_entry INTO TABLE gt_registry. ENDMETHOD. METHOD zif_abapgit_aff_registry~is_supported_object_type. DATA ls_registry_entry TYPE ty_registry_entry. IF gt_registry IS INITIAL. initialize_registry_table( ). ENDIF. READ TABLE gt_registry WITH TABLE KEY obj_type = iv_obj_type INTO ls_registry_entry. IF sy-subrc = 0 AND ls_registry_entry-experimental = abap_false. rv_result = abap_true. ELSEIF sy-subrc = 0 AND mv_aff_enabled = abap_true. rv_result = abap_true. ELSE. rv_result = abap_false. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ajson_utilities IMPLEMENTATION. METHOD delete_empty_nodes. DATA ls_json_tree LIKE LINE OF io_json->mt_json_tree. DATA lv_done TYPE abap_bool. DO. lv_done = abap_true. IF iv_keep_empty_arrays = abap_false. LOOP AT io_json->mt_json_tree INTO ls_json_tree WHERE type = zif_abapgit_ajson_types=>node_type-array AND children = 0. io_json->delete( ls_json_tree-path && ls_json_tree-name ). ENDLOOP. IF sy-subrc = 0. lv_done = abap_false. ENDIF. ENDIF. LOOP AT io_json->mt_json_tree INTO ls_json_tree WHERE type = zif_abapgit_ajson_types=>node_type-object AND children = 0. io_json->delete( ls_json_tree-path && ls_json_tree-name ). ENDLOOP. IF sy-subrc = 0. lv_done = abap_false. ENDIF. IF lv_done = abap_true. EXIT. " nothing else to delete ENDIF. ENDDO. ENDMETHOD. METHOD diff. mo_json_a = normalize_input( iv_json = iv_json_a io_json = io_json_a ). mo_json_b = normalize_input( iv_json = iv_json_b io_json = io_json_b ). mo_insert = zcl_abapgit_ajson=>create_empty( ). mo_delete = zcl_abapgit_ajson=>create_empty( ). mo_change = zcl_abapgit_ajson=>create_empty( ). diff_a_b( '/' ). diff_b_a( '/' ). eo_insert ?= mo_insert. eo_delete ?= mo_delete. eo_change ?= mo_change. delete_empty_nodes( io_json = eo_insert iv_keep_empty_arrays = iv_keep_empty_arrays ). delete_empty_nodes( io_json = eo_delete iv_keep_empty_arrays = iv_keep_empty_arrays ). delete_empty_nodes( io_json = eo_change iv_keep_empty_arrays = iv_keep_empty_arrays ). ENDMETHOD. METHOD diff_a_b. DATA: lv_path_a TYPE string, lv_path_b TYPE string. FIELD-SYMBOLS: LIKE LINE OF mo_json_a->mt_json_tree, LIKE LINE OF mo_json_a->mt_json_tree. LOOP AT mo_json_a->mt_json_tree ASSIGNING WHERE path = iv_path. lv_path_a = -path && -name && '/'. READ TABLE mo_json_b->mt_json_tree ASSIGNING WITH TABLE KEY path = -path name = -name. IF sy-subrc = 0. lv_path_b = -path && -name && '/'. IF -type = -type. CASE -type. WHEN zif_abapgit_ajson_types=>node_type-array. mo_insert->touch_array( lv_path_a ). mo_change->touch_array( lv_path_a ). mo_delete->touch_array( lv_path_a ). diff_a_b( lv_path_a ). WHEN zif_abapgit_ajson_types=>node_type-object. diff_a_b( lv_path_a ). WHEN OTHERS. IF -value <> -value. " save as changed value mo_change->set( iv_path = lv_path_b iv_val = -value iv_node_type = -type ). ENDIF. ENDCASE. ELSE. " save changed type as delete + insert CASE -type. WHEN zif_abapgit_ajson_types=>node_type-array. mo_delete->touch_array( lv_path_a ). diff_a_b( lv_path_a ). WHEN zif_abapgit_ajson_types=>node_type-object. diff_a_b( lv_path_a ). WHEN OTHERS. mo_delete->set( iv_path = lv_path_a iv_val = -value iv_node_type = -type ). ENDCASE. CASE -type. WHEN zif_abapgit_ajson_types=>node_type-array. mo_insert->touch_array( lv_path_b ). diff_b_a( lv_path_b ). WHEN zif_abapgit_ajson_types=>node_type-object. diff_b_a( lv_path_b ). WHEN OTHERS. mo_insert->set( iv_path = lv_path_b iv_val = -value iv_node_type = -type ). ENDCASE. ENDIF. ELSE. " save as delete CASE -type. WHEN zif_abapgit_ajson_types=>node_type-array. mo_delete->touch_array( lv_path_a ). diff_a_b( lv_path_a ). WHEN zif_abapgit_ajson_types=>node_type-object. diff_a_b( lv_path_a ). WHEN OTHERS. mo_delete->set( iv_path = lv_path_a iv_val = -value iv_node_type = -type ). ENDCASE. ENDIF. ENDLOOP. ENDMETHOD. METHOD diff_b_a. DATA lv_path TYPE string. FIELD-SYMBOLS LIKE LINE OF mo_json_b->mt_json_tree. LOOP AT mo_json_b->mt_json_tree ASSIGNING WHERE path = iv_path. lv_path = -path && -name && '/'. CASE -type. WHEN zif_abapgit_ajson_types=>node_type-array. mo_insert->touch_array( lv_path ). diff_b_a( iv_path = lv_path iv_array = abap_true ). WHEN zif_abapgit_ajson_types=>node_type-object. diff_b_a( lv_path ). WHEN OTHERS. IF iv_array = abap_false. READ TABLE mo_json_a->mt_json_tree TRANSPORTING NO FIELDS WITH TABLE KEY path = -path name = -name. IF sy-subrc <> 0. " save as insert mo_insert->set( iv_path = lv_path iv_val = -value iv_node_type = -type ). ENDIF. ELSE. READ TABLE mo_insert->mt_json_tree TRANSPORTING NO FIELDS WITH KEY path = -path value = -value. IF sy-subrc <> 0. " save as new array value mo_insert->push( iv_path = iv_path iv_val = -value ). ENDIF. ENDIF. ENDCASE. ENDLOOP. ENDMETHOD. METHOD is_equal. DATA li_ins TYPE REF TO zif_abapgit_ajson. DATA li_del TYPE REF TO zif_abapgit_ajson. DATA li_mod TYPE REF TO zif_abapgit_ajson. diff( EXPORTING iv_json_a = iv_json_a iv_json_b = iv_json_b io_json_a = ii_json_a io_json_b = ii_json_b IMPORTING eo_insert = li_ins eo_delete = li_del eo_change = li_mod ). rv_yes = boolc( li_ins->is_empty( ) = abap_true AND li_del->is_empty( ) = abap_true AND li_mod->is_empty( ) = abap_true ). ENDMETHOD. METHOD merge. mo_json_a = normalize_input( iv_json = iv_json_a io_json = io_json_a ). mo_json_b = normalize_input( iv_json = iv_json_b io_json = io_json_b ). " Start with first JSON... mo_insert = mo_json_a. " ...and add all nodes from second JSON diff_b_a( '/' ). ro_json ?= mo_insert. delete_empty_nodes( io_json = ro_json iv_keep_empty_arrays = iv_keep_empty_arrays ). ENDMETHOD. METHOD new. CREATE OBJECT ro_instance. ENDMETHOD. METHOD normalize_input. IF boolc( iv_json IS INITIAL ) = boolc( io_json IS INITIAL ). zcx_abapgit_ajson_error=>raise( 'Either supply JSON string or instance, but not both' ). ENDIF. IF iv_json IS NOT INITIAL. ro_json = zcl_abapgit_ajson=>parse( iv_json ). ELSEIF io_json IS NOT INITIAL. ro_json = io_json. ELSE. zcx_abapgit_ajson_error=>raise( 'Supply either JSON string or instance' ). ENDIF. ENDMETHOD. METHOD sort. DATA lo_json TYPE REF TO zif_abapgit_ajson. lo_json = normalize_input( iv_json = iv_json io_json = io_json ). " Nodes are parsed into a sorted table, so no explicit sorting required rv_sorted = lo_json->stringify( 2 ). ENDMETHOD. ENDCLASS. CLASS kHGwlpuwVGRXmbkWZJMoTFhfUGDgXz IMPLEMENTATION. "DEPRECATED METHOD constructor. DATA ls_mapping_field LIKE LINE OF mt_mapping_fields. LOOP AT it_mapping_fields INTO ls_mapping_field. ls_mapping_field-abap = to_upper( ls_mapping_field-abap ). INSERT ls_mapping_field INTO TABLE mt_mapping_fields. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_abap. DATA ls_mapping_field LIKE LINE OF mt_mapping_fields. READ TABLE mt_mapping_fields INTO ls_mapping_field WITH KEY json COMPONENTS json = iv_name. IF sy-subrc = 0. rv_result = ls_mapping_field-abap. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_json. DATA lv_field TYPE string. DATA ls_mapping_field LIKE LINE OF mt_mapping_fields. lv_field = to_upper( iv_name ). READ TABLE mt_mapping_fields INTO ls_mapping_field WITH KEY abap COMPONENTS abap = lv_field. IF sy-subrc = 0. rv_result = ls_mapping_field-json. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~rename_node. ENDMETHOD. ENDCLASS. CLASS kHGwlpuwVGRXmbkWZJMocwrelrEIET IMPLEMENTATION. METHOD constructor. mt_rename_map = it_rename_map. mv_rename_by = iv_rename_by. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_abap. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_json. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~rename_node. DATA lv_full_path TYPE string. DATA lv_pair_found TYPE abap_bool. FIELD-SYMBOLS LIKE LINE OF mt_rename_map. CASE mv_rename_by. WHEN zcl_abapgit_ajson_mapping=>rename_by-attr_name. READ TABLE mt_rename_map ASSIGNING WITH TABLE KEY by_name COMPONENTS from = cv_name. lv_pair_found = boolc( sy-subrc = 0 ). WHEN zcl_abapgit_ajson_mapping=>rename_by-full_path. lv_full_path = is_node-path && cv_name. READ TABLE mt_rename_map ASSIGNING WITH TABLE KEY by_name COMPONENTS from = lv_full_path. lv_pair_found = boolc( sy-subrc = 0 ). WHEN zcl_abapgit_ajson_mapping=>rename_by-pattern. lv_full_path = is_node-path && cv_name. LOOP AT mt_rename_map ASSIGNING . IF lv_full_path CP -from. lv_pair_found = abap_true. EXIT. ENDIF. ENDLOOP. WHEN OTHERS. lv_pair_found = abap_false. " No rename ENDCASE. IF lv_pair_found = abap_true. cv_name = -to. ENDIF. ENDMETHOD. ENDCLASS. CLASS kHGwlpuwVGRXmbkWZJMoayhtkOTSGN IMPLEMENTATION. METHOD constructor. mi_mapping_fields = zcl_abapgit_ajson_mapping=>create_field_mapping( it_mapping_fields ). ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_abap. rv_result = mi_mapping_fields->to_abap( iv_path = iv_path iv_name = iv_name ). ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_json. rv_result = mi_mapping_fields->to_json( iv_path = iv_path iv_name = iv_name ). IF rv_result IS NOT INITIAL. " Mapping found RETURN. ENDIF. rv_result = to_upper( iv_name ). ENDMETHOD. METHOD zif_abapgit_ajson_mapping~rename_node. cv_name = to_upper( cv_name ). ENDMETHOD. ENDCLASS. CLASS kHGwlpuwVGRXmbkWZJMoIaLFAtEmIg IMPLEMENTATION. METHOD constructor. mi_mapping_fields = zcl_abapgit_ajson_mapping=>create_field_mapping( it_mapping_fields ). ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_abap. rv_result = mi_mapping_fields->to_abap( iv_path = iv_path iv_name = iv_name ). ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_json. rv_result = mi_mapping_fields->to_json( iv_path = iv_path iv_name = iv_name ). IF rv_result IS NOT INITIAL. " Mapping found RETURN. ENDIF. rv_result = to_lower( iv_name ). ENDMETHOD. METHOD zif_abapgit_ajson_mapping~rename_node. cv_name = to_lower( cv_name ). ENDMETHOD. ENDCLASS. CLASS kHGwlpuwVGRXmbkWZJMoYWDnXPYsQA IMPLEMENTATION. "DEPRECATED METHOD constructor. mi_mapping_fields = zcl_abapgit_ajson_mapping=>create_field_mapping( it_mapping_fields ). mv_first_json_upper = iv_first_json_upper. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_abap. rv_result = mi_mapping_fields->to_abap( iv_path = iv_path iv_name = iv_name ). IF rv_result IS NOT INITIAL. " Mapping found RETURN. ENDIF. rv_result = iv_name. REPLACE ALL OCCURRENCES OF REGEX `([a-z])([A-Z])` IN rv_result WITH `$1_$2`. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_json. TYPES ty_token TYPE c LENGTH 255. DATA lt_tokens TYPE STANDARD TABLE OF ty_token. DATA lv_from TYPE i. FIELD-SYMBOLS LIKE LINE OF lt_tokens. rv_result = mi_mapping_fields->to_json( iv_path = iv_path iv_name = iv_name ). IF rv_result IS NOT INITIAL. " Mapping found RETURN. ENDIF. rv_result = iv_name. REPLACE ALL OCCURRENCES OF `__` IN rv_result WITH `*`. TRANSLATE rv_result TO LOWER CASE. TRANSLATE rv_result USING `/_:_~_`. IF mv_first_json_upper = abap_true. lv_from = 1. ELSE. lv_from = 2. ENDIF. SPLIT rv_result AT `_` INTO TABLE lt_tokens. LOOP AT lt_tokens ASSIGNING FROM lv_from. TRANSLATE (1) TO UPPER CASE. ENDLOOP. CONCATENATE LINES OF lt_tokens INTO rv_result. REPLACE ALL OCCURRENCES OF `*` IN rv_result WITH `_`. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~rename_node. ENDMETHOD. ENDCLASS. CLASS kHGwlpuwVGRXmbkWZJMooAlevhaDMg IMPLEMENTATION. METHOD constructor. mt_queue = it_queue. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~rename_node. DATA ls_node LIKE is_node. DATA li_mapper LIKE LINE OF mt_queue. ls_node = is_node. LOOP AT mt_queue INTO li_mapper. li_mapper->rename_node( EXPORTING is_node = ls_node CHANGING cv_name = cv_name ). ls_node-name = cv_name. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_abap. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_json. ENDMETHOD. ENDCLASS. CLASS kHGwlpuwVGRXmbkWZJMorCLylKulMM IMPLEMENTATION. METHOD zif_abapgit_ajson_mapping~rename_node. REPLACE ALL OCCURRENCES OF REGEX `([a-z])([A-Z])` IN cv_name WITH `$1_$2`. cv_name = to_lower( cv_name ). ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_abap. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_json. ENDMETHOD. ENDCLASS. CLASS kHGwlpuwVGRXmbkWZJMoWRsLzEdjUi IMPLEMENTATION. METHOD constructor. mv_first_json_upper = iv_first_json_upper. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~rename_node. TYPES lty_token TYPE c LENGTH 255. CONSTANTS lc_forced_underscore_marker TYPE c LENGTH 1 VALUE cl_abap_char_utilities=>horizontal_tab. DATA lt_tokens TYPE STANDARD TABLE OF lty_token. DATA lv_from TYPE i. FIELD-SYMBOLS LIKE LINE OF lt_tokens. IF mv_first_json_upper = abap_true. lv_from = 1. ELSE. lv_from = 2. ENDIF. REPLACE ALL OCCURRENCES OF `__` IN cv_name WITH lc_forced_underscore_marker. " Force underscore SPLIT cv_name AT `_` INTO TABLE lt_tokens. DELETE lt_tokens WHERE table_line IS INITIAL. LOOP AT lt_tokens ASSIGNING FROM lv_from. TRANSLATE +0(1) TO UPPER CASE. ENDLOOP. CONCATENATE LINES OF lt_tokens INTO cv_name. REPLACE ALL OCCURRENCES OF lc_forced_underscore_marker IN cv_name WITH `_`. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_abap. ENDMETHOD. METHOD zif_abapgit_ajson_mapping~to_json. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ajson_mapping IMPLEMENTATION. METHOD create_camel_case. CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoYWDnXPYsQA EXPORTING it_mapping_fields = it_mapping_fields iv_first_json_upper = iv_first_json_upper. ENDMETHOD. METHOD create_compound_mapper. DATA lt_queue TYPE zif_abapgit_ajson_mapping=>ty_table_of. APPEND ii_mapper1 TO lt_queue. APPEND ii_mapper2 TO lt_queue. APPEND ii_mapper3 TO lt_queue. APPEND LINES OF it_more TO lt_queue. DELETE lt_queue WHERE table_line IS INITIAL. CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMooAlevhaDMg EXPORTING it_queue = lt_queue. ENDMETHOD. METHOD create_field_mapping. CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoTFhfUGDgXz EXPORTING it_mapping_fields = it_mapping_fields. ENDMETHOD. METHOD create_lower_case. CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoIaLFAtEmIg EXPORTING it_mapping_fields = it_mapping_fields. ENDMETHOD. METHOD create_rename. CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMocwrelrEIET EXPORTING it_rename_map = it_rename_map iv_rename_by = iv_rename_by. ENDMETHOD. METHOD create_to_camel_case. CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoWRsLzEdjUi EXPORTING iv_first_json_upper = iv_first_json_upper. ENDMETHOD. METHOD create_to_snake_case. CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMorCLylKulMM. ENDMETHOD. METHOD create_upper_case. CREATE OBJECT ri_mapping TYPE kHGwlpuwVGRXmbkWZJMoayhtkOTSGN EXPORTING it_mapping_fields = it_mapping_fields. ENDMETHOD. ENDCLASS. CLASS kHGwlqZELdDwrxoEPdVyarIhEaaLQd DEFINITION DEFERRED. CLASS kHGwlqZELdDwrxoEPdVyKlBZxFUUhA DEFINITION DEFERRED. CLASS kHGwlqZELdDwrxoEPdVyHkqTfrNjtW DEFINITION DEFERRED. ********************************************************************** * FILTER EMPTY VALUES ********************************************************************** * renamed: zcl_abapgit_ajson_filter_lib :: lcl_empty_filter CLASS kHGwlqZELdDwrxoEPdVyHkqTfrNjtW DEFINITION FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_filter. ENDCLASS. CLASS kHGwlqZELdDwrxoEPdVyHkqTfrNjtW IMPLEMENTATION. METHOD zif_abapgit_ajson_filter~keep_node. rv_keep = boolc( ( iv_visit = zif_abapgit_ajson_filter=>visit_type-value AND is_node-value IS NOT INITIAL ) OR ( iv_visit <> zif_abapgit_ajson_filter=>visit_type-value AND is_node-children > 0 ) ). " children = 0 on open for initially empty nodes and on close for filtered ones ENDMETHOD. ENDCLASS. ********************************************************************** * FILTER PREDEFINED PATHS ********************************************************************** * renamed: zcl_abapgit_ajson_filter_lib :: lcl_paths_filter CLASS kHGwlqZELdDwrxoEPdVyKlBZxFUUhA DEFINITION FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_filter. METHODS constructor IMPORTING it_skip_paths TYPE string_table OPTIONAL iv_skip_paths TYPE string OPTIONAL iv_pattern_search TYPE abap_bool RAISING zcx_abapgit_ajson_error. PRIVATE SECTION. DATA mt_skip_paths TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line. DATA mv_pattern_search TYPE abap_bool. ENDCLASS. CLASS kHGwlqZELdDwrxoEPdVyKlBZxFUUhA IMPLEMENTATION. METHOD zif_abapgit_ajson_filter~keep_node. DATA lv_full_path TYPE string. FIELD-SYMBOLS

    LIKE LINE OF mt_skip_paths. lv_full_path = is_node-path && is_node-name. IF mv_pattern_search = abap_true. rv_keep = abap_true. LOOP AT mt_skip_paths ASSIGNING

    . IF lv_full_path CP

    . rv_keep = abap_false. EXIT. ENDIF. ENDLOOP. ELSE. READ TABLE mt_skip_paths WITH KEY table_line = lv_full_path TRANSPORTING NO FIELDS. rv_keep = boolc( sy-subrc <> 0 ). ENDIF. ENDMETHOD. METHOD constructor. DATA lv_s TYPE string. DATA lt_tab TYPE string_table. FIELD-SYMBOLS TYPE string. IF boolc( iv_skip_paths IS INITIAL ) = boolc( it_skip_paths IS INITIAL ). " XOR zcx_abapgit_ajson_error=>raise( 'no filter path specified' ). ENDIF. LOOP AT it_skip_paths INTO lv_s. lv_s = to_lower( lv_s ). APPEND lv_s TO lt_tab. ENDLOOP. IF iv_skip_paths IS NOT INITIAL. SPLIT iv_skip_paths AT ',' INTO TABLE lt_tab. LOOP AT lt_tab ASSIGNING . IF IS INITIAL. DELETE lt_tab INDEX sy-tabix. CONTINUE. ENDIF. = condense( to_lower( ) ). ENDLOOP. ENDIF. SORT lt_tab BY table_line. DELETE ADJACENT DUPLICATES FROM lt_tab. mt_skip_paths = lt_tab. mv_pattern_search = iv_pattern_search. ENDMETHOD. ENDCLASS. ********************************************************************** * MULTI FILTER ********************************************************************** * renamed: zcl_abapgit_ajson_filter_lib :: lcl_and_filter CLASS kHGwlqZELdDwrxoEPdVyarIhEaaLQd DEFINITION FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_filter. METHODS constructor IMPORTING it_filters TYPE zif_abapgit_ajson_filter=>ty_filter_tab RAISING zcx_abapgit_ajson_error. PRIVATE SECTION. DATA mt_filters TYPE zif_abapgit_ajson_filter=>ty_filter_tab. ENDCLASS. CLASS kHGwlqZELdDwrxoEPdVyarIhEaaLQd IMPLEMENTATION. METHOD zif_abapgit_ajson_filter~keep_node. DATA li_filter LIKE LINE OF mt_filters. rv_keep = abap_true. LOOP AT mt_filters INTO li_filter. rv_keep = li_filter->keep_node( is_node = is_node iv_visit = iv_visit ). IF rv_keep = abap_false. RETURN. ENDIF. ENDLOOP. ENDMETHOD. METHOD constructor. DATA li_filter LIKE LINE OF it_filters. LOOP AT it_filters INTO li_filter WHERE table_line IS BOUND. APPEND li_filter TO mt_filters. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ajson_filter_lib IMPLEMENTATION. METHOD create_and_filter. CREATE OBJECT ri_filter TYPE kHGwlqZELdDwrxoEPdVyarIhEaaLQd EXPORTING it_filters = it_filters. ENDMETHOD. METHOD create_empty_filter. CREATE OBJECT ri_filter TYPE kHGwlqZELdDwrxoEPdVyHkqTfrNjtW. ENDMETHOD. METHOD create_path_filter. CREATE OBJECT ri_filter TYPE kHGwlqZELdDwrxoEPdVyKlBZxFUUhA EXPORTING iv_pattern_search = iv_pattern_search it_skip_paths = it_skip_paths iv_skip_paths = iv_skip_paths. ENDMETHOD. ENDCLASS. CLASS kHGwlMWhQrsNKkKXALnpucOpllUiAS DEFINITION DEFERRED. CLASS kHGwlMWhQrsNKkKXALnphFTcRDbOtm DEFINITION DEFERRED. CLASS kHGwlMWhQrsNKkKXALnplwblMIpVBS DEFINITION DEFERRED. INTERFACE iUFTsMWhQrsNKkKXALnptzVIYRIbuu DEFERRED. CLASS kHGwlMWhQrsNKkKXALnpeJqampzabz DEFINITION DEFERRED. CLASS kHGwlMWhQrsNKkKXALnpXxNdxsjJjI DEFINITION DEFERRED. CLASS kHGwlMWhQrsNKkKXALnpFgyFungUrS DEFINITION DEFERRED. CLASS kHGwlMWhQrsNKkKXALnpfipvepHQnc DEFINITION DEFERRED. CLASS kHGwlMWhQrsNKkKXALnpzByNvbZmNu DEFINITION DEFERRED. INTERFACE iUFTsMWhQrsNKkKXALnpdAMURRqLkF DEFERRED. ********************************************************************** * UTILS ********************************************************************** * renamed: zcl_abapgit_ajson :: lif_kind INTERFACE iUFTsMWhQrsNKkKXALnpdAMURRqLkF. TYPES ty_kind TYPE c LENGTH 1. CONSTANTS: any TYPE ty_kind VALUE cl_abap_typedescr=>typekind_any, date TYPE ty_kind VALUE cl_abap_typedescr=>typekind_date, time TYPE ty_kind VALUE cl_abap_typedescr=>typekind_time, packed TYPE ty_kind VALUE cl_abap_typedescr=>typekind_packed, table TYPE ty_kind VALUE cl_abap_typedescr=>typekind_table, struct_flat TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct1, struct_deep TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct2, data_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_dref, object_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_oref, enum TYPE ty_kind VALUE 'k'. " cl_abap_typedescr=>typekind_enum not in lower releases CONSTANTS: BEGIN OF numeric, int1 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_int1, int2 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_int2, int4 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_int, int8 TYPE ty_kind VALUE '8', " cl_abap_tabledescr=>typekind_int8 not in lower releases float TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_float, packed TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_packed, decfloat16 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_decfloat16, decfloat34 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_decfloat34, END OF numeric. CONSTANTS: BEGIN OF texts, char TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_char, numc TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_num, string TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_string, END OF texts. CONSTANTS: BEGIN OF binary, hex TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_hex, xstring TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_xstring, END OF binary. CONSTANTS: BEGIN OF deep_targets, table TYPE ty_kind VALUE cl_abap_typedescr=>typekind_table, struct_flat TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct1, struct_deep TYPE ty_kind VALUE cl_abap_typedescr=>typekind_struct2, data_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_dref, object_ref TYPE ty_kind VALUE cl_abap_typedescr=>typekind_oref, END OF deep_targets. ENDINTERFACE. * renamed: zcl_abapgit_ajson :: lcl_utils CLASS kHGwlMWhQrsNKkKXALnpzByNvbZmNu DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS normalize_path IMPORTING iv_path TYPE string RETURNING VALUE(rv_path) TYPE string. CLASS-METHODS split_path IMPORTING iv_path TYPE string RETURNING VALUE(rv_path_name) TYPE zif_abapgit_ajson_types=>ty_path_name. CLASS-METHODS validate_array_index IMPORTING iv_path TYPE string iv_index TYPE string RETURNING VALUE(rv_index) TYPE i RAISING zcx_abapgit_ajson_error. CLASS-METHODS string_to_xstring_utf8 IMPORTING iv_str TYPE string RETURNING VALUE(rv_xstr) TYPE xstring. ENDCLASS. CLASS kHGwlMWhQrsNKkKXALnpzByNvbZmNu IMPLEMENTATION. METHOD string_to_xstring_utf8. DATA lo_conv TYPE REF TO object. DATA lv_out_ce TYPE string. lv_out_ce = 'CL_ABAP_CONV_OUT_CE'. TRY. CALL METHOD ('CL_ABAP_CONV_CODEPAGE')=>create_out RECEIVING instance = lo_conv. CALL METHOD lo_conv->('IF_ABAP_CONV_OUT~CONVERT') EXPORTING source = iv_str RECEIVING result = rv_xstr. CATCH cx_sy_dyn_call_illegal_class. CALL METHOD (lv_out_ce)=>create EXPORTING encoding = 'UTF-8' RECEIVING conv = lo_conv. CALL METHOD lo_conv->('CONVERT') EXPORTING data = iv_str IMPORTING buffer = rv_xstr. ENDTRY. ENDMETHOD. METHOD validate_array_index. IF NOT iv_index CO '0123456789'. zcx_abapgit_ajson_error=>raise( |Cannot add non-numeric key [{ iv_index }] to array [{ iv_path }]| ). ENDIF. rv_index = iv_index. IF rv_index = 0. zcx_abapgit_ajson_error=>raise( |Cannot add zero key to array [{ iv_path }]| ). ENDIF. ENDMETHOD. METHOD normalize_path. rv_path = iv_path. IF strlen( rv_path ) = 0. rv_path = '/'. ENDIF. IF rv_path+0(1) <> '/'. rv_path = '/' && rv_path. ENDIF. IF substring( val = rv_path off = strlen( rv_path ) - 1 ) <> '/'. rv_path = rv_path && '/'. ENDIF. ENDMETHOD. METHOD split_path. DATA lv_offs TYPE i. DATA lv_len TYPE i. DATA lv_trim_slash TYPE i. lv_len = strlen( iv_path ). IF lv_len = 0 OR iv_path = '/'. RETURN. " empty path is the alias for root item = '' + '' ENDIF. IF substring( val = iv_path off = lv_len - 1 ) = '/'. lv_trim_slash = 1. " ignore last '/' ENDIF. lv_offs = find( val = reverse( iv_path ) sub = '/' off = lv_trim_slash ). IF lv_offs = -1. lv_offs = lv_len. " treat whole string as the 'name' part ENDIF. lv_offs = lv_len - lv_offs. rv_path_name-path = normalize_path( substring( val = iv_path len = lv_offs ) ). rv_path_name-name = substring( val = iv_path off = lv_offs len = lv_len - lv_offs - lv_trim_slash ). ENDMETHOD. ENDCLASS. ********************************************************************** * PARSER ********************************************************************** * renamed: zcl_abapgit_ajson :: lcl_json_parser CLASS kHGwlMWhQrsNKkKXALnpfipvepHQnc DEFINITION FINAL. PUBLIC SECTION. METHODS parse IMPORTING iv_json TYPE string iv_keep_item_order TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rt_json_tree) TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. PRIVATE SECTION. TYPES: ty_stack_tt TYPE STANDARD TABLE OF REF TO zif_abapgit_ajson_types=>ty_node. DATA mt_stack TYPE ty_stack_tt. DATA mv_stack_path TYPE string. DATA mv_keep_item_order TYPE abap_bool. METHODS raise IMPORTING iv_error TYPE string RAISING zcx_abapgit_ajson_error. METHODS _parse IMPORTING iv_json TYPE string RETURNING VALUE(rt_json_tree) TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error cx_dynamic_check. " cx_sxml_error is not released on Steampunk #153 METHODS _get_location IMPORTING iv_json TYPE string iv_offset TYPE i RETURNING VALUE(rv_location) TYPE string. ENDCLASS. CLASS kHGwlMWhQrsNKkKXALnpfipvepHQnc IMPLEMENTATION. METHOD parse. DATA lx_sxml_parse TYPE REF TO cx_sxml_parse_error. DATA lx_sxml TYPE REF TO cx_dynamic_check. DATA lv_location TYPE string. mv_keep_item_order = iv_keep_item_order. TRY. " TODO sane JSON check: " JSON can be true,false,null,(-)digits " or start from " or from { rt_json_tree = _parse( iv_json ). CATCH cx_sxml_parse_error INTO lx_sxml_parse. lv_location = _get_location( iv_json = iv_json iv_offset = lx_sxml_parse->xml_offset ). zcx_abapgit_ajson_error=>raise( iv_msg = |Json parsing error (SXML): { lx_sxml_parse->get_text( ) }| iv_location = lv_location ). CATCH cx_dynamic_check INTO lx_sxml. " cx_sxml_error zcx_abapgit_ajson_error=>raise( iv_msg = |Json parsing error (SXML): { lx_sxml->get_text( ) }| iv_location = '@PARSER' ). ENDTRY. ENDMETHOD. METHOD _get_location. DATA lv_json TYPE string. DATA lv_offset TYPE i. DATA lt_text TYPE TABLE OF string. DATA lv_text TYPE string. DATA lv_line TYPE i. DATA lv_pos TYPE i. lv_offset = iv_offset. IF lv_offset < 0. lv_offset = 0. ENDIF. IF lv_offset > strlen( iv_json ). lv_offset = strlen( iv_json ). ENDIF. lv_json = iv_json(lv_offset). REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_json WITH cl_abap_char_utilities=>newline. SPLIT lv_json AT cl_abap_char_utilities=>newline INTO TABLE lt_text. lv_line = lines( lt_text ). IF lv_line = 0. lv_line = 1. lv_pos = 1. ELSE. READ TABLE lt_text INDEX lv_line INTO lv_text. lv_pos = strlen( lv_text ) + 1. ENDIF. rv_location = |Line { lv_line }, Offset { lv_pos }|. ENDMETHOD. METHOD _parse. DATA lo_reader TYPE REF TO if_sxml_reader. DATA lr_stack_top LIKE LINE OF mt_stack. DATA lo_node TYPE REF TO if_sxml_node. FIELD-SYMBOLS LIKE LINE OF rt_json_tree. CLEAR mt_stack. CLEAR mv_stack_path. IF iv_json IS INITIAL. RETURN. ENDIF. lo_reader = cl_sxml_string_reader=>create( kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>string_to_xstring_utf8( iv_json ) ). " TODO: self protection, check non-empty, check starting from object ... DO. lo_node = lo_reader->read_next_node( ). IF lo_node IS NOT BOUND. EXIT. ENDIF. CASE lo_node->type. WHEN if_sxml_node=>co_nt_element_open. DATA lt_attributes TYPE if_sxml_attribute=>attributes. DATA lo_attr LIKE LINE OF lt_attributes. DATA lo_open TYPE REF TO if_sxml_open_element. lo_open ?= lo_node. APPEND INITIAL LINE TO rt_json_tree ASSIGNING . -type = lo_open->qname-name. READ TABLE mt_stack INDEX 1 INTO lr_stack_top. IF sy-subrc = 0. " Using string is faster than rebuilding path from stack -path = mv_stack_path. lr_stack_top->children = lr_stack_top->children + 1. IF lr_stack_top->type = `array`. " This is parser type not ajson type -name = |{ lr_stack_top->children }|. -index = lr_stack_top->children. ELSE. lt_attributes = lo_open->get_attributes( ). LOOP AT lt_attributes INTO lo_attr. IF lo_attr->qname-name = 'name' AND lo_attr->value_type = if_sxml_value=>co_vt_text. -name = lo_attr->get_value( ). ENDIF. ENDLOOP. IF mv_keep_item_order = abap_true. -order = lr_stack_top->children. ENDIF. ENDIF. IF -name IS INITIAL. raise( 'Node without name (maybe not JSON)' ). ENDIF. ENDIF. GET REFERENCE OF INTO lr_stack_top. INSERT lr_stack_top INTO mt_stack INDEX 1. " add path component mv_stack_path = mv_stack_path && -name && '/'. WHEN if_sxml_node=>co_nt_element_close. DATA lo_close TYPE REF TO if_sxml_close_element. lo_close ?= lo_node. READ TABLE mt_stack INDEX 1 INTO lr_stack_top. DELETE mt_stack INDEX 1. IF lo_close->qname-name <> lr_stack_top->type. raise( 'Unexpected closing node type' ). ENDIF. " remove last path component mv_stack_path = substring( val = mv_stack_path len = find( val = mv_stack_path sub = '/' occ = -2 ) + 1 ). WHEN if_sxml_node=>co_nt_value. DATA lo_value TYPE REF TO if_sxml_value_node. lo_value ?= lo_node. -value = lo_value->get_value( ). WHEN OTHERS. raise( 'Unexpected node type' ). ENDCASE. ENDDO. IF lines( mt_stack ) > 0. raise( 'Unexpected end of data' ). ENDIF. ENDMETHOD. METHOD raise. zcx_abapgit_ajson_error=>raise( iv_location = mv_stack_path iv_msg = |JSON PARSER: { iv_error } @ { mv_stack_path }| ). ENDMETHOD. ENDCLASS. ********************************************************************** * SERIALIZER ********************************************************************** * renamed: zcl_abapgit_ajson :: lcl_json_serializer CLASS kHGwlMWhQrsNKkKXALnpFgyFungUrS DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS stringify IMPORTING it_json_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts iv_indent TYPE i DEFAULT 0 iv_keep_item_order TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_json_string) TYPE string RAISING zcx_abapgit_ajson_error. CLASS-METHODS class_constructor. PRIVATE SECTION. CLASS-DATA gv_comma_with_lf TYPE string. DATA mt_json_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts. DATA mv_keep_item_order TYPE abap_bool. DATA mt_buffer TYPE string_table. DATA mv_indent_step TYPE i. DATA mv_level TYPE i. CLASS-METHODS escape_string IMPORTING iv_unescaped TYPE string RETURNING VALUE(rv_escaped) TYPE string. METHODS _stringify RETURNING VALUE(rv_json_string) TYPE string RAISING zcx_abapgit_ajson_error. METHODS stringify_node IMPORTING is_node TYPE zif_abapgit_ajson_types=>ty_node RAISING zcx_abapgit_ajson_error. METHODS stringify_set IMPORTING iv_parent_path TYPE string iv_array TYPE abap_bool RAISING zcx_abapgit_ajson_error. ENDCLASS. CLASS kHGwlMWhQrsNKkKXALnpFgyFungUrS IMPLEMENTATION. METHOD class_constructor. gv_comma_with_lf = ',' && cl_abap_char_utilities=>newline. ENDMETHOD. METHOD stringify. DATA lo TYPE REF TO kHGwlMWhQrsNKkKXALnpFgyFungUrS. CREATE OBJECT lo. lo->mt_json_tree = it_json_tree. lo->mv_indent_step = iv_indent. lo->mv_keep_item_order = iv_keep_item_order. rv_json_string = lo->_stringify( ). ENDMETHOD. METHOD _stringify. FIELD-SYMBOLS LIKE LINE OF mt_json_tree. READ TABLE mt_json_tree ASSIGNING WITH KEY path = '' name = ''. " Root IF sy-subrc <> 0. RETURN. ENDIF. stringify_node( ). rv_json_string = concat_lines_of( table = mt_buffer ). ENDMETHOD. METHOD stringify_node. DATA lv_item TYPE string. DATA lv_indent_prefix TYPE string. IF mv_indent_step > 0. lv_indent_prefix = repeat( val = ` ` occ = mv_indent_step * mv_level ). lv_item = lv_indent_prefix. ENDIF. IF is_node-name IS NOT INITIAL AND is_node-index IS INITIAL. " Not root, not array item IF mv_indent_step > 0. lv_item = lv_item && |"{ is_node-name }": |. ELSE. lv_item = |"{ is_node-name }":|. ENDIF. ENDIF. CASE is_node-type. WHEN zif_abapgit_ajson_types=>node_type-array. lv_item = lv_item && '['. WHEN zif_abapgit_ajson_types=>node_type-object. lv_item = lv_item && '{'. WHEN zif_abapgit_ajson_types=>node_type-string. lv_item = lv_item && |"{ escape_string( is_node-value ) }"|. WHEN zif_abapgit_ajson_types=>node_type-boolean OR zif_abapgit_ajson_types=>node_type-number. lv_item = lv_item && is_node-value. WHEN zif_abapgit_ajson_types=>node_type-null. lv_item = lv_item && 'null'. WHEN OTHERS. zcx_abapgit_ajson_error=>raise( iv_msg = |Unexpected type [{ is_node-type }]| iv_location = is_node-path && is_node-name ). ENDCASE. IF mv_indent_step > 0 AND ( is_node-type = zif_abapgit_ajson_types=>node_type-array OR is_node-type = zif_abapgit_ajson_types=>node_type-object ) AND is_node-children > 0. mv_level = mv_level + 1. lv_item = lv_item && cl_abap_char_utilities=>newline. ENDIF. APPEND lv_item TO mt_buffer. " finish complex item IF is_node-type = zif_abapgit_ajson_types=>node_type-array OR is_node-type = zif_abapgit_ajson_types=>node_type-object. DATA lv_children_path TYPE string. DATA lv_tail TYPE string. lv_children_path = is_node-path && is_node-name && '/'. " for root: path = '' and name = '', so result is '/' CASE is_node-type. WHEN zif_abapgit_ajson_types=>node_type-array. IF is_node-children > 0. stringify_set( iv_parent_path = lv_children_path iv_array = abap_true ). ENDIF. lv_tail = ']'. WHEN zif_abapgit_ajson_types=>node_type-object. IF is_node-children > 0. stringify_set( iv_parent_path = lv_children_path iv_array = abap_false ). ENDIF. lv_tail = '}'. ENDCASE. IF mv_indent_step > 0 AND is_node-children > 0. lv_tail = lv_indent_prefix && lv_tail. mv_level = mv_level - 1. ENDIF. APPEND lv_tail TO mt_buffer. ENDIF. ENDMETHOD. METHOD stringify_set. DATA lv_tab_key TYPE string. DATA lv_first_done TYPE abap_bool. FIELD-SYMBOLS LIKE LINE OF mt_json_tree. IF iv_array = abap_true. lv_tab_key = 'array_index'. " path + index ELSEIF mv_keep_item_order = abap_true. lv_tab_key = 'item_order'. " path + order ELSE. lv_tab_key = 'primary_key'. " path + name ENDIF. LOOP AT mt_json_tree ASSIGNING USING KEY (lv_tab_key) WHERE path = iv_parent_path. IF lv_first_done = abap_false. lv_first_done = abap_true. ELSEIF mv_indent_step > 0. APPEND gv_comma_with_lf TO mt_buffer. ELSE. APPEND ',' TO mt_buffer. ENDIF. stringify_node( ). ENDLOOP. IF mv_indent_step > 0 AND lv_first_done = abap_true. " only of items were in the list APPEND cl_abap_char_utilities=>newline TO mt_buffer. ENDIF. ENDMETHOD. METHOD escape_string. rv_escaped = iv_unescaped. IF rv_escaped CA |"\\\t\n\r|. " TODO consider performance ... " see also https://www.json.org/json-en.html rv_escaped = replace( val = rv_escaped sub = '\' with = '\\' occ = 0 ). rv_escaped = replace( val = rv_escaped sub = |\n| with = '\n' occ = 0 ). rv_escaped = replace( val = rv_escaped sub = |\r| with = '\r' occ = 0 ). rv_escaped = replace( val = rv_escaped sub = |\t| with = '\t' occ = 0 ). rv_escaped = replace( val = rv_escaped sub = '"' with = '\"' occ = 0 ). ENDIF. ENDMETHOD. ENDCLASS. ********************************************************************** * JSON_TO_ABAP ********************************************************************** * renamed: zcl_abapgit_ajson :: lcl_json_to_abap CLASS kHGwlMWhQrsNKkKXALnpXxNdxsjJjI DEFINITION FINAL. PUBLIC SECTION. METHODS constructor IMPORTING !iv_corresponding TYPE abap_bool DEFAULT abap_false !ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL. METHODS to_abap IMPORTING it_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_ts CHANGING c_container TYPE any RAISING zcx_abapgit_ajson_error. METHODS to_timestamp IMPORTING iv_value TYPE zif_abapgit_ajson_types=>ty_node-value RETURNING VALUE(rv_result) TYPE timestamp RAISING zcx_abapgit_ajson_error. METHODS to_date IMPORTING iv_value TYPE zif_abapgit_ajson_types=>ty_node-value RETURNING VALUE(rv_result) TYPE d RAISING zcx_abapgit_ajson_error. METHODS to_time IMPORTING iv_value TYPE zif_abapgit_ajson_types=>ty_node-value RETURNING VALUE(rv_result) TYPE t RAISING zcx_abapgit_ajson_error. PRIVATE SECTION. TYPES: BEGIN OF ty_type_cache, type_path TYPE string, target_field_name TYPE string, dd TYPE REF TO cl_abap_datadescr, type_kind LIKE iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>any, tab_item_buf TYPE REF TO data, END OF ty_type_cache. DATA mt_node_type_cache TYPE HASHED TABLE OF ty_type_cache WITH UNIQUE KEY type_path. DATA mr_nodes TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. DATA mi_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping. DATA mv_corresponding TYPE abap_bool. METHODS any_to_abap IMPORTING iv_path TYPE string is_parent_type TYPE ty_type_cache OPTIONAL i_container_ref TYPE REF TO data RAISING zcx_abapgit_ajson_error. METHODS value_to_abap IMPORTING is_node TYPE zif_abapgit_ajson_types=>ty_node is_node_type TYPE ty_type_cache i_container_ref TYPE REF TO data RAISING zcx_abapgit_ajson_error cx_sy_conversion_no_number. METHODS get_node_type IMPORTING is_node TYPE zif_abapgit_ajson_types=>ty_node OPTIONAL " Empty for root is_parent_type TYPE ty_type_cache OPTIONAL i_container_ref TYPE REF TO data OPTIONAL RETURNING VALUE(rs_node_type) TYPE ty_type_cache RAISING zcx_abapgit_ajson_error. ENDCLASS. CLASS kHGwlMWhQrsNKkKXALnpXxNdxsjJjI IMPLEMENTATION. METHOD constructor. mi_custom_mapping = ii_custom_mapping. mv_corresponding = iv_corresponding. ENDMETHOD. METHOD to_abap. DATA lr_ref TYPE REF TO data. CLEAR c_container. " what about data/obj refs ? CLEAR mt_node_type_cache. GET REFERENCE OF c_container INTO lr_ref. GET REFERENCE OF it_nodes INTO mr_nodes. get_node_type( i_container_ref = lr_ref ). " Pre-cache root node type any_to_abap( iv_path = '' i_container_ref = lr_ref ). ENDMETHOD. METHOD get_node_type. DATA lv_node_type_path TYPE string. DATA lo_sdescr TYPE REF TO cl_abap_structdescr. DATA lo_tdescr TYPE REF TO cl_abap_tabledescr. DATA lo_ddescr TYPE REF TO cl_abap_datadescr. " Calculate type path IF is_parent_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. lv_node_type_path = is_parent_type-type_path && '/-'. " table item type ELSEIF is_parent_type-type_kind IS NOT INITIAL. lv_node_type_path = is_parent_type-type_path && '/' && is_node-name. ENDIF. " For root node lv_node_type_path remains '' " Get or create cached READ TABLE mt_node_type_cache INTO rs_node_type WITH KEY type_path = lv_node_type_path. IF sy-subrc <> 0. rs_node_type-type_path = lv_node_type_path. IF mi_custom_mapping IS BOUND. rs_node_type-target_field_name = to_upper( mi_custom_mapping->to_abap( iv_path = is_node-path iv_name = is_node-name ) ). IF rs_node_type-target_field_name IS INITIAL. rs_node_type-target_field_name = to_upper( is_node-name ). ENDIF. ELSE. rs_node_type-target_field_name = to_upper( is_node-name ). ENDIF. CASE is_parent_type-type_kind. WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. lo_tdescr ?= is_parent_type-dd. rs_node_type-dd = lo_tdescr->get_table_line_type( ). WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_flat OR iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_deep. lo_sdescr ?= is_parent_type-dd. lo_sdescr->get_component_type( EXPORTING p_name = rs_node_type-target_field_name RECEIVING p_descr_ref = rs_node_type-dd EXCEPTIONS component_not_found = 4 ). IF sy-subrc <> 0. IF mv_corresponding = abap_false. zcx_abapgit_ajson_error=>raise( |Path not found| ). ELSE. CLEAR rs_node_type. RETURN. ENDIF. ENDIF. WHEN ''. " Root node rs_node_type-dd ?= cl_abap_typedescr=>describe_by_data_ref( i_container_ref ). WHEN OTHERS. zcx_abapgit_ajson_error=>raise( |Unexpected parent type| ). ENDCASE. rs_node_type-type_kind = rs_node_type-dd->type_kind. " for caching and cleaner uninitialized access IF rs_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. lo_tdescr ?= rs_node_type-dd. IF lo_tdescr->table_kind <> cl_abap_tabledescr=>tablekind_std. lo_ddescr = lo_tdescr->get_table_line_type( ). CREATE DATA rs_node_type-tab_item_buf TYPE HANDLE lo_ddescr. ENDIF. ENDIF. INSERT rs_node_type INTO TABLE mt_node_type_cache. ENDIF. ENDMETHOD. METHOD any_to_abap. DATA ls_node_type LIKE LINE OF mt_node_type_cache. DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. DATA lx_root TYPE REF TO cx_root. DATA lr_target_field TYPE REF TO data. FIELD-SYMBOLS TYPE zif_abapgit_ajson_types=>ty_node. FIELD-SYMBOLS TYPE STANDARD TABLE. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. " Assign container CASE is_parent_type-type_kind. WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. IF is_parent_type-tab_item_buf IS BOUND. " Indirect hint that table was sorted/hashed, see get_node_type. ASSIGN i_container_ref->* TO . ASSERT sy-subrc = 0. lr_target_field = is_parent_type-tab_item_buf. " For hashed/sorted table - same buffer for all children ASSIGN is_parent_type-tab_item_buf->* TO . ASSERT sy-subrc = 0. ELSE. ASSIGN i_container_ref->* TO . ASSERT sy-subrc = 0. ENDIF. WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_flat OR iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_deep. ASSIGN i_container_ref->* TO . ASSERT sy-subrc = 0. ENDCASE. TRY. " array_index because stringified index goes in wrong order [1, 10, 2 ...] LOOP AT mr_nodes->* ASSIGNING USING KEY array_index WHERE path = iv_path. " Get or create type cache record IF is_parent_type-type_kind <> iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table OR ls_node_type-type_kind IS INITIAL. " table records are the same, no need to refetch twice ls_node_type = get_node_type( is_node = is_parent_type = is_parent_type ). IF mv_corresponding = abap_true AND ls_node_type IS INITIAL. CONTINUE. ENDIF. ENDIF. " Validate node type IF ls_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>data_ref OR ls_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>object_ref. " TODO maybe in future zcx_abapgit_ajson_error=>raise( 'Cannot assign to ref' ). ENDIF. " Find target field reference CASE is_parent_type-type_kind. WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. IF NOT ls_node_type-target_field_name CO '0123456789'. " Does not affect anything actually but for integrity zcx_abapgit_ajson_error=>raise( 'Need index to access tables' ). ENDIF. IF is_parent_type-tab_item_buf IS NOT BOUND. " Indirect hint that table was srt/hsh, see get_node_type APPEND INITIAL LINE TO REFERENCE INTO lr_target_field. ASSERT sy-subrc = 0. ENDIF. WHEN iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_flat OR iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_deep. FIELD-SYMBOLS TYPE any. ASSIGN COMPONENT ls_node_type-target_field_name OF STRUCTURE TO . ASSERT sy-subrc = 0. GET REFERENCE OF INTO lr_target_field. WHEN ''. " Root node lr_target_field = i_container_ref. WHEN OTHERS. zcx_abapgit_ajson_error=>raise( 'Unexpected parent type' ). ENDCASE. " Process value assignment CASE -type. WHEN zif_abapgit_ajson_types=>node_type-object. IF ls_node_type-type_kind <> iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_flat AND ls_node_type-type_kind <> iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>struct_deep. zcx_abapgit_ajson_error=>raise( 'Expected structure' ). ENDIF. any_to_abap( iv_path = -path && -name && '/' is_parent_type = ls_node_type i_container_ref = lr_target_field ). WHEN zif_abapgit_ajson_types=>node_type-array. IF NOT ls_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>table. zcx_abapgit_ajson_error=>raise( 'Expected table' ). ENDIF. any_to_abap( iv_path = -path && -name && '/' is_parent_type = ls_node_type i_container_ref = lr_target_field ). WHEN OTHERS. value_to_abap( is_node = is_node_type = ls_node_type i_container_ref = lr_target_field ). ENDCASE. IF is_parent_type-tab_item_buf IS BOUND. " Indirect hint that table was sorted/hashed, see get_node_type. TRY. INSERT INTO TABLE . IF sy-subrc <> 0. zcx_abapgit_ajson_error=>raise( 'Duplicate insertion' ). ENDIF. CATCH cx_sy_itab_duplicate_key. zcx_abapgit_ajson_error=>raise( 'Duplicate insertion' ). ENDTRY. ENDIF. ENDLOOP. CATCH zcx_abapgit_ajson_error INTO lx_ajson. IF lx_ajson->location IS INITIAL. lx_ajson->set_location( -path && -name ). ENDIF. RAISE EXCEPTION lx_ajson. CATCH cx_sy_conversion_no_number. zcx_abapgit_ajson_error=>raise( iv_msg = 'Source is not a number' iv_location = -path && -name ). CATCH cx_root INTO lx_root. zcx_abapgit_ajson_error=>raise( iv_msg = lx_root->get_text( ) iv_location = -path && -name ). ENDTRY. ENDMETHOD. METHOD value_to_abap. FIELD-SYMBOLS TYPE any. IF is_node_type-type_kind CA iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>deep_targets. zcx_abapgit_ajson_error=>raise( |Unsupported target for value [{ is_node_type-type_kind }]| ). ENDIF. ASSIGN i_container_ref->* TO . ASSERT sy-subrc = 0. CASE is_node-type. WHEN zif_abapgit_ajson_types=>node_type-null. " Do nothing WHEN zif_abapgit_ajson_types=>node_type-boolean. " TODO: check type ? = boolc( is_node-value = 'true' ). WHEN zif_abapgit_ajson_types=>node_type-number. " TODO: check type ? = is_node-value. WHEN zif_abapgit_ajson_types=>node_type-string. " TODO: check type ? IF is_node-value IS NOT INITIAL. IF is_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>date. = to_date( is_node-value ). ELSEIF is_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>time. = to_time( is_node-value ). ELSEIF is_node_type-dd->absolute_name = '\TYPE=TIMESTAMP' OR is_node_type-dd->absolute_name = '\TYPE=TIMESTAMPL'. = to_timestamp( is_node-value ). ELSEIF is_node_type-type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>packed. " Number as a string, but not a timestamp = is_node-value. ELSE. = is_node-value. ENDIF. ELSE. = is_node-value. ENDIF. WHEN OTHERS. zcx_abapgit_ajson_error=>raise( |Unexpected JSON type [{ is_node-type }]| ). ENDCASE. ENDMETHOD. METHOD to_date. DATA lv_y TYPE c LENGTH 4. DATA lv_m TYPE c LENGTH 2. DATA lv_d TYPE c LENGTH 2. FIND FIRST OCCURRENCE OF REGEX '^(\d{4})-(\d{2})-(\d{2})(T|$)' IN iv_value SUBMATCHES lv_y lv_m lv_d. IF sy-subrc <> 0. zcx_abapgit_ajson_error=>raise( 'Unexpected date format' ). ENDIF. CONCATENATE lv_y lv_m lv_d INTO rv_result. ENDMETHOD. METHOD to_timestamp. CONSTANTS lc_utc TYPE c LENGTH 6 VALUE 'UTC'. CONSTANTS lc_regex_ts_with_hour TYPE string VALUE `^(\d{4})-(\d{2})-(\d{2})(T)(\d{2}):(\d{2}):(\d{2})(\+)(\d{2}):(\d{2})`. CONSTANTS lc_regex_ts_utc TYPE string VALUE `^(\d{4})-(\d{2})-(\d{2})(T)(\d{2}):(\d{2}):(\d{2})(Z|$)`. DATA: BEGIN OF ls_timestamp, year TYPE c LENGTH 4, month TYPE c LENGTH 2, day TYPE c LENGTH 2, t TYPE c LENGTH 1, hour TYPE c LENGTH 2, minute TYPE c LENGTH 2, second TYPE c LENGTH 2, local_sign TYPE c LENGTH 1, local_hour TYPE c LENGTH 2, local_minute TYPE c LENGTH 2, END OF ls_timestamp. DATA lv_date TYPE d. DATA lv_time TYPE t. DATA lv_seconds_conv TYPE i. DATA lv_timestamp TYPE timestampl. FIND FIRST OCCURRENCE OF REGEX lc_regex_ts_with_hour IN iv_value SUBMATCHES ls_timestamp-year ls_timestamp-month ls_timestamp-day ls_timestamp-t ls_timestamp-hour ls_timestamp-minute ls_timestamp-second ls_timestamp-local_sign ls_timestamp-local_hour ls_timestamp-local_minute. IF sy-subrc = 0. lv_seconds_conv = ( ls_timestamp-local_hour * 3600 ) + ( ls_timestamp-local_minute * 60 ). ELSE. FIND FIRST OCCURRENCE OF REGEX lc_regex_ts_utc IN iv_value SUBMATCHES ls_timestamp-year ls_timestamp-month ls_timestamp-day ls_timestamp-t ls_timestamp-hour ls_timestamp-minute ls_timestamp-second. IF sy-subrc <> 0. zcx_abapgit_ajson_error=>raise( 'Unexpected timestamp format' ). ENDIF. ENDIF. CONCATENATE ls_timestamp-year ls_timestamp-month ls_timestamp-day INTO lv_date. CONCATENATE ls_timestamp-hour ls_timestamp-minute ls_timestamp-second INTO lv_time. CONVERT DATE lv_date TIME lv_time INTO TIME STAMP lv_timestamp TIME ZONE lc_utc. TRY. CASE ls_timestamp-local_sign. WHEN '-'. lv_timestamp = cl_abap_tstmp=>add( tstmp = lv_timestamp secs = lv_seconds_conv ). WHEN '+'. lv_timestamp = cl_abap_tstmp=>subtractsecs( tstmp = lv_timestamp secs = lv_seconds_conv ). ENDCASE. CATCH cx_parameter_invalid_range cx_parameter_invalid_type. zcx_abapgit_ajson_error=>raise( 'Unexpected error calculating timestamp' ). ENDTRY. IF lv_timestamp IS NOT INITIAL. cl_abap_tstmp=>move( EXPORTING tstmp_src = lv_timestamp IMPORTING tstmp_tgt = rv_result ). ENDIF. ENDMETHOD. METHOD to_time. DATA lv_h TYPE c LENGTH 2. DATA lv_m TYPE c LENGTH 2. DATA lv_s TYPE c LENGTH 2. FIND FIRST OCCURRENCE OF REGEX '^(\d{2}):(\d{2}):(\d{2})(T|$)' IN iv_value SUBMATCHES lv_h lv_m lv_s. IF sy-subrc <> 0. zcx_abapgit_ajson_error=>raise( 'Unexpected time format' ). ENDIF. CONCATENATE lv_h lv_m lv_s INTO rv_result. ENDMETHOD. ENDCLASS. ********************************************************************** * ABAP_TO_JSON ********************************************************************** * renamed: zcl_abapgit_ajson :: lcl_abap_to_json CLASS kHGwlMWhQrsNKkKXALnpeJqampzabz DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS convert IMPORTING iv_data TYPE any is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name OPTIONAL iv_array_index TYPE i DEFAULT 0 ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL is_opts TYPE zif_abapgit_ajson=>ty_opts OPTIONAL iv_item_order TYPE i DEFAULT 0 RETURNING VALUE(rt_nodes) TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. CLASS-METHODS insert_with_type IMPORTING iv_data TYPE any iv_type TYPE zif_abapgit_ajson_types=>ty_node_type is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name OPTIONAL iv_array_index TYPE i DEFAULT 0 ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL is_opts TYPE zif_abapgit_ajson=>ty_opts OPTIONAL iv_item_order TYPE i DEFAULT 0 RETURNING VALUE(rt_nodes) TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. CLASS-METHODS format_date IMPORTING iv_date TYPE d RETURNING VALUE(rv_str) TYPE string. CLASS-METHODS format_time IMPORTING iv_time TYPE t RETURNING VALUE(rv_str) TYPE string. CLASS-METHODS format_timestamp IMPORTING iv_ts TYPE timestamp RETURNING VALUE(rv_str) TYPE string. CLASS-METHODS class_constructor. PRIVATE SECTION. CLASS-DATA gv_ajson_absolute_type_name TYPE string. DATA mi_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping. DATA mv_keep_item_order TYPE abap_bool. DATA mv_format_datetime TYPE abap_bool. METHODS convert_any IMPORTING iv_data TYPE any io_type TYPE REF TO cl_abap_typedescr is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name iv_index TYPE i DEFAULT 0 iv_item_order TYPE i DEFAULT 0 CHANGING ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. METHODS convert_ajson IMPORTING io_json TYPE REF TO zif_abapgit_ajson is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name iv_index TYPE i DEFAULT 0 iv_item_order TYPE i DEFAULT 0 CHANGING ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. METHODS convert_value IMPORTING iv_data TYPE any io_type TYPE REF TO cl_abap_typedescr is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name iv_index TYPE i DEFAULT 0 iv_item_order TYPE i DEFAULT 0 CHANGING ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. METHODS convert_ref IMPORTING iv_data TYPE any is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name iv_index TYPE i DEFAULT 0 iv_item_order TYPE i DEFAULT 0 CHANGING ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. METHODS convert_struc IMPORTING iv_data TYPE any io_type TYPE REF TO cl_abap_typedescr is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name iv_index TYPE i DEFAULT 0 iv_item_order TYPE i DEFAULT 0 CHANGING ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. METHODS convert_table IMPORTING iv_data TYPE any io_type TYPE REF TO cl_abap_typedescr is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name iv_index TYPE i DEFAULT 0 iv_item_order TYPE i DEFAULT 0 CHANGING ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. METHODS insert_value_with_type IMPORTING iv_data TYPE any iv_type TYPE zif_abapgit_ajson_types=>ty_node_type io_type TYPE REF TO cl_abap_typedescr is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name iv_index TYPE i DEFAULT 0 iv_item_order TYPE i DEFAULT 0 CHANGING ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. ENDCLASS. CLASS kHGwlMWhQrsNKkKXALnpeJqampzabz IMPLEMENTATION. METHOD class_constructor. DATA lo_dummy TYPE REF TO zcl_abapgit_ajson. DATA lo_type TYPE REF TO cl_abap_refdescr. lo_type ?= cl_abap_typedescr=>describe_by_data( lo_dummy ). gv_ajson_absolute_type_name = lo_type->get_referenced_type( )->absolute_name. ENDMETHOD. METHOD convert. DATA lo_type TYPE REF TO cl_abap_typedescr. DATA lo_converter TYPE REF TO kHGwlMWhQrsNKkKXALnpeJqampzabz. lo_type = cl_abap_typedescr=>describe_by_data( iv_data ). CREATE OBJECT lo_converter. lo_converter->mi_custom_mapping = ii_custom_mapping. lo_converter->mv_keep_item_order = is_opts-keep_item_order. lo_converter->mv_format_datetime = is_opts-format_datetime. lo_converter->convert_any( EXPORTING iv_data = iv_data io_type = lo_type is_prefix = is_prefix iv_index = iv_array_index iv_item_order = iv_item_order CHANGING ct_nodes = rt_nodes ). ENDMETHOD. METHOD convert_any. CASE io_type->kind. WHEN cl_abap_typedescr=>kind_elem. convert_value( EXPORTING iv_data = iv_data io_type = io_type is_prefix = is_prefix iv_index = iv_index iv_item_order = iv_item_order CHANGING ct_nodes = ct_nodes ). WHEN cl_abap_typedescr=>kind_struct. convert_struc( EXPORTING iv_data = iv_data io_type = io_type is_prefix = is_prefix iv_index = iv_index iv_item_order = iv_item_order CHANGING ct_nodes = ct_nodes ). WHEN cl_abap_typedescr=>kind_table. convert_table( EXPORTING iv_data = iv_data io_type = io_type is_prefix = is_prefix iv_index = iv_index iv_item_order = iv_item_order CHANGING ct_nodes = ct_nodes ). WHEN OTHERS. IF io_type->type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>data_ref OR iv_data IS INITIAL. " Convert data references and initial references to other types (like ref to class or interface) " Initial references will result in "null" convert_ref( EXPORTING iv_data = iv_data is_prefix = is_prefix iv_index = iv_index iv_item_order = iv_item_order CHANGING ct_nodes = ct_nodes ). ELSEIF io_type->type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>object_ref AND cl_abap_typedescr=>describe_by_object_ref( iv_data )->absolute_name = gv_ajson_absolute_type_name. convert_ajson( EXPORTING io_json = iv_data is_prefix = is_prefix iv_index = iv_index iv_item_order = iv_item_order CHANGING ct_nodes = ct_nodes ). ELSE. zcx_abapgit_ajson_error=>raise( |Unsupported type [{ io_type->type_kind }] @{ is_prefix-path && is_prefix-name }| ). ENDIF. ENDCASE. ENDMETHOD. METHOD convert_ajson. FIELD-SYMBOLS LIKE LINE OF ct_nodes. FIELD-SYMBOLS LIKE LINE OF ct_nodes. IF io_json IS NOT BOUND. RETURN. ENDIF. LOOP AT io_json->mt_json_tree ASSIGNING . APPEND TO ct_nodes ASSIGNING . IF -path IS INITIAL AND -name IS INITIAL. " root node -path = is_prefix-path. -name = is_prefix-name. -index = iv_index. -order = iv_item_order. ELSE. -path = is_prefix-path && is_prefix-name && -path. ENDIF. ENDLOOP. ENDMETHOD. METHOD format_date. IF iv_date IS NOT INITIAL. rv_str = iv_date+0(4) && '-' && iv_date+4(2) && '-' && iv_date+6(2). ENDIF. ENDMETHOD. METHOD format_time. IF iv_time IS NOT INITIAL. rv_str = iv_time+0(2) && ':' && iv_time+2(2) && ':' && iv_time+4(2). ENDIF. ENDMETHOD. METHOD format_timestamp. CONSTANTS lc_utc TYPE c LENGTH 6 VALUE 'UTC'. DATA lv_date TYPE d. DATA lv_time TYPE t. CONVERT TIME STAMP iv_ts TIME ZONE lc_utc INTO DATE lv_date TIME lv_time. rv_str = lv_date+0(4) && '-' && lv_date+4(2) && '-' && lv_date+6(2) && 'T' && lv_time+0(2) && ':' && lv_time+2(2) && ':' && lv_time+4(2) && 'Z'. ENDMETHOD. METHOD convert_value. DATA ls_node LIKE LINE OF ct_nodes. ls_node-path = is_prefix-path. ls_node-name = is_prefix-name. ls_node-index = iv_index. ls_node-order = iv_item_order. IF ls_node-name IS INITIAL. ls_node-name = is_prefix-name. ENDIF. IF io_type->absolute_name = '\TYPE-POOL=ABAP\TYPE=ABAP_BOOL' OR io_type->absolute_name = '\TYPE=ABAP_BOOLEAN' OR io_type->absolute_name = '\TYPE=XSDBOOLEAN' OR io_type->absolute_name = '\TYPE=FLAG' OR io_type->absolute_name = '\TYPE=XFELD'. ls_node-type = zif_abapgit_ajson_types=>node_type-boolean. IF iv_data IS NOT INITIAL. ls_node-value = 'true'. ELSE. ls_node-value = 'false'. ENDIF. ELSEIF io_type->absolute_name = '\TYPE=TIMESTAMP'. IF mv_format_datetime = abap_true. ls_node-type = zif_abapgit_ajson_types=>node_type-string. ls_node-value = format_timestamp( iv_data ). ELSE. ls_node-type = zif_abapgit_ajson_types=>node_type-number. ls_node-value = |{ iv_data }|. ENDIF. ELSEIF io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>texts OR io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>binary OR io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>enum. ls_node-type = zif_abapgit_ajson_types=>node_type-string. ls_node-value = |{ iv_data }|. ELSEIF io_type->type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>date. ls_node-type = zif_abapgit_ajson_types=>node_type-string. IF mv_format_datetime = abap_true. ls_node-value = format_date( iv_data ). ELSE. ls_node-value = |{ iv_data }|. ENDIF. ELSEIF io_type->type_kind = iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>time. ls_node-type = zif_abapgit_ajson_types=>node_type-string. IF mv_format_datetime = abap_true. ls_node-value = format_time( iv_data ). ELSE. ls_node-value = |{ iv_data }|. ENDIF. ELSEIF io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>numeric. ls_node-type = zif_abapgit_ajson_types=>node_type-number. ls_node-value = |{ iv_data }|. ELSE. zcx_abapgit_ajson_error=>raise( |Unexpected elementary type [{ io_type->type_kind }] @{ is_prefix-path && is_prefix-name }| ). ENDIF. APPEND ls_node TO ct_nodes. ENDMETHOD. METHOD convert_ref. DATA ls_node LIKE LINE OF ct_nodes. ls_node-path = is_prefix-path. ls_node-name = is_prefix-name. ls_node-index = iv_index. ls_node-order = iv_item_order. IF mi_custom_mapping IS BOUND. ls_node-name = mi_custom_mapping->to_json( iv_path = is_prefix-path iv_name = is_prefix-name ). ENDIF. IF ls_node-name IS INITIAL. ls_node-name = is_prefix-name. ENDIF. IF iv_data IS INITIAL. ls_node-type = zif_abapgit_ajson_types=>node_type-null. ls_node-value = 'null'. ELSE. " TODO support data references zcx_abapgit_ajson_error=>raise( |Unexpected reference @{ is_prefix-path && is_prefix-name }| ). ENDIF. APPEND ls_node TO ct_nodes. ENDMETHOD. METHOD convert_struc. DATA lo_struc TYPE REF TO cl_abap_structdescr. DATA lt_comps TYPE cl_abap_structdescr=>included_view. DATA ls_next_prefix LIKE is_prefix. DATA lv_mapping_prefix_name LIKE is_prefix-name. DATA lv_item_order TYPE i. DATA ls_root LIKE LINE OF ct_nodes. FIELD-SYMBOLS LIKE ls_root. FIELD-SYMBOLS LIKE LINE OF lt_comps. FIELD-SYMBOLS TYPE any. " Object root ls_root-path = is_prefix-path. ls_root-name = is_prefix-name. ls_root-type = zif_abapgit_ajson_types=>node_type-object. ls_root-index = iv_index. IF mi_custom_mapping IS BOUND. ls_root-name = mi_custom_mapping->to_json( iv_path = is_prefix-path iv_name = is_prefix-name ). ENDIF. IF ls_root-name IS INITIAL. ls_root-name = is_prefix-name. ENDIF. ls_root-order = iv_item_order. APPEND ls_root TO ct_nodes ASSIGNING . " Object attributes lo_struc ?= io_type. lt_comps = lo_struc->get_included_view( ). " replaced call to get_components() with get_included_view() to avoid problems with suffixes in includes. " get_components is potentially much slower than lo_struc->components " but ! we still need it to identify booleans " and rtti seems to cache type descriptions really well (https://github.com/sbcgua/benchmarks.git) " the structures will be repeated in real life ls_next_prefix-path = is_prefix-path && -name && '/'. LOOP AT lt_comps ASSIGNING . CLEAR lv_mapping_prefix_name. -children = -children + 1. ls_next_prefix-name = to_lower( -name ). ASSIGN COMPONENT -name OF STRUCTURE iv_data TO . ASSERT sy-subrc = 0. IF mi_custom_mapping IS BOUND AND -type->kind = cl_abap_typedescr=>kind_elem. lv_mapping_prefix_name = mi_custom_mapping->to_json( iv_path = ls_next_prefix-path iv_name = ls_next_prefix-name ). ENDIF. IF lv_mapping_prefix_name IS NOT INITIAL. ls_next_prefix-name = lv_mapping_prefix_name. ENDIF. IF mv_keep_item_order = abap_true. lv_item_order = -children. ENDIF. convert_any( EXPORTING iv_data = io_type = -type is_prefix = ls_next_prefix iv_item_order = lv_item_order CHANGING ct_nodes = ct_nodes ). ENDLOOP. ENDMETHOD. METHOD convert_table. DATA lo_table TYPE REF TO cl_abap_tabledescr. DATA lo_ltype TYPE REF TO cl_abap_typedescr. DATA ls_next_prefix LIKE is_prefix. DATA lv_tabix TYPE sy-tabix. DATA ls_root LIKE LINE OF ct_nodes. FIELD-SYMBOLS LIKE ls_root. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. " Array root ls_root-path = is_prefix-path. ls_root-name = is_prefix-name. ls_root-type = zif_abapgit_ajson_types=>node_type-array. ls_root-index = iv_index. ls_root-order = iv_item_order. IF mi_custom_mapping IS BOUND. ls_root-name = mi_custom_mapping->to_json( iv_path = is_prefix-path iv_name = is_prefix-name ). ENDIF. IF ls_root-name IS INITIAL. ls_root-name = is_prefix-name. ENDIF. APPEND ls_root TO ct_nodes ASSIGNING . " Array items lo_table ?= io_type. lo_ltype = lo_table->get_table_line_type( ). ls_next_prefix-path = is_prefix-path && -name && '/'. ASSIGN iv_data TO . lv_tabix = 1. LOOP AT ASSIGNING . ls_next_prefix-name = to_lower( |{ lv_tabix }| ). convert_any( EXPORTING iv_data = io_type = lo_ltype is_prefix = ls_next_prefix iv_index = -children + 1 CHANGING ct_nodes = ct_nodes ). -children = -children + 1. lv_tabix = lv_tabix + 1. ENDLOOP. ENDMETHOD. METHOD insert_with_type. DATA lo_type TYPE REF TO cl_abap_typedescr. DATA lo_converter TYPE REF TO kHGwlMWhQrsNKkKXALnpeJqampzabz. lo_type = cl_abap_typedescr=>describe_by_data( iv_data ). CREATE OBJECT lo_converter. lo_converter->mi_custom_mapping = ii_custom_mapping. lo_converter->mv_keep_item_order = is_opts-keep_item_order. lo_converter->mv_format_datetime = is_opts-format_datetime. lo_converter->insert_value_with_type( EXPORTING iv_data = iv_data iv_type = iv_type io_type = lo_type is_prefix = is_prefix iv_index = iv_array_index iv_item_order = iv_item_order CHANGING ct_nodes = rt_nodes ). ENDMETHOD. METHOD insert_value_with_type. DATA lv_prefix TYPE string. DATA ls_node LIKE LINE OF ct_nodes. lv_prefix = is_prefix-path && is_prefix-name. IF io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>texts OR io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>date OR io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>time. IF iv_type = zif_abapgit_ajson_types=>node_type-boolean AND iv_data <> 'true' AND iv_data <> 'false'. zcx_abapgit_ajson_error=>raise( |Unexpected boolean value [{ iv_data }] @{ lv_prefix }| ). ELSEIF iv_type = zif_abapgit_ajson_types=>node_type-null AND iv_data IS NOT INITIAL. zcx_abapgit_ajson_error=>raise( |Unexpected null value [{ iv_data }] @{ lv_prefix }| ). ELSEIF iv_type = zif_abapgit_ajson_types=>node_type-number AND iv_data CN '0123456789. E+-'. zcx_abapgit_ajson_error=>raise( |Unexpected numeric value [{ iv_data }] @{ lv_prefix }| ). ELSEIF iv_type <> zif_abapgit_ajson_types=>node_type-string AND iv_type <> zif_abapgit_ajson_types=>node_type-boolean AND iv_type <> zif_abapgit_ajson_types=>node_type-null AND iv_type <> zif_abapgit_ajson_types=>node_type-number. zcx_abapgit_ajson_error=>raise( |Unexpected type for value [{ iv_type },{ iv_data }] @{ lv_prefix }| ). ENDIF. ELSEIF io_type->type_kind CO iUFTsMWhQrsNKkKXALnpdAMURRqLkF=>numeric. IF iv_type <> zif_abapgit_ajson_types=>node_type-number. zcx_abapgit_ajson_error=>raise( |Unexpected value for numeric [{ iv_data }] @{ lv_prefix }| ). ENDIF. ELSE. zcx_abapgit_ajson_error=>raise( |Unexpected type [{ io_type->type_kind }] @{ lv_prefix }| ). ENDIF. ls_node-path = is_prefix-path. ls_node-name = is_prefix-name. ls_node-index = iv_index. ls_node-value = iv_data. ls_node-type = iv_type. ls_node-order = iv_item_order. IF mi_custom_mapping IS BOUND. ls_node-name = mi_custom_mapping->to_json( iv_path = is_prefix-path iv_name = is_prefix-name ). ENDIF. IF ls_node-name IS INITIAL. ls_node-name = is_prefix-name. ENDIF. APPEND ls_node TO ct_nodes. ENDMETHOD. ENDCLASS. ********************************************************************** * MUTATOR INTERFACE ********************************************************************** * renamed: zcl_abapgit_ajson :: lif_mutator_runner INTERFACE iUFTsMWhQrsNKkKXALnptzVIYRIbuu. METHODS run IMPORTING it_source_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts EXPORTING et_dest_tree TYPE zif_abapgit_ajson_types=>ty_nodes_ts RAISING zcx_abapgit_ajson_error. ENDINTERFACE. ********************************************************************** * FILTER RUNNER ********************************************************************** * renamed: zcl_abapgit_ajson :: lcl_filter_runner CLASS kHGwlMWhQrsNKkKXALnplwblMIpVBS DEFINITION FINAL. PUBLIC SECTION. INTERFACES iUFTsMWhQrsNKkKXALnptzVIYRIbuu. CLASS-METHODS new IMPORTING ii_filter TYPE REF TO zif_abapgit_ajson_filter RETURNING VALUE(ro_instance) TYPE REF TO kHGwlMWhQrsNKkKXALnplwblMIpVBS. METHODS constructor IMPORTING ii_filter TYPE REF TO zif_abapgit_ajson_filter. PRIVATE SECTION. DATA mi_filter TYPE REF TO zif_abapgit_ajson_filter. DATA mr_source_tree TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. DATA mr_dest_tree TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. METHODS walk IMPORTING iv_path TYPE string CHANGING cs_parent TYPE zif_abapgit_ajson_types=>ty_node OPTIONAL RAISING zcx_abapgit_ajson_error. ENDCLASS. CLASS kHGwlMWhQrsNKkKXALnplwblMIpVBS IMPLEMENTATION. METHOD new. CREATE OBJECT ro_instance EXPORTING ii_filter = ii_filter. ENDMETHOD. METHOD constructor. ASSERT ii_filter IS BOUND. mi_filter = ii_filter. ENDMETHOD. METHOD iUFTsMWhQrsNKkKXALnptzVIYRIbuu~run. CLEAR et_dest_tree. GET REFERENCE OF it_source_tree INTO mr_source_tree. GET REFERENCE OF et_dest_tree INTO mr_dest_tree. walk( iv_path = '' ). ENDMETHOD. METHOD walk. DATA ls_node TYPE zif_abapgit_ajson_types=>ty_node. LOOP AT mr_source_tree->* INTO ls_node WHERE path = iv_path. CASE ls_node-type. WHEN zif_abapgit_ajson_types=>node_type-boolean OR zif_abapgit_ajson_types=>node_type-null OR zif_abapgit_ajson_types=>node_type-number OR zif_abapgit_ajson_types=>node_type-string. IF mi_filter->keep_node( ls_node ) = abap_false. CONTINUE. ENDIF. WHEN zif_abapgit_ajson_types=>node_type-array OR zif_abapgit_ajson_types=>node_type-object. IF mi_filter->keep_node( is_node = ls_node iv_visit = zif_abapgit_ajson_filter=>visit_type-open ) = abap_false. CONTINUE. ENDIF. " Intentionally clear AFTER "open" CLEAR ls_node-children. walk( EXPORTING iv_path = iv_path && ls_node-name && `/` CHANGING cs_parent = ls_node ). IF mi_filter->keep_node( is_node = ls_node iv_visit = zif_abapgit_ajson_filter=>visit_type-close ) = abap_false. CONTINUE. ENDIF. WHEN OTHERS. zcx_abapgit_ajson_error=>raise( |Unexpected node type { ls_node-type }| ). ENDCASE. IF cs_parent IS SUPPLIED. cs_parent-children = cs_parent-children + 1. IF cs_parent-type = zif_abapgit_ajson_types=>node_type-array. ls_node-name = |{ cs_parent-children }|. ls_node-index = cs_parent-children. ENDIF. ENDIF. INSERT ls_node INTO TABLE mr_dest_tree->*. ENDLOOP. ENDMETHOD. ENDCLASS. ********************************************************************** * MAPPER RUNNER ********************************************************************** * renamed: zcl_abapgit_ajson :: lcl_mapper_runner CLASS kHGwlMWhQrsNKkKXALnphFTcRDbOtm DEFINITION FINAL. PUBLIC SECTION. INTERFACES iUFTsMWhQrsNKkKXALnptzVIYRIbuu. CLASS-METHODS new IMPORTING ii_mapper TYPE REF TO zif_abapgit_ajson_mapping RETURNING VALUE(ro_instance) TYPE REF TO kHGwlMWhQrsNKkKXALnphFTcRDbOtm. METHODS constructor IMPORTING ii_mapper TYPE REF TO zif_abapgit_ajson_mapping. PRIVATE SECTION. DATA mi_mapper TYPE REF TO zif_abapgit_ajson_mapping. DATA mr_source_tree TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. DATA mr_dest_tree TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. METHODS process_deep_node IMPORTING iv_path TYPE string iv_renamed_path TYPE string iv_node_type TYPE zif_abapgit_ajson_types=>ty_node-type RAISING zcx_abapgit_ajson_error. ENDCLASS. CLASS kHGwlMWhQrsNKkKXALnphFTcRDbOtm IMPLEMENTATION. METHOD new. CREATE OBJECT ro_instance EXPORTING ii_mapper = ii_mapper. ENDMETHOD. METHOD constructor. ASSERT ii_mapper IS BOUND. mi_mapper = ii_mapper. ENDMETHOD. METHOD iUFTsMWhQrsNKkKXALnptzVIYRIbuu~run. FIELD-SYMBOLS LIKE LINE OF it_source_tree. READ TABLE it_source_tree WITH KEY path = `` name = `` ASSIGNING . IF sy-subrc <> 0 OR NOT ( -type = zif_abapgit_ajson_types=>node_type-array OR -type = zif_abapgit_ajson_types=>node_type-object ). " empty or one-value-only tree et_dest_tree = it_source_tree. RETURN. ENDIF. CLEAR et_dest_tree. GET REFERENCE OF it_source_tree INTO mr_source_tree. GET REFERENCE OF et_dest_tree INTO mr_dest_tree. INSERT INTO TABLE et_dest_tree. process_deep_node( iv_path = `/` iv_renamed_path = `/` iv_node_type = -type ). ENDMETHOD. METHOD process_deep_node. FIELD-SYMBOLS LIKE LINE OF mr_source_tree->*. DATA ls_renamed_node LIKE . LOOP AT mr_source_tree->* ASSIGNING WHERE path = iv_path. ls_renamed_node = . IF iv_node_type <> zif_abapgit_ajson_types=>node_type-array. " don't rename array item names -> they are numeric index mi_mapper->rename_node( EXPORTING is_node = CHANGING cv_name = ls_renamed_node-name ). IF ls_renamed_node-name IS INITIAL. zcx_abapgit_ajson_error=>raise( iv_msg = 'Renamed node name cannot be empty' is_node = ). ENDIF. ENDIF. ls_renamed_node-path = iv_renamed_path. INSERT ls_renamed_node INTO TABLE mr_dest_tree->*. IF sy-subrc <> 0. " = 4 ? zcx_abapgit_ajson_error=>raise( iv_msg = 'Renamed node has a duplicate' is_node = ls_renamed_node ). ENDIF. " maybe also catch CX_SY_ITAB_DUPLICATE_KEY but secondary keys are not changed here, so not for now IF -type = zif_abapgit_ajson_types=>node_type-array OR -type = zif_abapgit_ajson_types=>node_type-object. process_deep_node( iv_path = iv_path && -name && `/` iv_renamed_path = iv_renamed_path && ls_renamed_node-name && `/` iv_node_type = -type ). ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. ********************************************************************** * MUTATOR QUEUE ********************************************************************** * renamed: zcl_abapgit_ajson :: lcl_mutator_queue CLASS kHGwlMWhQrsNKkKXALnpucOpllUiAS DEFINITION FINAL. PUBLIC SECTION. INTERFACES iUFTsMWhQrsNKkKXALnptzVIYRIbuu. CLASS-METHODS new RETURNING VALUE(ro_instance) TYPE REF TO kHGwlMWhQrsNKkKXALnpucOpllUiAS. METHODS add IMPORTING ii_mutator TYPE REF TO iUFTsMWhQrsNKkKXALnptzVIYRIbuu RETURNING VALUE(ro_self) TYPE REF TO kHGwlMWhQrsNKkKXALnpucOpllUiAS. PRIVATE SECTION. DATA mt_queue TYPE STANDARD TABLE OF REF TO iUFTsMWhQrsNKkKXALnptzVIYRIbuu. ENDCLASS. CLASS kHGwlMWhQrsNKkKXALnpucOpllUiAS IMPLEMENTATION. METHOD add. IF ii_mutator IS BOUND. APPEND ii_mutator TO mt_queue. ENDIF. ro_self = me. ENDMETHOD. METHOD new. CREATE OBJECT ro_instance. ENDMETHOD. METHOD iUFTsMWhQrsNKkKXALnptzVIYRIbuu~run. DATA li_mutator TYPE REF TO iUFTsMWhQrsNKkKXALnptzVIYRIbuu. DATA lv_qsize TYPE i. FIELD-SYMBOLS LIKE it_source_tree. FIELD-SYMBOLS LIKE it_source_tree. DATA lr_buf TYPE REF TO zif_abapgit_ajson_types=>ty_nodes_ts. lv_qsize = lines( mt_queue ). IF lv_qsize = 0. et_dest_tree = it_source_tree. RETURN. ENDIF. LOOP AT mt_queue INTO li_mutator. IF sy-tabix = 1. ASSIGN it_source_tree TO . ELSE. ASSIGN lr_buf->* TO . ENDIF. IF sy-tabix = lv_qsize. ASSIGN et_dest_tree TO . ELSE. CREATE DATA lr_buf. ASSIGN lr_buf->* TO . ENDIF. li_mutator->run( EXPORTING it_source_tree = IMPORTING et_dest_tree = ). ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_ajson IMPLEMENTATION. METHOD constructor. ms_opts-keep_item_order = iv_keep_item_order. ms_opts-to_abap_corresponding_only = iv_to_abap_corresponding_only. format_datetime( iv_format_datetime ). ENDMETHOD. METHOD create_empty. CREATE OBJECT ro_instance EXPORTING iv_to_abap_corresponding_only = iv_to_abap_corresponding_only iv_format_datetime = iv_format_datetime iv_keep_item_order = iv_keep_item_order. ro_instance->mi_custom_mapping = ii_custom_mapping. ENDMETHOD. METHOD create_from. DATA lo_mutator_queue TYPE REF TO kHGwlMWhQrsNKkKXALnpucOpllUiAS. IF ii_source_json IS NOT BOUND. zcx_abapgit_ajson_error=>raise( 'Source not bound' ). ENDIF. CREATE OBJECT ro_instance EXPORTING iv_to_abap_corresponding_only = ii_source_json->opts( )-to_abap_corresponding_only iv_format_datetime = ii_source_json->opts( )-format_datetime iv_keep_item_order = ii_source_json->opts( )-keep_item_order. IF ii_filter IS NOT BOUND AND ii_mapper IS NOT BOUND. ro_instance->mt_json_tree = ii_source_json->mt_json_tree. ELSE. CREATE OBJECT lo_mutator_queue. IF ii_mapper IS BOUND. " Mapping goes first. But maybe it should be a freely definable queue of processors ? lo_mutator_queue->add( kHGwlMWhQrsNKkKXALnphFTcRDbOtm=>new( ii_mapper ) ). ENDIF. IF ii_filter IS BOUND. lo_mutator_queue->add( kHGwlMWhQrsNKkKXALnplwblMIpVBS=>new( ii_filter ) ). ENDIF. lo_mutator_queue->iUFTsMWhQrsNKkKXALnptzVIYRIbuu~run( EXPORTING it_source_tree = ii_source_json->mt_json_tree IMPORTING et_dest_tree = ro_instance->mt_json_tree ). ENDIF. ENDMETHOD. METHOD delete_subtree. DATA lv_parent_path TYPE string. DATA lr_parent LIKE ir_parent. READ TABLE mt_json_tree INTO rs_top_node WITH KEY path = iv_path name = iv_name. IF sy-subrc <> 0. RETURN. " Not found ? nothing to delete ! ENDIF. DELETE mt_json_tree INDEX sy-tabix. " where path = iv_path and name = iv_name. IF rs_top_node-children > 0. " only for objects and arrays lv_parent_path = iv_path && iv_name && '/*'. DELETE mt_json_tree WHERE path CP lv_parent_path. ENDIF. " decrement parent children IF ir_parent IS SUPPLIED. ir_parent->children = ir_parent->children - 1. ELSE. lr_parent = get_item( iv_path ). IF lr_parent IS NOT INITIAL. lr_parent->children = lr_parent->children - 1. ENDIF. ENDIF. ENDMETHOD. METHOD get_item. FIELD-SYMBOLS LIKE LINE OF mt_json_tree. DATA ls_path_name TYPE zif_abapgit_ajson_types=>ty_path_name. ls_path_name = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( iv_path ). READ TABLE mt_json_tree ASSIGNING WITH KEY path = ls_path_name-path name = ls_path_name-name. IF sy-subrc = 0. GET REFERENCE OF INTO rv_item. ENDIF. ENDMETHOD. METHOD new. CREATE OBJECT ro_instance EXPORTING iv_to_abap_corresponding_only = iv_to_abap_corresponding_only iv_format_datetime = iv_format_datetime iv_keep_item_order = iv_keep_item_order. ENDMETHOD. METHOD parse. DATA lo_parser TYPE REF TO kHGwlMWhQrsNKkKXALnpfipvepHQnc. CREATE OBJECT ro_instance. CREATE OBJECT lo_parser. ro_instance->mt_json_tree = lo_parser->parse( iv_json = iv_json iv_keep_item_order = iv_keep_item_order ). ro_instance->mi_custom_mapping = ii_custom_mapping. ro_instance->ms_opts-keep_item_order = iv_keep_item_order. IF iv_freeze = abap_true. ro_instance->freeze( ). ENDIF. ENDMETHOD. METHOD prove_path_exists. DATA lt_path TYPE string_table. DATA lr_node_parent LIKE rr_end_node. DATA lv_cur_path TYPE string. DATA lv_cur_name TYPE string. DATA ls_new_node LIKE LINE OF mt_json_tree. SPLIT iv_path AT '/' INTO TABLE lt_path. DELETE lt_path WHERE table_line IS INITIAL. DO. lr_node_parent = rr_end_node. READ TABLE mt_json_tree REFERENCE INTO rr_end_node WITH KEY path = lv_cur_path name = lv_cur_name. IF sy-subrc <> 0. " New node, assume it is always object as it has a named child, use touch_array to init array CLEAR ls_new_node. IF lr_node_parent IS NOT INITIAL. " if has parent lr_node_parent->children = lr_node_parent->children + 1. IF lr_node_parent->type = zif_abapgit_ajson_types=>node_type-array. ls_new_node-index = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>validate_array_index( iv_path = lv_cur_path iv_index = lv_cur_name ). ENDIF. ENDIF. ls_new_node-path = lv_cur_path. ls_new_node-name = lv_cur_name. ls_new_node-type = zif_abapgit_ajson_types=>node_type-object. INSERT ls_new_node INTO TABLE mt_json_tree REFERENCE INTO rr_end_node. ENDIF. lv_cur_path = lv_cur_path && lv_cur_name && '/'. READ TABLE lt_path INDEX sy-index INTO lv_cur_name. IF sy-subrc <> 0. EXIT. " no more segments ENDIF. ENDDO. ENDMETHOD. METHOD read_only_watchdog. IF ms_opts-read_only = abap_true. zcx_abapgit_ajson_error=>raise( 'This json instance is read only' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson~array_to_string_table. DATA lv_normalized_path TYPE string. DATA lr_node TYPE REF TO zif_abapgit_ajson_types=>ty_node. FIELD-SYMBOLS LIKE LINE OF mt_json_tree. lv_normalized_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>normalize_path( iv_path ). lr_node = get_item( iv_path ). IF lr_node IS INITIAL. zcx_abapgit_ajson_error=>raise( |Path not found: { iv_path }| ). ENDIF. IF lr_node->type <> zif_abapgit_ajson_types=>node_type-array. zcx_abapgit_ajson_error=>raise( |Array expected at: { iv_path }| ). ENDIF. LOOP AT mt_json_tree ASSIGNING WHERE path = lv_normalized_path. CASE -type. WHEN zif_abapgit_ajson_types=>node_type-number OR zif_abapgit_ajson_types=>node_type-string. APPEND -value TO rt_string_table. WHEN zif_abapgit_ajson_types=>node_type-null. APPEND '' TO rt_string_table. WHEN zif_abapgit_ajson_types=>node_type-boolean. DATA lv_tmp TYPE string. IF -value = 'true'. lv_tmp = abap_true. ELSE. CLEAR lv_tmp. ENDIF. APPEND lv_tmp TO rt_string_table. WHEN OTHERS. zcx_abapgit_ajson_error=>raise( |Cannot convert [{ -type }] to string at [{ -path }{ -name }]| ). ENDCASE. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_ajson~clear. read_only_watchdog( ). CLEAR mt_json_tree. ENDMETHOD. METHOD zif_abapgit_ajson~clone. ri_json = create_from( me ). ENDMETHOD. METHOD zif_abapgit_ajson~delete. read_only_watchdog( ). DATA ls_split_path TYPE zif_abapgit_ajson_types=>ty_path_name. ls_split_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( iv_path ). delete_subtree( iv_path = ls_split_path-path iv_name = ls_split_path-name ). ri_json = me. ENDMETHOD. METHOD zif_abapgit_ajson~exists. rv_exists = boolc( get_item( iv_path ) IS NOT INITIAL ). ENDMETHOD. METHOD zif_abapgit_ajson~filter. ri_json = create_from( ii_source_json = me ii_filter = ii_filter ). ENDMETHOD. METHOD zif_abapgit_ajson~format_datetime. ms_opts-format_datetime = iv_use_iso. ri_json = me. ENDMETHOD. METHOD zif_abapgit_ajson~freeze. ms_opts-read_only = abap_true. ENDMETHOD. METHOD zif_abapgit_ajson~get. DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. lr_item = get_item( iv_path ). IF lr_item IS NOT INITIAL. rv_value = lr_item->value. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson~get_boolean. DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. lr_item = get_item( iv_path ). IF lr_item IS INITIAL OR lr_item->type = zif_abapgit_ajson_types=>node_type-null. RETURN. ELSEIF lr_item->type = zif_abapgit_ajson_types=>node_type-boolean. rv_value = boolc( lr_item->value = 'true' ). ELSEIF lr_item->value IS NOT INITIAL. rv_value = abap_true. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson~get_date. DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. DATA lv_y TYPE c LENGTH 4. DATA lv_m TYPE c LENGTH 2. DATA lv_d TYPE c LENGTH 2. lr_item = get_item( iv_path ). IF lr_item IS NOT INITIAL AND lr_item->type = zif_abapgit_ajson_types=>node_type-string. FIND FIRST OCCURRENCE OF REGEX '^(\d{4})-(\d{2})-(\d{2})(T|$)' IN lr_item->value SUBMATCHES lv_y lv_m lv_d. CONCATENATE lv_y lv_m lv_d INTO rv_value. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson~get_integer. DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. lr_item = get_item( iv_path ). IF lr_item IS NOT INITIAL AND lr_item->type = zif_abapgit_ajson_types=>node_type-number. rv_value = lr_item->value. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson~get_node_type. DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. lr_item = get_item( iv_path ). IF lr_item IS NOT INITIAL. rv_node_type = lr_item->type. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson~get_number. DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. lr_item = get_item( iv_path ). IF lr_item IS NOT INITIAL AND lr_item->type = zif_abapgit_ajson_types=>node_type-number. rv_value = lr_item->value. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson~get_string. DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. lr_item = get_item( iv_path ). IF lr_item IS NOT INITIAL AND lr_item->type <> zif_abapgit_ajson_types=>node_type-null. rv_value = lr_item->value. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson~get_timestamp. DATA lo_to_abap TYPE REF TO kHGwlMWhQrsNKkKXALnpXxNdxsjJjI. DATA lr_item TYPE REF TO zif_abapgit_ajson_types=>ty_node. lr_item = get_item( iv_path ). IF lr_item IS INITIAL. RETURN. ENDIF. CREATE OBJECT lo_to_abap. TRY. rv_value = lo_to_abap->to_timestamp( lr_item->value ). CATCH zcx_abapgit_ajson_error. RETURN. ENDTRY. ENDMETHOD. METHOD zif_abapgit_ajson~is_empty. rv_yes = boolc( lines( mt_json_tree ) = 0 ). ENDMETHOD. METHOD zif_abapgit_ajson~keep_item_order. ms_opts-keep_item_order = abap_true. ri_json = me. ENDMETHOD. METHOD zif_abapgit_ajson~map. ri_json = create_from( ii_source_json = me ii_mapper = ii_mapper ). ENDMETHOD. METHOD zif_abapgit_ajson~members. DATA lv_normalized_path TYPE string. FIELD-SYMBOLS LIKE LINE OF mt_json_tree. lv_normalized_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>normalize_path( iv_path ). LOOP AT mt_json_tree ASSIGNING WHERE path = lv_normalized_path. APPEND -name TO rt_members. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_ajson~opts. rs_opts = ms_opts. ENDMETHOD. METHOD zif_abapgit_ajson~push. DATA lr_parent TYPE REF TO zif_abapgit_ajson_types=>ty_node. DATA lr_new_node TYPE REF TO zif_abapgit_ajson_types=>ty_node. read_only_watchdog( ). lr_parent = get_item( iv_path ). IF lr_parent IS INITIAL. zcx_abapgit_ajson_error=>raise( |Path [{ iv_path }] does not exist| ). ENDIF. IF lr_parent->type <> zif_abapgit_ajson_types=>node_type-array. zcx_abapgit_ajson_error=>raise( |Path [{ iv_path }] is not array| ). ENDIF. DATA lt_new_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt. DATA ls_new_path TYPE zif_abapgit_ajson_types=>ty_path_name. DATA lv_new_index TYPE i. lv_new_index = lr_parent->children + 1. ls_new_path-path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>normalize_path( iv_path ). ls_new_path-name = |{ lv_new_index }|. lt_new_nodes = kHGwlMWhQrsNKkKXALnpeJqampzabz=>convert( is_opts = ms_opts iv_data = iv_val is_prefix = ls_new_path ). READ TABLE lt_new_nodes INDEX 1 REFERENCE INTO lr_new_node. " assume first record is the array item - not ideal ! ASSERT sy-subrc = 0. lr_new_node->index = lv_new_index. " update data lr_parent->children = lv_new_index. INSERT LINES OF lt_new_nodes INTO TABLE mt_json_tree. ri_json = me. ENDMETHOD. METHOD zif_abapgit_ajson~set. DATA ls_split_path TYPE zif_abapgit_ajson_types=>ty_path_name. DATA lr_parent TYPE REF TO zif_abapgit_ajson_types=>ty_node. DATA ls_deleted_node TYPE zif_abapgit_ajson_types=>ty_node. DATA lv_item_order TYPE zif_abapgit_ajson_types=>ty_node-order. read_only_watchdog( ). ri_json = me. IF iv_val IS INITIAL AND iv_ignore_empty = abap_true AND iv_node_type IS INITIAL. RETURN. " nothing to assign ENDIF. IF iv_node_type IS NOT INITIAL AND iv_node_type <> zif_abapgit_ajson_types=>node_type-boolean AND iv_node_type <> zif_abapgit_ajson_types=>node_type-null AND iv_node_type <> zif_abapgit_ajson_types=>node_type-number AND iv_node_type <> zif_abapgit_ajson_types=>node_type-string. zcx_abapgit_ajson_error=>raise( |Unexpected type { iv_node_type }| ). ENDIF. ls_split_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( iv_path ). IF ls_split_path IS INITIAL. " Assign root, exceptional processing IF iv_node_type IS NOT INITIAL. mt_json_tree = kHGwlMWhQrsNKkKXALnpeJqampzabz=>insert_with_type( is_opts = ms_opts iv_data = iv_val iv_type = iv_node_type is_prefix = ls_split_path ii_custom_mapping = mi_custom_mapping ). ELSE. mt_json_tree = kHGwlMWhQrsNKkKXALnpeJqampzabz=>convert( is_opts = ms_opts iv_data = iv_val is_prefix = ls_split_path ii_custom_mapping = mi_custom_mapping ). ENDIF. RETURN. ENDIF. " Ensure whole path exists lr_parent = prove_path_exists( ls_split_path-path ). ASSERT lr_parent IS NOT INITIAL. " delete if exists with subtree ls_deleted_node = delete_subtree( ir_parent = lr_parent iv_path = ls_split_path-path iv_name = ls_split_path-name ). lv_item_order = ls_deleted_node-order. " convert to json DATA lt_new_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt. DATA lv_array_index TYPE i. IF lr_parent->type = zif_abapgit_ajson_types=>node_type-array. lv_array_index = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>validate_array_index( iv_path = ls_split_path-path iv_index = ls_split_path-name ). ELSEIF lr_parent->type = zif_abapgit_ajson_types=>node_type-object AND lv_item_order = 0 AND ms_opts-keep_item_order = abap_true. lv_item_order = lr_parent->children + 1. ENDIF. IF iv_node_type IS NOT INITIAL. lt_new_nodes = kHGwlMWhQrsNKkKXALnpeJqampzabz=>insert_with_type( is_opts = ms_opts iv_item_order = lv_item_order iv_data = iv_val iv_type = iv_node_type iv_array_index = lv_array_index is_prefix = ls_split_path ii_custom_mapping = mi_custom_mapping ). ELSE. lt_new_nodes = kHGwlMWhQrsNKkKXALnpeJqampzabz=>convert( is_opts = ms_opts iv_item_order = lv_item_order iv_data = iv_val iv_array_index = lv_array_index is_prefix = ls_split_path ii_custom_mapping = mi_custom_mapping ). ENDIF. " update nodes IF lines( lt_new_nodes ) > 0. lr_parent->children = lr_parent->children + 1. INSERT LINES OF lt_new_nodes INTO TABLE mt_json_tree. ENDIF. ENDMETHOD. METHOD zif_abapgit_ajson~setx. DATA lv_path TYPE string. DATA lv_val TYPE string. DATA lv_int TYPE i. DATA lv_dec TYPE decfloat34. DATA lv_last TYPE i. IF iv_param IS INITIAL. ri_json = me. RETURN. ENDIF. SPLIT iv_param AT ':' INTO lv_path lv_val. CONDENSE lv_path. CONDENSE lv_val. IF lv_val IS INITIAL. ri_json = me. RETURN. " Hmm ? or empty string ? or null ? ENDIF. IF go_float_regex IS NOT BOUND. CREATE OBJECT go_float_regex EXPORTING pattern = '^([1-9][0-9]*|0)\.[0-9]+$'. " expects fractional, because ints are detected separately ENDIF. IF lv_val = 'null'. zif_abapgit_ajson~set_null( lv_path ). ELSEIF lv_val = 'true'. zif_abapgit_ajson~set_boolean( iv_path = lv_path iv_val = abap_true ). ELSEIF lv_val = 'false'. zif_abapgit_ajson~set_boolean( iv_path = lv_path iv_val = abap_false ). ELSEIF lv_val CO '0123456789'. lv_int = lv_val. zif_abapgit_ajson~set_integer( iv_path = lv_path iv_val = lv_int ). ELSEIF lv_val CO '0123456789.' AND go_float_regex->create_matcher( text = lv_val )->match( ) = abap_true. lv_dec = lv_val. zif_abapgit_ajson~set( iv_path = lv_path iv_val = lv_dec ). ELSEIF lv_val+0(1) = '{' OR lv_val+0(1) = '['. "Expect object/array, but no further checks, parser will catch errors zif_abapgit_ajson~set( iv_path = lv_path iv_val = parse( iv_json = lv_val iv_keep_item_order = ms_opts-keep_item_order ) ). ELSE. " string lv_last = strlen( lv_val ) - 1. IF lv_val+0(1) = '"' AND lv_val+lv_last(1) = '"'. lv_val = substring( val = lv_val off = 1 len = lv_last - 1 ). ENDIF. zif_abapgit_ajson~set_string( iv_path = lv_path iv_val = lv_val ). ENDIF. ri_json = me. ENDMETHOD. METHOD zif_abapgit_ajson~set_boolean. ri_json = me. DATA lv_bool TYPE abap_bool. lv_bool = boolc( iv_val IS NOT INITIAL ). zif_abapgit_ajson~set( iv_ignore_empty = abap_false iv_path = iv_path iv_val = lv_bool ). ENDMETHOD. METHOD zif_abapgit_ajson~set_date. ri_json = me. DATA lv_val TYPE string. lv_val = kHGwlMWhQrsNKkKXALnpeJqampzabz=>format_date( iv_val ). zif_abapgit_ajson~set( iv_ignore_empty = abap_false iv_path = iv_path iv_val = lv_val ). ENDMETHOD. METHOD zif_abapgit_ajson~set_integer. ri_json = me. zif_abapgit_ajson~set( iv_ignore_empty = abap_false iv_path = iv_path iv_val = iv_val ). ENDMETHOD. METHOD zif_abapgit_ajson~set_null. ri_json = me. DATA lv_null_ref TYPE REF TO data. zif_abapgit_ajson~set( iv_ignore_empty = abap_false iv_path = iv_path iv_val = lv_null_ref ). ENDMETHOD. METHOD zif_abapgit_ajson~set_string. ri_json = me. DATA lv_val TYPE string. lv_val = iv_val. zif_abapgit_ajson~set( iv_ignore_empty = abap_false iv_path = iv_path iv_val = lv_val ). ENDMETHOD. METHOD zif_abapgit_ajson~set_timestamp. ri_json = me. DATA lv_timestamp_iso TYPE string. lv_timestamp_iso = kHGwlMWhQrsNKkKXALnpeJqampzabz=>format_timestamp( iv_val ). zif_abapgit_ajson~set( iv_ignore_empty = abap_false iv_path = iv_path iv_val = lv_timestamp_iso ). ENDMETHOD. METHOD zif_abapgit_ajson~slice. DATA lo_section TYPE REF TO zcl_abapgit_ajson. DATA ls_item LIKE LINE OF mt_json_tree. DATA lv_normalized_path TYPE string. DATA ls_path_parts TYPE zif_abapgit_ajson_types=>ty_path_name. DATA lv_path_len TYPE i. DATA lv_path_pattern TYPE string. CREATE OBJECT lo_section. lv_normalized_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>normalize_path( iv_path ). lv_path_len = strlen( lv_normalized_path ). ls_path_parts = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( lv_normalized_path ). READ TABLE mt_json_tree INTO ls_item WITH KEY path = ls_path_parts-path name = ls_path_parts-name. IF sy-subrc <> 0. RETURN. ENDIF. CLEAR: ls_item-path, ls_item-name, ls_item-order. " this becomes a new root INSERT ls_item INTO TABLE lo_section->mt_json_tree. lv_path_pattern = lv_normalized_path && `*`. LOOP AT mt_json_tree INTO ls_item WHERE path CP lv_path_pattern. ls_item-path = substring( val = ls_item-path off = lv_path_len - 1 ). " less closing '/' INSERT ls_item INTO TABLE lo_section->mt_json_tree. ENDLOOP. ri_json = lo_section. ENDMETHOD. METHOD zif_abapgit_ajson~stringify. rv_json = kHGwlMWhQrsNKkKXALnpFgyFungUrS=>stringify( it_json_tree = mt_json_tree iv_keep_item_order = ms_opts-keep_item_order iv_indent = iv_indent ). ENDMETHOD. METHOD zif_abapgit_ajson~touch_array. DATA lr_node TYPE REF TO zif_abapgit_ajson_types=>ty_node. DATA ls_deleted_node TYPE zif_abapgit_ajson_types=>ty_node. DATA ls_new_node LIKE LINE OF mt_json_tree. DATA ls_split_path TYPE zif_abapgit_ajson_types=>ty_path_name. read_only_watchdog( ). ls_split_path = kHGwlMWhQrsNKkKXALnpzByNvbZmNu=>split_path( iv_path ). IF ls_split_path IS INITIAL. " Assign root, exceptional processing ls_new_node-path = ls_split_path-path. ls_new_node-name = ls_split_path-name. ls_new_node-type = zif_abapgit_ajson_types=>node_type-array. INSERT ls_new_node INTO TABLE mt_json_tree. RETURN. ENDIF. IF iv_clear = abap_true. ls_deleted_node = delete_subtree( iv_path = ls_split_path-path iv_name = ls_split_path-name ). ELSE. lr_node = get_item( iv_path ). ENDIF. IF lr_node IS INITIAL. " Or node was cleared DATA lr_parent TYPE REF TO zif_abapgit_ajson_types=>ty_node. lr_parent = prove_path_exists( ls_split_path-path ). ASSERT lr_parent IS NOT INITIAL. lr_parent->children = lr_parent->children + 1. ls_new_node-path = ls_split_path-path. ls_new_node-name = ls_split_path-name. ls_new_node-type = zif_abapgit_ajson_types=>node_type-array. IF ms_opts-keep_item_order = abap_true. IF ls_deleted_node IS NOT INITIAL. ls_new_node-order = ls_deleted_node-order. ELSE. ls_new_node-order = lr_parent->children. ENDIF. ENDIF. INSERT ls_new_node INTO TABLE mt_json_tree. ELSEIF lr_node->type <> zif_abapgit_ajson_types=>node_type-array. zcx_abapgit_ajson_error=>raise( |Path [{ iv_path }] already used and is not array| ). ENDIF. ri_json = me. ENDMETHOD. METHOD zif_abapgit_ajson~to_abap. DATA lo_to_abap TYPE REF TO kHGwlMWhQrsNKkKXALnpXxNdxsjJjI. CLEAR ev_container. CREATE OBJECT lo_to_abap EXPORTING iv_corresponding = boolc( iv_corresponding = abap_true OR ms_opts-to_abap_corresponding_only = abap_true ) ii_custom_mapping = mi_custom_mapping. lo_to_abap->to_abap( EXPORTING it_nodes = zif_abapgit_ajson~mt_json_tree CHANGING c_container = ev_container ). ENDMETHOD. METHOD zif_abapgit_ajson~to_abap_corresponding_only. ms_opts-to_abap_corresponding_only = iv_enable. ri_json = me. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_WHERE_USED_TOOLS IMPLEMENTATION. METHOD build_package_scope. FIELD-SYMBOLS TYPE zif_abapgit_definitions=>ty_tadir. FIELD-SYMBOLS LIKE LINE OF rt_package_scope. rt_package_scope = ir_package_scope. LOOP AT it_tadir ASSIGNING . CHECK -object = 'DEVC'. APPEND INITIAL LINE TO rt_package_scope ASSIGNING . -sign = 'E'. -option = 'EQ'. -low = -obj_name. ENDLOOP. ENDMETHOD. METHOD collect_where_used. DATA li_progress TYPE REF TO zif_abapgit_progress. DATA lt_where_used TYPE ty_where_used_tt. DATA lt_objs_portion LIKE rt_objs. FIELD-SYMBOLS TYPE zif_abapgit_definitions=>ty_tadir. li_progress = zcl_abapgit_progress=>get_instance( lines( it_tadir ) ). LOOP AT it_tadir ASSIGNING . CHECK -object <> 'DEVC'. li_progress->show( iv_current = sy-tabix iv_text = |{ -object } { -obj_name }| ). lt_where_used = get_where_used( iv_obj_type = |{ -object }| iv_obj_name = -obj_name ir_package_scope = ir_package_scope ). lt_objs_portion = convert_list( iv_package = -devclass iv_obj_type = -object iv_obj_name = -obj_name it_where_used = lt_where_used ). APPEND LINES OF lt_objs_portion TO rt_objs. ENDLOOP. li_progress->off( ). ENDMETHOD. METHOD convert_list. " See also CL_FINB_GN_BBI=>GET_CROSSREF FIELD-SYMBOLS LIKE LINE OF rt_objs. FIELD-SYMBOLS LIKE LINE OF it_where_used. LOOP AT it_where_used ASSIGNING . APPEND INITIAL LINE TO rt_objs ASSIGNING . -dep_package = iv_package. -dep_obj_type = iv_obj_type. -dep_obj_name = iv_obj_name. -dep_used_obj = -used_obj. -dep_used_cls = -used_cls. -obj_cls = -object_cls. -obj_name = -encl_objec. IF -obj_name IS INITIAL. -obj_name = -object. ENDIF. IF -object_cls = 'FF'. " Function module -obj_type = 'FUNC'. -package = get_func_package( -obj_name ). ELSE. -obj_type = decode_obj_type( -object_cls ). -package = get_obj_package( iv_obj_type = -obj_type iv_obj_name = -obj_name ). IF -package IS INITIAL AND -obj_type = 'CLAS'. -package = get_obj_package( iv_obj_type = 'INTF' iv_obj_name = -obj_name ). IF -package IS NOT INITIAL. -obj_type = 'INTF'. ENDIF. ENDIF. ENDIF. IF -package IS INITIAL. IF -obj_type = 'PROG'. " Maybe it is an include -package = get_incl_package( -obj_name ). IF -package IS INITIAL. SELECT SINGLE subc INTO -obj_prog_type FROM trdir WHERE name = -obj_name. IF -obj_prog_type IS NOT INITIAL AND -obj_prog_type <> '1'. " Exec. prog -obj_type = 'INCL'. ENDIF. ENDIF. ENDIF. IF -package IS INITIAL. -package = '????'. ENDIF. ENDIF. ENDLOOP. " some includes are ENHO ... " include detection TRDIR, D010INC ??? " how to find connection with ENHO ? " Useful: https://github.com/abaplint/abaplint-sci-client/blob/main/src/deps/zcl_abaplint_deps_find.clas.abap " And cl_wb_manager->if_wb_manager~request_tool_access " And discussions in https://github.com/abapGit/abapGit/pull/6897 ENDMETHOD. METHOD decode_obj_type. FIELD-SYMBOLS LIKE LINE OF mt_dev_obj_cache. IF mt_dev_obj_cache IS INITIAL. SELECT type tadir INTO TABLE mt_dev_obj_cache FROM euobjedit. ENDIF. READ TABLE mt_dev_obj_cache ASSIGNING WITH KEY type = iv_type. IF sy-subrc = 0. rv_type = -tadir. ENDIF. ENDMETHOD. METHOD get_func_package. " See also: FUNCTION_INCLUDE_INFO, TFDIR, find main program -> get its pkg DATA ls_obj_sig LIKE LINE OF mt_object_packages. READ TABLE mt_object_packages INTO ls_obj_sig WITH KEY obj_type = 'FUNC' obj_name = iv_func_name. IF sy-subrc <> 0. SELECT SINGLE devclass INTO ls_obj_sig-package FROM info_func WHERE funcname = iv_func_name. IF ls_obj_sig-package IS NOT INITIAL. ls_obj_sig-obj_type = 'FUNC'. ls_obj_sig-obj_name = iv_func_name. INSERT ls_obj_sig INTO TABLE mt_object_packages. ENDIF. ENDIF. rv_package = ls_obj_sig-package. ENDMETHOD. METHOD get_incl_package. DATA lv_program TYPE progname. DATA lv_area TYPE rs38l_area. lv_program = iv_prog_name. CALL FUNCTION 'FUNCTION_INCLUDE_CONCATENATE' CHANGING program = lv_program complete_area = lv_area EXCEPTIONS not_enough_input = 1 no_function_pool = 2 delimiter_wrong_position = 3 OTHERS = 4. IF lv_area IS INITIAL. SELECT SINGLE master FROM d010inc INTO lv_program WHERE include = iv_prog_name. CALL FUNCTION 'FUNCTION_INCLUDE_CONCATENATE' CHANGING program = lv_program complete_area = lv_area EXCEPTIONS not_enough_input = 1 no_function_pool = 2 delimiter_wrong_position = 3 OTHERS = 4. ENDIF. IF lv_area IS NOT INITIAL. rv_package = get_obj_package( iv_obj_type = 'FUGR' iv_obj_name = |{ lv_area }| ). RETURN. ENDIF. " TODO more ... ENDMETHOD. METHOD get_obj_package. " see also zcl_abapgit_tadir->get_object_package for checks DATA ls_obj_sig LIKE LINE OF mt_object_packages. READ TABLE mt_object_packages INTO ls_obj_sig WITH KEY obj_type = iv_obj_type obj_name = iv_obj_name. IF sy-subrc <> 0. ls_obj_sig-package = zcl_abapgit_factory=>get_tadir( )->read_single( iv_object = iv_obj_type iv_obj_name = iv_obj_name )-devclass. IF ls_obj_sig-package IS NOT INITIAL. ls_obj_sig-obj_type = iv_obj_type. ls_obj_sig-obj_name = iv_obj_name. INSERT ls_obj_sig INTO TABLE mt_object_packages. ENDIF. ENDIF. rv_package = ls_obj_sig-package. ENDMETHOD. METHOD get_where_used. DATA lt_findstrings TYPE string_table. DATA lt_scope LIKE it_scope. DATA lv_findstring LIKE LINE OF lt_findstrings. IF iv_obj_name IS INITIAL. RETURN. ENDIF. lt_scope = it_scope. lv_findstring = iv_obj_name. INSERT lv_findstring INTO TABLE lt_findstrings. CALL FUNCTION 'RS_EU_CROSSREF' EXPORTING i_find_obj_cls = iv_obj_type no_dialog = abap_true without_text = abap_true TABLES i_findstrings = lt_findstrings o_founds = rt_findings i_scope_object_cls = lt_scope i_scope_devclass = ir_package_scope EXCEPTIONS not_executed = 1 not_found = 2 illegal_object = 3 no_cross_for_this_object = 4 batch = 5 batchjob_error = 6 wrong_type = 7 object_not_exist = 8 OTHERS = 9. IF sy-subrc = 1 OR sy-subrc = 2 OR lines( rt_findings ) = 0. RETURN. ELSEIF sy-subrc > 2. zcx_abapgit_exception=>raise( |RS_EU_CROSSREF({ sy-subrc }) for { iv_obj_type } { iv_obj_name }| ). ENDIF. ENDMETHOD. METHOD new. CREATE OBJECT ro_instance. ENDMETHOD. METHOD select_external_usages. DATA lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. DATA lt_package_scope LIKE ir_package_scope. lt_tadir = zcl_abapgit_factory=>get_tadir( )->read( iv_package = iv_package iv_ignore_subpackages = iv_ignore_subpackages ). lt_package_scope = build_package_scope( ir_package_scope = ir_package_scope it_tadir = lt_tadir ). rt_objs = collect_where_used( ir_package_scope = lt_package_scope it_tadir = lt_tadir ). SORT rt_objs. DELETE ADJACENT DUPLICATES FROM rt_objs. " Duplicates happen e.g. because where-used is found by method. " However here this functionality aggregates them to the object " These are not true duplicates, so if ever the method name (or any other duplicate cause) " will be extracted, this sort can be removed ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_code_inspector IMPLEMENTATION. METHOD cleanup. IF mo_inspection IS BOUND. mo_inspection->delete( EXCEPTIONS locked = 1 error_in_enqueue = 2 not_authorized = 3 exceptn_appl_exists = 4 OTHERS = 5 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Couldn't delete inspection. Subrc = { sy-subrc }| ). ENDIF. ENDIF. io_set->delete( EXCEPTIONS exists_in_insp = 1 locked = 2 error_in_enqueue = 3 not_authorized = 4 exists_in_objs = 5 OTHERS = 6 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Couldn't delete objectset. Subrc = { sy-subrc }| ). ENDIF. ENDMETHOD. METHOD constructor. IF iv_package IS INITIAL. zcx_abapgit_exception=>raise( |Please supply package| ). ENDIF. mv_package = iv_package. " We create the inspection and objectset with dummy names. " Because we want to persist them so we can run it in parallel. " Both are deleted afterwards. mv_name = |{ sy-uname }_{ sy-datum }_{ sy-uzeit }|. mv_run_mode = decide_run_mode( ). ENDMETHOD. METHOD create_inspection. cl_ci_inspection=>create( EXPORTING p_user = sy-uname p_name = mv_name RECEIVING p_ref = ro_inspection EXCEPTIONS locked = 1 error_in_enqueue = 2 not_authorized = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Failed to create inspection. Subrc = { sy-subrc }| ). ENDIF. ro_inspection->set( p_chkv = io_variant p_objs = io_set ). ro_inspection->save( EXCEPTIONS missing_information = 1 insp_no_name = 2 not_enqueued = 3 OTHERS = 4 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Failed to save inspection. Subrc = { sy-subrc }| ). ENDIF. ENDMETHOD. METHOD create_objectset. DATA: lt_objs TYPE scit_objs, ls_obj TYPE scir_objs, lt_objs_check TYPE scit_objs, ls_item TYPE zif_abapgit_definitions=>ty_item, lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. lt_packages = zcl_abapgit_factory=>get_sap_package( mv_package )->list_subpackages( ). INSERT mv_package INTO TABLE lt_packages. SELECT object AS objtype obj_name AS objname FROM tadir INTO CORRESPONDING FIELDS OF TABLE lt_objs FOR ALL ENTRIES IN lt_packages WHERE devclass = lt_packages-table_line AND delflag = abap_false AND pgmid = 'R3TR' ##TOO_MANY_ITAB_FIELDS. "#EC CI_GENBUFF LOOP AT lt_objs INTO ls_obj. IF skip_object( ls_obj ) = abap_true. CONTINUE. ENDIF. ls_item-obj_type = ls_obj-objtype. ls_item-obj_name = ls_obj-objname. IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. CONTINUE. ENDIF. INSERT ls_obj INTO TABLE lt_objs_check. ENDLOOP. ro_set = cl_ci_objectset=>save_from_list( p_name = mv_name p_objects = lt_objs_check ). ENDMETHOD. METHOD create_variant. IF iv_variant IS INITIAL. zcx_abapgit_exception=>raise( |No check variant supplied.| ). ENDIF. cl_ci_checkvariant=>get_ref( EXPORTING p_user = '' p_name = iv_variant RECEIVING p_ref = ro_variant EXCEPTIONS chkv_not_exists = 1 missing_parameter = 2 OTHERS = 3 ). CASE sy-subrc. WHEN 1. zcx_abapgit_exception=>raise( |Check variant { iv_variant } doesn't exist| ). WHEN 2. zcx_abapgit_exception=>raise( |Parameter missing for check variant { iv_variant }| ). ENDCASE. ENDMETHOD. METHOD decide_run_mode. DATA lo_settings TYPE REF TO zcl_abapgit_settings. lo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). IF sy-batch = abap_true. " We have to disable parallelization in batch because of lock errors. rv_run_mode = co_run_mode-run_via_rfc. ELSEIF lo_settings->get_parallel_proc_disabled( ) = abap_false. rv_run_mode = co_run_mode-run_loc_parallel. ELSE. rv_run_mode = co_run_mode-run_via_rfc. ENDIF. ENDMETHOD. METHOD filter_inspection. " Remove findings in LSVIM* includes which are part of generated maintenance screens DELETE ct_list WHERE sobjtype = 'PROG' AND sobjname CP 'LSVIM*'. ENDMETHOD. METHOD run_inspection. io_inspection->run( EXPORTING p_howtorun = mv_run_mode EXCEPTIONS invalid_check_version = 1 OTHERS = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Code inspector run failed. Subrc = { sy-subrc }| ). ENDIF. io_inspection->plain_list( IMPORTING p_list = rt_list ). filter_inspection( CHANGING ct_list = rt_list ). SORT rt_list BY objtype objname test code sobjtype sobjname line col. DELETE ADJACENT DUPLICATES FROM rt_list. ENDMETHOD. METHOD skip_object. DATA ls_program_type TYPE subc. CASE is_obj-objtype. WHEN 'PROG'. SELECT SINGLE subc INTO ls_program_type FROM trdir WHERE name = is_obj-objname. rv_skip = boolc( ls_program_type = 'I' ). " Include program. WHEN OTHERS. rv_skip = abap_false. ENDCASE. ENDMETHOD. METHOD zif_abapgit_code_inspector~get_summary. rv_summary = mv_summary. ENDMETHOD. METHOD zif_abapgit_code_inspector~is_successful. rv_success = mv_success. ENDMETHOD. METHOD zif_abapgit_code_inspector~list_global_variants. SELECT scichkv_hd~checkvname AS name scichkv_tx~text AS description INTO TABLE rt_list FROM scichkv_hd LEFT OUTER JOIN scichkv_tx ON scichkv_hd~checkvid = scichkv_tx~checkvid AND scichkv_hd~ciuser = scichkv_tx~ciuser AND scichkv_tx~language = sy-langu WHERE scichkv_hd~ciuser = space ORDER BY name. ENDMETHOD. METHOD zif_abapgit_code_inspector~run. DATA: lo_set TYPE REF TO cl_ci_objectset, lo_variant TYPE REF TO cl_ci_checkvariant, lv_count TYPE i, lt_list TYPE scit_alvlist, ls_list LIKE LINE OF lt_list, ls_result LIKE LINE OF rt_list, lo_timer TYPE REF TO zcl_abapgit_timer, lx_error TYPE REF TO zcx_abapgit_exception. TRY. lo_set = create_objectset( ). lv_count = lines( lo_set->iobjlst-objects ). IF lv_count = 0. " no objects, nothing to check RETURN. ENDIF. lo_timer = zcl_abapgit_timer=>create( iv_count = lv_count )->start( ). lo_variant = create_variant( iv_variant ). mo_inspection = create_inspection( io_set = lo_set io_variant = lo_variant ). lt_list = run_inspection( mo_inspection ). cleanup( lo_set ). LOOP AT lt_list INTO ls_list. MOVE-CORRESPONDING ls_list TO ls_result. INSERT ls_result INTO TABLE rt_list. ENDLOOP. IF iv_save = abap_true. READ TABLE rt_list TRANSPORTING NO FIELDS WITH KEY kind = 'E'. mv_success = boolc( sy-subrc <> 0 ). ENDIF. CATCH zcx_abapgit_exception INTO lx_error. " ensure cleanup cleanup( lo_set ). zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. mv_summary = lo_timer->end( ). ENDMETHOD. METHOD zif_abapgit_code_inspector~validate_check_variant. cl_ci_checkvariant=>get_ref( EXPORTING p_user = '' p_name = iv_check_variant_name EXCEPTIONS chkv_not_exists = 1 missing_parameter = 2 OTHERS = 3 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |No valid check variant { iv_check_variant_name }| ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_url IMPLEMENTATION. METHOD host. regex( EXPORTING iv_url = iv_url IMPORTING ev_host = rv_host ). ENDMETHOD. METHOD is_abapgit_repo. IF iv_url CS 'github.com' AND ( iv_url CP '*/abapGit' OR iv_url CP '*/abapGit.git' ). rv_abapgit = abap_true. ENDIF. ENDMETHOD. METHOD name. DATA: lv_path TYPE string. TRY. regex( EXPORTING iv_url = iv_url IMPORTING ev_name = rv_name ev_path = lv_path ). IF rv_name IS INITIAL. FIND REGEX '([\w-]+)/$' IN lv_path SUBMATCHES rv_name. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Malformed URL' ). ENDIF. ENDIF. CATCH zcx_abapgit_exception. IF iv_validate = abap_true. zcx_abapgit_exception=>raise( 'Malformed URL' ). ELSE. rv_name = 'URL error (fix repo with "Advanced > Change Remote")'. ENDIF. ENDTRY. ENDMETHOD. METHOD path_name. DATA: lv_host TYPE string ##NEEDED. FIND REGEX '(.*://[^/]*)(.*)' IN iv_url SUBMATCHES lv_host rv_path_name. ENDMETHOD. METHOD regex. FIND REGEX '^(https?://[^/]*)(.*/)(.*)\.git$' IN iv_url SUBMATCHES ev_host ev_path ev_name. IF sy-subrc <> 0. FIND REGEX '^(https?://[^/]*)(.*/)(.*)$' IN iv_url SUBMATCHES ev_host ev_path ev_name. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Malformed URL' ). ENDIF. ENDIF. ENDMETHOD. METHOD url_address. DATA: lv_host TYPE string, lv_path TYPE string, lv_name TYPE string, lv_len TYPE i. regex( EXPORTING iv_url = iv_url IMPORTING ev_host = lv_host ev_path = lv_path ev_name = lv_name ). IF lv_path IS INITIAL AND lv_name IS INITIAL. zcx_abapgit_exception=>raise( 'Malformed URL' ). ELSEIF lv_name IS INITIAL. lv_len = strlen( lv_path ) - 1. IF lv_path+lv_len(1) = '/'. lv_path = lv_path(lv_len). ENDIF. ENDIF. rv_adress = |{ lv_host }{ lv_path }{ lv_name }|. ENDMETHOD. METHOD validate. name( iv_url = iv_url iv_validate = abap_true ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_PROXY_CONFIG IMPLEMENTATION. METHOD bypass_proxy. DATA lt_proxy_bypass TYPE zif_abapgit_definitions=>ty_range_proxy_bypass_url. lt_proxy_bypass = mo_settings->get_proxy_bypass( ). IF lt_proxy_bypass IS NOT INITIAL AND iv_repo_url IN lt_proxy_bypass. rv_bypass_proxy = abap_true. ENDIF. ENDMETHOD. METHOD constructor. mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). mi_exit = zcl_abapgit_exit=>get_instance( ). ENDMETHOD. METHOD get_proxy_authentication. IF bypass_proxy( iv_repo_url ) = abap_false. rv_auth = mo_settings->get_proxy_authentication( ). ENDIF. mi_exit->change_proxy_authentication( EXPORTING iv_repo_url = iv_repo_url CHANGING cv_proxy_authentication = rv_auth ). ENDMETHOD. METHOD get_proxy_port. IF bypass_proxy( iv_repo_url ) = abap_false. rv_port = mo_settings->get_proxy_port( ). ENDIF. mi_exit->change_proxy_port( EXPORTING iv_repo_url = iv_repo_url CHANGING cv_proxy_port = rv_port ). CONDENSE rv_port. ENDMETHOD. METHOD get_proxy_url. IF bypass_proxy( iv_repo_url ) = abap_false. rv_proxy_url = mo_settings->get_proxy_url( ). ENDIF. mi_exit->change_proxy_url( EXPORTING iv_repo_url = iv_repo_url CHANGING cv_proxy_url = rv_proxy_url ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_PROXY_AUTH IMPLEMENTATION. METHOD enter. zcl_abapgit_password_dialog=>popup( EXPORTING iv_repo_url = 'Proxy Authentication' CHANGING cv_user = gv_username cv_pass = gv_password ). IF gv_username IS INITIAL OR gv_password IS INITIAL. zcx_abapgit_exception=>raise( 'Proxy auth failed' ). ENDIF. ENDMETHOD. METHOD run. IF gv_username IS INITIAL OR gv_password IS INITIAL. enter( ). ENDIF. ii_client->authenticate( proxy_authentication = abap_true username = gv_username password = gv_password ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_LOGIN_MANAGER IMPLEMENTATION. METHOD append. FIELD-SYMBOLS: LIKE LINE OF gt_auth. READ TABLE gt_auth WITH KEY uri = zcl_abapgit_url=>host( iv_uri ) TRANSPORTING NO FIELDS. IF sy-subrc <> 0. APPEND INITIAL LINE TO gt_auth ASSIGNING . -uri = zcl_abapgit_url=>host( iv_uri ). -authorization = iv_auth. ENDIF. ENDMETHOD. METHOD clear. CLEAR gt_auth. ENDMETHOD. METHOD get. DATA ls_auth LIKE LINE OF gt_auth. READ TABLE gt_auth INTO ls_auth WITH KEY uri = zcl_abapgit_url=>host( iv_uri ). IF sy-subrc = 0. rv_auth = ls_auth-authorization. ENDIF. ENDMETHOD. METHOD load. DATA ls_auth LIKE LINE OF gt_auth. READ TABLE gt_auth INTO ls_auth WITH KEY uri = zcl_abapgit_url=>host( iv_uri ). IF sy-subrc = 0. rv_authorization = ls_auth-authorization. ENDIF. ENDMETHOD. METHOD save. IF NOT iv_authorization IS INITIAL. append( iv_uri = iv_uri iv_auth = iv_authorization ). ENDIF. ENDMETHOD. METHOD set. DATA: lv_concat TYPE string. ASSERT NOT iv_uri IS INITIAL. IF iv_username IS INITIAL OR iv_password IS INITIAL. RETURN. ENDIF. CONCATENATE iv_username ':' iv_password INTO lv_concat. rv_auth = cl_http_utility=>encode_base64( lv_concat ). CONCATENATE 'Basic' rv_auth INTO rv_auth SEPARATED BY space. append( iv_uri = iv_uri iv_auth = rv_auth ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_HTTP_DIGEST IMPLEMENTATION. METHOD constructor. parse( ii_client ). mv_ha1 = md5( |{ iv_username }:{ mv_realm }:{ iv_password }| ). mv_username = iv_username. ENDMETHOD. METHOD hash. DATA: lv_ha2 TYPE string. lv_ha2 = md5( |{ iv_method }:{ iv_uri }| ). ASSERT NOT iv_cnonse IS INITIAL. rv_response = md5( |{ mv_ha1 }:{ iv_nonce }:{ gv_nc }:{ iv_cnonse }:{ iv_qop }:{ lv_ha2 }| ). ENDMETHOD. METHOD md5. DATA lv_xstr TYPE xstring. DATA lv_hash TYPE xstring. DATA lv_empty TYPE xstring. lv_xstr = zcl_abapgit_convert=>string_to_xstring_utf8( iv_data ). TRY. cl_abap_hmac=>calculate_hmac_for_raw( EXPORTING if_algorithm = 'MD5' if_key = lv_empty if_data = lv_xstr IMPORTING ef_hmacxstring = lv_hash ). CATCH cx_abap_message_digest. zcx_abapgit_exception=>raise( 'error calculating md5' ). ENDTRY. rv_hash = lv_hash. TRANSLATE rv_hash TO LOWER CASE. ENDMETHOD. METHOD parse. DATA: lv_value TYPE string. lv_value = ii_client->response->get_header_field( 'www-authenticate' ). FIND REGEX 'realm="([\w ]+)"' IN lv_value SUBMATCHES mv_realm. FIND REGEX 'qop="(\w+)"' IN lv_value SUBMATCHES mv_qop. FIND REGEX 'nonce="([\w=/+\$]+)"' IN lv_value SUBMATCHES mv_nonce. ENDMETHOD. METHOD run. DATA: lv_response TYPE string, lv_method TYPE string, lv_cnonce TYPE string, lv_uri TYPE string, lv_auth TYPE string. ASSERT NOT mv_nonce IS INITIAL. lv_method = ii_client->request->get_header_field( '~request_method' ). lv_uri = ii_client->request->get_header_field( '~request_uri' ). CALL FUNCTION 'GENERAL_GET_RANDOM_STRING' EXPORTING number_chars = 24 IMPORTING random_string = lv_cnonce. lv_response = hash( iv_qop = mv_qop iv_nonce = mv_nonce iv_uri = lv_uri iv_method = lv_method iv_cnonse = lv_cnonce ). * client response lv_auth = |Digest username="{ mv_username }", realm="{ mv_realm }", nonce="{ mv_nonce }", uri="{ lv_uri }", qop={ mv_qop }, nc={ gv_nc }, cnonce="{ lv_cnonce }", response="{ lv_response }"|. ii_client->request->set_header_field( name = 'Authorization' value = lv_auth ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_http_client IMPLEMENTATION. METHOD check_http_200. DATA: lv_code TYPE i, lv_text TYPE string. mi_client->response->get_status( IMPORTING code = lv_code ). CASE lv_code. WHEN 200. RETURN. " Success, OK WHEN 302. zcx_abapgit_exception=>raise( 'Resource access temporarily redirected (HTTP 302). Check the URL' ). WHEN 401. zcx_abapgit_exception=>raise( 'Unauthorized access to resource (HTTP 401). Check your credentials' ). WHEN 403. zcx_abapgit_exception=>raise( 'Access to resource forbidden (HTTP 403)' ). WHEN 404. zcx_abapgit_exception=>raise( 'Resource not found (HTTP 404). Check the URL' ). WHEN 407. zcx_abapgit_exception=>raise( 'Proxy authentication required (HTTP 407). Check your credentials' ). WHEN 408. zcx_abapgit_exception=>raise( 'Request timeout (HTTP 408)' ). WHEN 415. zcx_abapgit_exception=>raise( 'Unsupported media type (HTTP 415)' ). WHEN 422. zcx_abapgit_exception=>raise( 'Unprocessable entity (HTTP 422). Check, if URL has to end with ".git"' ). WHEN 426. zcx_abapgit_exception=>raise( iv_text = 'Upgrade Required (HTTP 426)' iv_longtext = |The git server requires a different HTTP-protocol than which is sent. | && |abapGit uses HTTP/1.1 as default. | && |See more details in the abapGit online documentation.| ). WHEN OTHERS. lv_text = mi_client->response->get_cdata( ). zcx_abapgit_exception=>raise( |(HTTP { lv_code }) { lv_text }| ). ENDCASE. ENDMETHOD. METHOD check_smart_response. DATA: lv_content_type TYPE string. DATA: lv_data TYPE string. IF iv_expected_content_type IS NOT INITIAL. lv_content_type = mi_client->response->get_content_type( ). IF lv_content_type <> iv_expected_content_type. zcx_abapgit_exception=>raise( 'Wrong Content-Type sent by server - no fallback to the dumb protocol!' ). ENDIF. ENDIF. IF iv_content_regex IS NOT INITIAL. lv_data = mi_client->response->get_cdata( ). FIND REGEX iv_content_regex IN lv_data. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Wrong Content sent by server' ). ENDIF. ENDIF. ENDMETHOD. METHOD close. mi_client->close( ). ENDMETHOD. METHOD constructor. mi_client = ii_client. ENDMETHOD. METHOD get_cdata. rv_value = mi_client->response->get_cdata( ). ENDMETHOD. METHOD send_receive. DATA: lv_text TYPE string, lv_code TYPE i, lv_message TYPE string. mi_client->send( EXCEPTIONS http_communication_failure = 1 http_invalid_state = 2 http_processing_failed = 3 http_invalid_timeout = 4 OTHERS = 5 ). IF sy-subrc = 0. mi_client->receive( EXCEPTIONS http_communication_failure = 1 http_invalid_state = 2 http_processing_failed = 3 OTHERS = 4 ). ENDIF. IF sy-subrc <> 0. " in case of HTTP_COMMUNICATION_FAILURE " make sure: " a) SSL is setup properly in STRUST " b) no firewalls " check trace file in transaction SMICM mi_client->get_last_error( IMPORTING code = lv_code message = lv_message ). lv_text = |HTTP error { lv_code } occurred: { lv_message }|. zcx_abapgit_exception=>raise( lv_text ). ENDIF. ENDMETHOD. METHOD send_receive_close. * do not use set_cdata as it modifies the Content-Type header field mi_client->request->set_data( iv_data ). send_receive( ). check_http_200( ). rv_data = mi_client->response->get_data( ). mi_client->close( ). ENDMETHOD. METHOD set_digest. mo_digest = io_digest. ENDMETHOD. METHOD set_header. mi_client->request->set_header_field( name = iv_key value = iv_value ). ENDMETHOD. METHOD set_headers. DATA: lv_value TYPE string. mi_client->request->set_header_field( name = '~request_method' value = 'POST' ). lv_value = zcl_abapgit_url=>path_name( iv_url ) && '/git-' && iv_service && '-pack'. mi_client->request->set_header_field( name = '~request_uri' value = lv_value ). lv_value = 'application/x-git-' && iv_service && '-pack-request'. mi_client->request->set_header_field( name = 'Content-Type' value = lv_value ). lv_value = 'application/x-git-' && iv_service && '-pack-result'. mi_client->request->set_header_field( name = 'Accept' value = lv_value ). IF mo_digest IS BOUND. mo_digest->run( mi_client ). ENDIF. ENDMETHOD. ENDCLASS. CLASS kHGwlkOaymxFRlCWtlTOYvbNmJsakp DEFINITION DEFERRED. * renamed: zcl_abapgit_http_agent :: lcl_http_response CLASS kHGwlkOaymxFRlCWtlTOYvbNmJsakp DEFINITION FINAL. PUBLIC SECTION. INTERFACES zif_abapgit_http_response. CLASS-METHODS create IMPORTING ii_client TYPE REF TO if_http_client RETURNING VALUE(ri_response) TYPE REF TO zif_abapgit_http_response. PRIVATE SECTION. DATA mi_client TYPE REF TO if_http_client. DATA mi_response TYPE REF TO if_http_response. ENDCLASS. CLASS kHGwlkOaymxFRlCWtlTOYvbNmJsakp IMPLEMENTATION. METHOD create. DATA lo_response TYPE REF TO kHGwlkOaymxFRlCWtlTOYvbNmJsakp. CREATE OBJECT lo_response. lo_response->mi_client = ii_client. lo_response->mi_response = ii_client->response. ri_response ?= lo_response. ENDMETHOD. METHOD zif_abapgit_http_response~close. mi_client->close( ). ENDMETHOD. METHOD zif_abapgit_http_response~is_ok. DATA lv_code TYPE i. lv_code = zif_abapgit_http_response~code( ). rv_yes = boolc( lv_code >= 200 AND lv_code < 300 ). ENDMETHOD. METHOD zif_abapgit_http_response~data. rv_data = mi_response->get_data( ). ENDMETHOD. METHOD zif_abapgit_http_response~cdata. rv_data = mi_response->get_cdata( ). ENDMETHOD. METHOD zif_abapgit_http_response~code. DATA lv_msg TYPE string ##NEEDED. mi_response->get_status( IMPORTING reason = lv_msg " for debug code = rv_code ). ENDMETHOD. METHOD zif_abapgit_http_response~json. ri_json = zcl_abapgit_ajson=>parse( zif_abapgit_http_response~cdata( ) ). ENDMETHOD. METHOD zif_abapgit_http_response~error. rv_message = mi_response->get_cdata( ). ENDMETHOD. METHOD zif_abapgit_http_response~headers. DATA lt_headers TYPE tihttpnvp. FIELD-SYMBOLS LIKE LINE OF lt_headers. CREATE OBJECT ro_headers. mi_response->get_header_fields( CHANGING fields = lt_headers ). LOOP AT lt_headers ASSIGNING . ro_headers->set( iv_key = -name iv_val = -value ). ENDLOOP. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_HTTP_AGENT IMPLEMENTATION. METHOD attach_payload. DATA lo_type TYPE REF TO cl_abap_typedescr. lo_type = cl_abap_typedescr=>describe_by_data( iv_payload ). IF lo_type->type_kind = cl_abap_typedescr=>typekind_xstring. ii_request->set_data( iv_payload ). ELSEIF lo_type->type_kind = cl_abap_typedescr=>typekind_string. ii_request->set_cdata( iv_payload ). ELSE. zcx_abapgit_exception=>raise( |Unexpected payload type { lo_type->absolute_name }| ). ENDIF. ENDMETHOD. METHOD constructor. CREATE OBJECT mo_global_headers. ENDMETHOD. METHOD create. CREATE OBJECT ri_instance TYPE zcl_abapgit_http_agent. ENDMETHOD. METHOD zif_abapgit_http_agent~global_headers. ro_global_headers = mo_global_headers. ENDMETHOD. METHOD zif_abapgit_http_agent~request. DATA li_client TYPE REF TO if_http_client. DATA lo_proxy_configuration TYPE REF TO zcl_abapgit_proxy_config. DATA lv_code TYPE i. DATA lv_message TYPE string. FIELD-SYMBOLS LIKE LINE OF io_query->mt_entries. CREATE OBJECT lo_proxy_configuration. cl_http_client=>create_by_url( EXPORTING url = iv_url ssl_id = zcl_abapgit_exit=>get_instance( )->get_ssl_id( ) proxy_host = lo_proxy_configuration->get_proxy_url( iv_url ) proxy_service = lo_proxy_configuration->get_proxy_port( iv_url ) IMPORTING client = li_client ). li_client->request->set_version( if_http_request=>co_protocol_version_1_1 ). li_client->request->set_method( iv_method ). IF io_query IS BOUND. LOOP AT io_query->mt_entries ASSIGNING . li_client->request->set_form_field( name = -k value = -v ). ENDLOOP. ENDIF. LOOP AT mo_global_headers->mt_entries ASSIGNING . li_client->request->set_header_field( name = to_lower( -k ) value = -v ). ENDLOOP. IF io_headers IS BOUND. LOOP AT io_headers->mt_entries ASSIGNING . li_client->request->set_header_field( name = to_lower( -k ) value = -v ). ENDLOOP. ENDIF. IF iv_method = zif_abapgit_http_agent=>c_methods-post OR iv_method = zif_abapgit_http_agent=>c_methods-put OR iv_method = zif_abapgit_http_agent=>c_methods-patch. attach_payload( ii_request = li_client->request iv_payload = iv_payload ). ENDIF. li_client->send( EXCEPTIONS http_communication_failure = 1 http_invalid_state = 2 http_processing_failed = 3 http_invalid_timeout = 4 OTHERS = 5 ). IF sy-subrc = 0. li_client->receive( EXCEPTIONS http_communication_failure = 1 http_invalid_state = 2 http_processing_failed = 3 OTHERS = 4 ). ENDIF. IF sy-subrc <> 0. li_client->get_last_error( IMPORTING code = lv_code message = lv_message ). zcx_abapgit_exception=>raise( |HTTP error: [{ lv_code }] { lv_message }| ). ENDIF. ri_response = kHGwlkOaymxFRlCWtlTOYvbNmJsakp=>create( li_client ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_http IMPLEMENTATION. METHOD acquire_login_details. DATA: lv_default_user TYPE string, lv_user TYPE string, lv_pass TYPE string, lo_digest TYPE REF TO zcl_abapgit_http_digest. lv_default_user = zcl_abapgit_persistence_user=>get_instance( )->get_repo_login( iv_url ). lv_user = lv_default_user. zcl_abapgit_password_dialog=>popup( EXPORTING iv_repo_url = iv_url CHANGING cv_user = lv_user cv_pass = lv_pass ). IF lv_user IS INITIAL. zcx_abapgit_exception=>raise( 'Unauthorized access. Check your credentials' ). ENDIF. IF lv_user <> lv_default_user. zcl_abapgit_persistence_user=>get_instance( )->set_repo_login( iv_url = iv_url iv_login = lv_user ). ENDIF. rv_scheme = ii_client->response->get_header_field( 'www-authenticate' ). FIND REGEX '^(\w+)' IN rv_scheme SUBMATCHES rv_scheme. CASE rv_scheme. WHEN c_scheme-digest. * https://en.wikipedia.org/wiki/Digest_access_authentication * e.g. used by https://www.gerritcodereview.com/ CREATE OBJECT lo_digest EXPORTING ii_client = ii_client iv_username = lv_user iv_password = lv_pass. lo_digest->run( ii_client ). io_client->set_digest( lo_digest ). WHEN OTHERS. * https://en.wikipedia.org/wiki/Basic_access_authentication ii_client->authenticate( username = lv_user password = lv_pass ). ENDCASE. ENDMETHOD. METHOD check_auth_requested. DATA: lv_code TYPE i. ii_client->response->get_status( IMPORTING code = lv_code ). IF lv_code = 401. rv_auth_requested = abap_true. ENDIF. ENDMETHOD. METHOD check_connection. " Check if a connection from this system to the git host is possible " This will validate the general HTTP/HTTPS/SSL configuration and certificates get_http_client( iv_url ). ENDMETHOD. METHOD create_by_url. DATA: lv_uri TYPE string, lv_scheme TYPE string, lv_authorization TYPE string, li_client TYPE REF TO if_http_client, ls_header LIKE LINE OF it_headers. li_client = get_http_client( iv_url ). CREATE OBJECT ro_client EXPORTING ii_client = li_client. IF is_local_system( iv_url ) = abap_true. li_client->send_sap_logon_ticket( ). ENDIF. li_client->request->set_cdata( '' ). li_client->request->set_header_field( name = '~request_method' value = 'GET' ). li_client->request->set_header_field( name = 'user-agent' value = get_agent( ) ). lv_uri = zcl_abapgit_url=>path_name( iv_url ) && '/info/refs?service=git-' && iv_service && '-pack'. li_client->request->set_header_field( name = '~request_uri' value = lv_uri ). LOOP AT it_headers INTO ls_header. li_client->request->set_header_field( name = ls_header-key value = ls_header-value ). ENDLOOP. " Disable internal auth dialog (due to its unclarity) li_client->propertytype_logon_popup = if_http_client=>co_disabled. lv_authorization = zcl_abapgit_login_manager=>load( iv_url ). IF lv_authorization IS NOT INITIAL. li_client->request->set_header_field( name = 'authorization' value = lv_authorization ). li_client->propertytype_logon_popup = li_client->co_disabled. ENDIF. li_client->request->set_version( if_http_request=>co_protocol_version_1_1 ). zcl_abapgit_exit=>get_instance( )->http_client( iv_url = iv_url ii_client = li_client ). ro_client->send_receive( ). IF check_auth_requested( li_client ) = abap_true. lv_scheme = acquire_login_details( ii_client = li_client io_client = ro_client iv_url = iv_url ). ro_client->send_receive( ). ENDIF. ro_client->check_http_200( ). IF lv_scheme <> c_scheme-digest. zcl_abapgit_login_manager=>save( iv_uri = iv_url iv_authorization = li_client->request->get_header_field( 'authorization' ) ). ENDIF. ENDMETHOD. METHOD get_agent. * bitbucket require agent prefix = "git/" * also see https://github.com/abapGit/abapGit/issues/1432 rv_agent = |git/2.0 (abapGit { zif_abapgit_version=>c_abap_version })|. ENDMETHOD. METHOD get_connection_longtext. CONSTANTS lc_docs TYPE string VALUE 'https://docs.abapgit.org/user-guide/setup/ssl-setup.html'. DATA lv_proxy TYPE string. IF iv_proxy_host IS NOT INITIAL. lv_proxy = | via proxy { iv_proxy_host }:{ iv_proxy_service }|. ENDIF. rv_longtext = |abapGit is trying to connect to { iv_host } | && |using SSL certificates under { iv_ssl_id }{ lv_proxy }. | && |Check system parameters (transaction | && zcl_abapgit_html=>create( )->a( iv_txt = 'RZ10' iv_act = |{ zif_abapgit_definitions=>c_action-jump_transaction }?transaction=RZ10| iv_class = 'no-pad' ) && |), SSL setup (transaction | && zcl_abapgit_html=>create( )->a( iv_txt = 'STRUST' iv_act = |{ zif_abapgit_definitions=>c_action-jump_transaction }?transaction=STRUST| iv_class = 'no-pad' ) && |), Internet connection monitor (transaction | && zcl_abapgit_html=>create( )->a( iv_txt = 'SMICM' iv_act = |{ zif_abapgit_definitions=>c_action-jump_transaction }?transaction=SMICM| iv_class = 'no-pad' ) && |)|. IF lv_proxy IS NOT INITIAL. rv_longtext = rv_longtext && |, and proxy configuration (| && zcl_abapgit_html=>create( )->a( iv_txt = 'global settings' iv_act = |{ zif_abapgit_definitions=>c_action-go_settings }| iv_class = 'no-pad' ) && |)|. ENDIF. rv_longtext = rv_longtext && |. It's recommended to get your SAP Basis and network teams involved. | && |For more information and troubleshooting, see the | && zcl_abapgit_html=>create( )->a( iv_txt = 'abapGit documentation' iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ lc_docs }| iv_class = 'no-pad' ) && |.|. ENDMETHOD. METHOD get_http_client. DATA: lv_error TYPE string, lv_longtext TYPE string, lv_host TYPE string, lv_ssl_id TYPE ssfapplssl, lv_proxy_host TYPE string, lv_proxy_service TYPE string, lo_proxy_configuration TYPE REF TO zcl_abapgit_proxy_config. CREATE OBJECT lo_proxy_configuration. ri_client = zcl_abapgit_exit=>get_instance( )->create_http_client( iv_url ). IF ri_client IS INITIAL. lv_host = zcl_abapgit_url=>host( iv_url ). lv_ssl_id = zcl_abapgit_exit=>get_instance( )->get_ssl_id( ). lv_proxy_host = lo_proxy_configuration->get_proxy_url( iv_url ). lv_proxy_service = lo_proxy_configuration->get_proxy_port( iv_url ). lv_longtext = get_connection_longtext( iv_host = lv_host iv_ssl_id = lv_ssl_id iv_proxy_host = lv_proxy_host iv_proxy_service = lv_proxy_service ). cl_http_client=>create_by_url( EXPORTING url = lv_host ssl_id = lv_ssl_id proxy_host = lv_proxy_host proxy_service = lv_proxy_service IMPORTING client = ri_client EXCEPTIONS argument_not_found = 1 plugin_not_active = 2 internal_error = 3 OTHERS = 4 ). IF sy-subrc <> 0. CASE sy-subrc. WHEN 1. lv_error = 'ARGUMENT_NOT_FOUND'. WHEN 2. lv_error = 'PLUGIN_NOT_ACTIVE'. WHEN 3. lv_error = 'INTERNAL_ERROR'. WHEN OTHERS. lv_error = |OTHER_ERROR_{ sy-subrc }|. ENDCASE. zcx_abapgit_exception=>raise( iv_text = |Error { lv_error } creating HTTP connection. Check the configuration| iv_longtext = lv_longtext ). ENDIF. ENDIF. IF lo_proxy_configuration->get_proxy_authentication( iv_url ) = abap_true. zcl_abapgit_proxy_auth=>run( ri_client ). ENDIF. ENDMETHOD. METHOD is_local_system. DATA: lv_host TYPE string, lt_list TYPE zif_abapgit_definitions=>ty_string_tt, li_exit TYPE REF TO zif_abapgit_exit. cl_http_server=>get_location( IMPORTING host = lv_host ). APPEND lv_host TO lt_list. APPEND 'localhost' TO lt_list. li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->change_local_host( CHANGING ct_hosts = lt_list ). FIND REGEX 'https?://([^/^:]*)' IN iv_url SUBMATCHES lv_host. READ TABLE lt_list WITH KEY table_line = lv_host TRANSPORTING NO FIELDS. rv_bool = boolc( sy-subrc = 0 ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_pr_enumerator IMPLEMENTATION. METHOD constructor. mv_repo_url = to_lower( iv_url ). TRY. mi_enum_provider = create_provider( mv_repo_url ). CATCH zcx_abapgit_exception. ENDTRY. ENDMETHOD. METHOD create_provider. DATA li_agent TYPE REF TO zif_abapgit_http_agent. DATA lv_user TYPE string. DATA lv_repo TYPE string. li_agent = zcl_abapgit_factory=>get_http_agent( ). FIND ALL OCCURRENCES OF REGEX 'github\.com\/([^\/]+)\/([^\/]+)' IN iv_repo_url SUBMATCHES lv_user lv_repo. IF sy-subrc = 0. lv_repo = replace( val = lv_repo regex = '\.git$' with = '' ). CREATE OBJECT ri_provider TYPE zcl_abapgit_pr_enum_github EXPORTING iv_user_and_repo = |{ lv_user }/{ lv_repo }| ii_http_agent = li_agent. ELSE. zcx_abapgit_exception=>raise( |PR enumeration is not supported for { iv_repo_url }| ). ENDIF. " TODO somewhen more providers ENDMETHOD. METHOD get_pulls. IF mi_enum_provider IS NOT BOUND. RETURN. ENDIF. rt_pulls = mi_enum_provider->list_pull_requests( ). ENDMETHOD. METHOD new. CREATE OBJECT ro_instance EXPORTING iv_url = iv_url. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_PR_ENUM_GITHUB IMPLEMENTATION. METHOD clean_url. rv_url = replace( val = iv_url regex = '\{.*\}$' with = '' ). ENDMETHOD. METHOD constructor. DATA lv_search TYPE string. mv_repo_url = |https://api.github.com/repos/{ iv_user_and_repo }|. mi_http_agent = ii_http_agent. mi_http_agent->global_headers( )->set( iv_key = 'Accept' iv_val = 'application/vnd.github.v3+json' ). IF zcl_abapgit_login_manager=>get( mv_repo_url ) IS NOT INITIAL. mi_http_agent->global_headers( )->set( iv_key = 'Authorization' iv_val = zcl_abapgit_login_manager=>get( mv_repo_url ) ). ELSE. * fallback, try searching for the git credentials lv_search = mv_repo_url. REPLACE FIRST OCCURRENCE OF 'api.github.com/repos' IN lv_search WITH 'github.com'. IF zcl_abapgit_login_manager=>get( lv_search ) IS NOT INITIAL. mi_http_agent->global_headers( )->set( iv_key = 'Authorization' iv_val = zcl_abapgit_login_manager=>get( lv_search ) ). ENDIF. ENDIF. ENDMETHOD. METHOD convert_list. DATA lt_items TYPE string_table. DATA lv_i TYPE string. FIELD-SYMBOLS LIKE LINE OF rt_pulls. lt_items = ii_json->members( '/' ). LOOP AT lt_items INTO lv_i. APPEND INITIAL LINE TO rt_pulls ASSIGNING . -base_url = ii_json->get( |/{ lv_i }/base/repo/clone_url| ). -number = ii_json->get( |/{ lv_i }/number| ). -title = ii_json->get( |/{ lv_i }/title| ). -user = ii_json->get( |/{ lv_i }/user/login| ). -head_url = ii_json->get( |/{ lv_i }/head/repo/clone_url| ). -head_branch = ii_json->get( |/{ lv_i }/head/ref| ). -created_at = ii_json->get( |/{ lv_i }/created_at| ). -draft = ii_json->get_boolean( |/{ lv_i }/draft| ). -html_url = ii_json->get( |/{ lv_i }/html_url| ). ENDLOOP. ENDMETHOD. METHOD fetch_repo_by_url. DATA li_pulls_json TYPE REF TO zif_abapgit_ajson. DATA lv_pull_url TYPE string. DATA li_response TYPE REF TO zif_abapgit_http_response. DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. li_response = mi_http_agent->request( iv_repo_url ). TRY. rs_info-repo_json = li_response->json( ). li_response->headers( ). " for debug lv_pull_url = clean_url( rs_info-repo_json->get( '/pulls_url' ) ). IF lv_pull_url IS INITIAL OR rs_info-repo_json->get( '/message' ) = 'Not Found'. RETURN. ENDIF. li_pulls_json = mi_http_agent->request( lv_pull_url )->json( ). CATCH zcx_abapgit_ajson_error INTO lx_ajson. zcx_abapgit_exception=>raise_with_text( lx_ajson ). ENDTRY. rs_info-pulls = convert_list( li_pulls_json ). ENDMETHOD. METHOD zif_abapgit_pr_enum_provider~list_pull_requests. DATA lv_upstream_url TYPE string. DATA ls_repo_info TYPE ty_info. FIELD-SYMBOLS LIKE LINE OF ls_repo_info-pulls. ls_repo_info = fetch_repo_by_url( mv_repo_url ). APPEND LINES OF ls_repo_info-pulls TO rt_pulls. IF ls_repo_info-repo_json->get_boolean( '/fork' ) = abap_true. lv_upstream_url = ls_repo_info-repo_json->get( '/source/url' ). " parent ? ls_repo_info = fetch_repo_by_url( lv_upstream_url ). LOOP AT ls_repo_info-pulls ASSIGNING . -is_for_upstream = abap_true. APPEND TO rt_pulls. ENDLOOP. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_url IMPLEMENTATION. METHOD get_commit_display_url. DATA li_exit TYPE REF TO zif_abapgit_exit. rv_url = get_default_commit_display_url( iv_repo_url = io_repo->get_url( ) iv_hash = io_repo->get_current_remote( ) ). li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->adjust_display_commit_url( EXPORTING iv_repo_url = io_repo->get_url( ) iv_repo_name = io_repo->get_name( ) iv_repo_key = io_repo->get_key( ) iv_commit_hash = io_repo->get_current_remote( ) CHANGING cv_display_url = rv_url ). IF rv_url IS INITIAL. zcx_abapgit_exception=>raise( |provider not yet supported| ). ENDIF. ENDMETHOD. METHOD get_default_commit_display_url. DATA ls_result TYPE match_result. FIELD-SYMBOLS TYPE submatch_result. rv_commit_url = iv_repo_url. FIND REGEX '^http(?:s)?:\/\/(?:www\.)?(github\.com|bitbucket\.org|gitlab\.com)\/' IN rv_commit_url RESULTS ls_result. IF sy-subrc = 0. READ TABLE ls_result-submatches INDEX 1 ASSIGNING . CASE rv_commit_url+-offset(-length). WHEN 'github.com'. REPLACE REGEX '\.git$' IN rv_commit_url WITH space. rv_commit_url = rv_commit_url && |/commit/| && iv_hash. WHEN 'bitbucket.org'. REPLACE REGEX '\.git$' IN rv_commit_url WITH space. rv_commit_url = rv_commit_url && |/commits/| && iv_hash. WHEN 'gitlab.com'. REPLACE REGEX '\.git$' IN rv_commit_url WITH space. rv_commit_url = rv_commit_url && |/-/commit/| && iv_hash. ENDCASE. ENDIF. ENDMETHOD. METHOD validate_url. DATA lv_provider TYPE string. lv_provider = zcl_abapgit_url=>host( to_lower( iv_url ) ). " Provider-specific check for URLs that don't work IF lv_provider CS 'gitlab.com'. FIND REGEX '\.git$' IN iv_url IGNORING CASE. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Repo URL for GitLab must end in ".git"' ). ENDIF. ELSEIF lv_provider CS 'dev.azure.com'. FIND REGEX '\.git$' IN iv_url IGNORING CASE. IF sy-subrc = 0. zcx_abapgit_exception=>raise( 'Repo URL for Azure DevOps must not end in ".git"' ). ENDIF. ENDIF. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ZLIB_STREAM IMPLEMENTATION. METHOD clear_bits. CLEAR mv_bits. ENDMETHOD. METHOD constructor. mv_compressed = iv_data. ENDMETHOD. METHOD remaining. rv_length = xstrlen( mv_compressed ) + 1. ENDMETHOD. METHOD take_bits. DATA: lv_left TYPE i, lv_index TYPE i, lv_x TYPE x LENGTH 1. WHILE strlen( rv_bits ) < iv_length. IF mv_bits IS INITIAL. lv_x = mv_compressed(1). mv_bits = zcl_abapgit_zlib_convert=>hex_to_bits( lv_x ). mv_compressed = mv_compressed+1. ENDIF. lv_left = iv_length - strlen( rv_bits ). IF lv_left >= strlen( mv_bits ). CONCATENATE mv_bits rv_bits INTO rv_bits. CLEAR mv_bits. ELSE. lv_index = strlen( mv_bits ) - lv_left. CONCATENATE mv_bits+lv_index(lv_left) rv_bits INTO rv_bits. mv_bits = mv_bits(lv_index). ENDIF. ENDWHILE. ENDMETHOD. METHOD take_bytes. rv_bytes = mv_compressed(iv_length). mv_compressed = mv_compressed+iv_length. ENDMETHOD. METHOD take_int. rv_int = zcl_abapgit_zlib_convert=>bits_to_int( take_bits( iv_length ) ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ZLIB_HUFFMAN IMPLEMENTATION. METHOD constructor. DATA: lv_index TYPE i, lt_offset TYPE TABLE OF i, lv_length LIKE LINE OF it_lengths, lv_prev TYPE i, lv_count LIKE LINE OF mt_count. FIELD-SYMBOLS: LIKE LINE OF lt_offset, LIKE LINE OF mt_symbol, LIKE LINE OF it_lengths. DO c_maxbits TIMES. APPEND 0 TO mt_count. ENDDO. LOOP AT it_lengths INTO lv_index. IF lv_index = 0. CONTINUE. ENDIF. READ TABLE mt_count INDEX lv_index ASSIGNING . ASSERT sy-subrc = 0. = + 1. ENDLOOP. ************ APPEND 0 TO lt_offset. DO c_maxbits - 1 TIMES. READ TABLE mt_count INDEX sy-index INTO lv_count. ASSERT sy-subrc = 0. lv_prev = lv_prev + lv_count. APPEND lv_prev TO lt_offset. ENDDO. DO lines( it_lengths ) TIMES. APPEND 0 TO mt_symbol. ENDDO. DO lines( it_lengths ) TIMES. lv_index = sy-index. READ TABLE it_lengths INDEX lv_index INTO lv_length. ASSERT sy-subrc = 0. IF lv_length = 0. CONTINUE. ENDIF. READ TABLE lt_offset INDEX lv_length ASSIGNING . ASSERT sy-subrc = 0. READ TABLE mt_symbol INDEX + 1 ASSIGNING . ASSERT sy-subrc = 0. = lv_index - 1. = + 1. ENDDO. ENDMETHOD. METHOD get_count. READ TABLE mt_count INDEX iv_index INTO rv_value. "#EC CI_SUBRC ENDMETHOD. METHOD get_symbol. READ TABLE mt_symbol INDEX iv_index INTO rv_value. "#EC CI_SUBRC ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_ZLIB_CONVERT IMPLEMENTATION. METHOD bits_to_int. DATA lv_i TYPE i. DATA lv_offset TYPE i. DO strlen( iv_bits ) TIMES. lv_i = iv_bits+lv_offset(1). rv_int = rv_int * 2 + lv_i. lv_offset = lv_offset + 1. ENDDO. ENDMETHOD. METHOD hex_to_bits. DATA: lv_x TYPE x LENGTH 1, lv_c TYPE c LENGTH 1, lv_bit TYPE i, lv_hex TYPE xstring. lv_hex = iv_hex. WHILE NOT lv_hex IS INITIAL. lv_x = lv_hex. DO 8 TIMES. lv_bit = sy-index. GET BIT lv_bit OF lv_x INTO lv_c. CONCATENATE rv_bits lv_c INTO rv_bits. ENDDO. lv_hex = lv_hex+1. ENDWHILE. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_zlib IMPLEMENTATION. METHOD copy_out. * copy one byte at a time, it is not possible to copy using * string offsets, as it might copy data that does not exist * in mv_out yet DATA: lv_distance TYPE i, lv_index TYPE i, lv_x TYPE x LENGTH 1. lv_distance = xstrlen( gv_out ) - is_pair-distance. DO is_pair-length TIMES. lv_index = sy-index - 1 + lv_distance. lv_x = gv_out+lv_index(1). CONCATENATE gv_out lv_x INTO gv_out IN BYTE MODE. ENDDO. ENDMETHOD. METHOD decode. DATA: lv_bit TYPE c LENGTH 1, lv_len TYPE i, lv_count TYPE i, lv_code TYPE i, lv_index TYPE i, lv_first TYPE i, lv_bits TYPE string. DO zcl_abapgit_zlib_huffman=>c_maxbits TIMES. lv_len = sy-index. lv_bit = go_stream->take_bits( 1 ). CONCATENATE lv_bits lv_bit INTO lv_bits. lv_code = zcl_abapgit_zlib_convert=>bits_to_int( lv_bits ). lv_count = io_huffman->get_count( lv_len ). IF lv_code - lv_count < lv_first. rv_symbol = io_huffman->get_symbol( lv_index + lv_code - lv_first + 1 ). RETURN. ENDIF. lv_index = lv_index + lv_count. lv_first = lv_first + lv_count. lv_first = lv_first * 2. ENDDO. ENDMETHOD. METHOD decode_loop. DATA lv_x TYPE x. DATA lv_symbol TYPE i. DO. lv_symbol = decode( go_lencode ). IF lv_symbol < 256. lv_x = lv_symbol. CONCATENATE gv_out lv_x INTO gv_out IN BYTE MODE. ELSEIF lv_symbol = 256. EXIT. ELSE. copy_out( read_pair( lv_symbol ) ). ENDIF. ENDDO. ENDMETHOD. METHOD decompress. DATA: lv_bfinal TYPE c LENGTH 1, lv_btype TYPE c LENGTH 2. IF iv_compressed IS INITIAL. RETURN. ENDIF. CLEAR gv_out. CREATE OBJECT go_stream EXPORTING iv_data = iv_compressed. DO. lv_bfinal = go_stream->take_bits( 1 ). lv_btype = go_stream->take_bits( 2 ). CASE lv_btype. WHEN '00'. not_compressed( ). WHEN '01'. fixed( ). decode_loop( ). WHEN '10'. dynamic( ). decode_loop( ). WHEN OTHERS. ASSERT 1 = 0. ENDCASE. IF lv_bfinal = '1'. EXIT. ENDIF. ENDDO. rs_data-raw = gv_out. rs_data-compressed_len = xstrlen( iv_compressed ) - go_stream->remaining( ). ENDMETHOD. METHOD dynamic. DATA: lv_nlen TYPE i, lv_ndist TYPE i, lv_ncode TYPE i, lv_index TYPE i, lv_length TYPE i, lv_symbol TYPE i, lt_order TYPE TABLE OF i, lt_lengths TYPE zcl_abapgit_zlib_huffman=>ty_lengths, lt_dists TYPE zcl_abapgit_zlib_huffman=>ty_lengths. FIELD-SYMBOLS: LIKE LINE OF lt_lengths. APPEND 16 TO lt_order. APPEND 17 TO lt_order. APPEND 18 TO lt_order. APPEND 0 TO lt_order. APPEND 8 TO lt_order. APPEND 7 TO lt_order. APPEND 9 TO lt_order. APPEND 6 TO lt_order. APPEND 10 TO lt_order. APPEND 5 TO lt_order. APPEND 11 TO lt_order. APPEND 4 TO lt_order. APPEND 12 TO lt_order. APPEND 3 TO lt_order. APPEND 13 TO lt_order. APPEND 2 TO lt_order. APPEND 14 TO lt_order. APPEND 1 TO lt_order. APPEND 15 TO lt_order. lv_nlen = go_stream->take_int( 5 ) + 257. lv_ndist = go_stream->take_int( 5 ) + 1. lv_ncode = go_stream->take_int( 4 ) + 4. DO 19 TIMES. APPEND 0 TO lt_lengths. ENDDO. DO lv_ncode TIMES. READ TABLE lt_order INDEX sy-index INTO lv_index. ASSERT sy-subrc = 0. lv_index = lv_index + 1. READ TABLE lt_lengths INDEX lv_index ASSIGNING . ASSERT sy-subrc = 0. = go_stream->take_int( 3 ). ENDDO. CREATE OBJECT go_lencode EXPORTING it_lengths = lt_lengths. CLEAR lt_lengths. WHILE lines( lt_lengths ) < lv_nlen + lv_ndist. lv_symbol = decode( go_lencode ). IF lv_symbol < 16. APPEND lv_symbol TO lt_lengths. ELSE. lv_length = 0. IF lv_symbol = 16. READ TABLE lt_lengths INDEX lines( lt_lengths ) INTO lv_length. ASSERT sy-subrc = 0. lv_symbol = go_stream->take_int( 2 ) + 3. ELSEIF lv_symbol = 17. lv_symbol = go_stream->take_int( 3 ) + 3. ELSE. lv_symbol = go_stream->take_int( 7 ) + 11. ENDIF. DO lv_symbol TIMES. APPEND lv_length TO lt_lengths. ENDDO. ENDIF. ENDWHILE. lt_dists = lt_lengths. DELETE lt_lengths FROM lv_nlen + 1. DELETE lt_dists TO lv_nlen. CREATE OBJECT go_lencode EXPORTING it_lengths = lt_lengths. CREATE OBJECT go_distcode EXPORTING it_lengths = lt_dists. ENDMETHOD. METHOD fixed. DATA: lt_lengths TYPE zcl_abapgit_zlib_huffman=>ty_lengths. DO 144 TIMES. APPEND 8 TO lt_lengths. ENDDO. DO 112 TIMES. APPEND 9 TO lt_lengths. ENDDO. DO 24 TIMES. APPEND 7 TO lt_lengths. ENDDO. DO 8 TIMES. APPEND 8 TO lt_lengths. ENDDO. CREATE OBJECT go_lencode EXPORTING it_lengths = lt_lengths. CLEAR lt_lengths. DO c_maxdcodes TIMES. APPEND 5 TO lt_lengths. ENDDO. CREATE OBJECT go_distcode EXPORTING it_lengths = lt_lengths. ENDMETHOD. METHOD map_distance. CASE iv_code. WHEN 0. rv_distance = go_stream->take_int( 0 ) + 1. WHEN 1. rv_distance = go_stream->take_int( 0 ) + 2. WHEN 2. rv_distance = go_stream->take_int( 0 ) + 3. WHEN 3. rv_distance = go_stream->take_int( 0 ) + 4. WHEN 4. rv_distance = go_stream->take_int( 1 ) + 5. WHEN 5. rv_distance = go_stream->take_int( 1 ) + 7. WHEN 6. rv_distance = go_stream->take_int( 2 ) + 9. WHEN 7. rv_distance = go_stream->take_int( 2 ) + 13. WHEN 8. rv_distance = go_stream->take_int( 3 ) + 17. WHEN 9. rv_distance = go_stream->take_int( 3 ) + 25. WHEN 10. rv_distance = go_stream->take_int( 4 ) + 33. WHEN 11. rv_distance = go_stream->take_int( 4 ) + 49. WHEN 12. rv_distance = go_stream->take_int( 5 ) + 65. WHEN 13. rv_distance = go_stream->take_int( 5 ) + 97. WHEN 14. rv_distance = go_stream->take_int( 6 ) + 129. WHEN 15. rv_distance = go_stream->take_int( 6 ) + 193. WHEN 16. rv_distance = go_stream->take_int( 7 ) + 257. WHEN 17. rv_distance = go_stream->take_int( 7 ) + 385. WHEN 18. rv_distance = go_stream->take_int( 8 ) + 513. WHEN 19. rv_distance = go_stream->take_int( 8 ) + 769. WHEN 20. rv_distance = go_stream->take_int( 9 ) + 1025. WHEN 21. rv_distance = go_stream->take_int( 9 ) + 1537. WHEN 22. rv_distance = go_stream->take_int( 10 ) + 2049. WHEN 23. rv_distance = go_stream->take_int( 10 ) + 3073. WHEN 24. rv_distance = go_stream->take_int( 11 ) + 4097. WHEN 25. rv_distance = go_stream->take_int( 11 ) + 6145. WHEN 26. rv_distance = go_stream->take_int( 12 ) + 8193. WHEN 27. rv_distance = go_stream->take_int( 12 ) + 12289. WHEN 28. rv_distance = go_stream->take_int( 13 ) + 16385. WHEN 29. rv_distance = go_stream->take_int( 13 ) + 24577. WHEN OTHERS. ASSERT 1 = 0. ENDCASE. ENDMETHOD. METHOD map_length. CASE iv_code. WHEN 257. rv_length = go_stream->take_int( 0 ) + 3. WHEN 258. rv_length = go_stream->take_int( 0 ) + 4. WHEN 259. rv_length = go_stream->take_int( 0 ) + 5. WHEN 260. rv_length = go_stream->take_int( 0 ) + 6. WHEN 261. rv_length = go_stream->take_int( 0 ) + 7. WHEN 262. rv_length = go_stream->take_int( 0 ) + 8. WHEN 263. rv_length = go_stream->take_int( 0 ) + 9. WHEN 264. rv_length = go_stream->take_int( 0 ) + 10. WHEN 265. rv_length = go_stream->take_int( 1 ) + 11. WHEN 266. rv_length = go_stream->take_int( 1 ) + 13. WHEN 267. rv_length = go_stream->take_int( 1 ) + 15. WHEN 268. rv_length = go_stream->take_int( 1 ) + 17. WHEN 269. rv_length = go_stream->take_int( 2 ) + 19. WHEN 270. rv_length = go_stream->take_int( 2 ) + 23. WHEN 271. rv_length = go_stream->take_int( 2 ) + 27. WHEN 272. rv_length = go_stream->take_int( 2 ) + 31. WHEN 273. rv_length = go_stream->take_int( 3 ) + 35. WHEN 274. rv_length = go_stream->take_int( 3 ) + 43. WHEN 275. rv_length = go_stream->take_int( 3 ) + 51. WHEN 276. rv_length = go_stream->take_int( 3 ) + 59. WHEN 277. rv_length = go_stream->take_int( 4 ) + 67. WHEN 278. rv_length = go_stream->take_int( 4 ) + 83. WHEN 279. rv_length = go_stream->take_int( 4 ) + 99. WHEN 280. rv_length = go_stream->take_int( 4 ) + 115. WHEN 281. rv_length = go_stream->take_int( 5 ) + 131. WHEN 282. rv_length = go_stream->take_int( 5 ) + 163. WHEN 283. rv_length = go_stream->take_int( 5 ) + 195. WHEN 284. rv_length = go_stream->take_int( 5 ) + 227. WHEN 285. rv_length = go_stream->take_int( 0 ) + 258. WHEN OTHERS. ASSERT 1 = 0. ENDCASE. ENDMETHOD. METHOD not_compressed. DATA: lv_len TYPE i, lv_nlen TYPE i ##NEEDED. DATA lv_bytes TYPE xstring. * skip any remaining bits in current partially processed byte go_stream->clear_bits( ). lv_len = go_stream->take_int( 16 ). lv_nlen = go_stream->take_int( 16 ). lv_bytes = go_stream->take_bytes( lv_len ). CONCATENATE gv_out lv_bytes INTO gv_out IN BYTE MODE. ENDMETHOD. METHOD read_pair. DATA: lv_symbol TYPE i. rs_pair-length = map_length( iv_length ). lv_symbol = decode( go_distcode ). rs_pair-distance = map_distance( lv_symbol ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_hash IMPLEMENTATION. METHOD adler32. CONSTANTS: lc_adler TYPE i VALUE 65521, lc_max_b TYPE i VALUE 1800000000. DATA: lv_index TYPE i, lv_a TYPE i VALUE 1, lv_b TYPE i VALUE 0, lv_x TYPE x LENGTH 2, lv_ca TYPE c LENGTH 4, lv_cb TYPE c LENGTH 4, lv_char8 TYPE c LENGTH 8. DO xstrlen( iv_xstring ) TIMES. lv_index = sy-index - 1. lv_a = lv_a + iv_xstring+lv_index(1). lv_b = lv_b + lv_a. * delay the MOD operation until the integer might overflow * articles describe 5552 additions are allowed, but this assumes unsigned integers * instead of allowing a fixed number of additions before running MOD, then * just compare value of lv_b, this is 1 operation less than comparing and adding IF lv_b > lc_max_b. lv_a = lv_a MOD lc_adler. lv_b = lv_b MOD lc_adler. ENDIF. ENDDO. lv_a = lv_a MOD lc_adler. lv_b = lv_b MOD lc_adler. lv_x = lv_a. lv_ca = lv_x. lv_x = lv_b. lv_cb = lv_x. CONCATENATE lv_cb lv_ca INTO lv_char8. rv_checksum = lv_char8. ENDMETHOD. METHOD sha1. DATA: lv_len TYPE i, lv_char10 TYPE c LENGTH 10, lv_string TYPE string, lv_xstring TYPE xstring. lv_len = xstrlen( iv_data ). lv_char10 = lv_len. CONDENSE lv_char10. CONCATENATE iv_type lv_char10 INTO lv_string SEPARATED BY space. lv_xstring = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). lv_string = lv_xstring. CONCATENATE lv_string '00' INTO lv_string. lv_xstring = lv_string. CONCATENATE lv_xstring iv_data INTO lv_xstring IN BYTE MODE. rv_sha1 = sha1_raw( lv_xstring ). ENDMETHOD. METHOD sha1_blob. rv_sha1 = sha1( iv_type = zif_abapgit_git_definitions=>c_type-blob iv_data = iv_data ). ENDMETHOD. METHOD sha1_commit. rv_sha1 = sha1( iv_type = zif_abapgit_git_definitions=>c_type-commit iv_data = iv_data ). ENDMETHOD. METHOD sha1_raw. DATA: lv_hash TYPE string, lv_key TYPE xstring, lx_error TYPE REF TO cx_abap_message_digest. TRY. cl_abap_hmac=>calculate_hmac_for_raw( EXPORTING if_key = lv_key if_data = iv_data IMPORTING ef_hmacstring = lv_hash ). CATCH cx_abap_message_digest INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. rv_sha1 = lv_hash. TRANSLATE rv_sha1 TO LOWER CASE. ENDMETHOD. METHOD sha1_string. DATA: lv_hash TYPE string, lv_key TYPE xstring, lx_error TYPE REF TO cx_abap_message_digest. TRY. cl_abap_hmac=>calculate_hmac_for_char( EXPORTING if_key = lv_key if_data = iv_data IMPORTING ef_hmacstring = lv_hash ). CATCH cx_abap_message_digest INTO lx_error. zcx_abapgit_exception=>raise_with_text( lx_error ). ENDTRY. rv_sha1 = lv_hash. TRANSLATE rv_sha1 TO LOWER CASE. ENDMETHOD. METHOD sha1_tag. rv_sha1 = sha1( iv_type = zif_abapgit_git_definitions=>c_type-tag iv_data = iv_data ). ENDMETHOD. METHOD sha1_tree. rv_sha1 = sha1( iv_type = zif_abapgit_git_definitions=>c_type-tree iv_data = iv_data ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_utils IMPLEMENTATION. METHOD get_null. * must be length 4, or it gives a syntax error on lower versions DATA: lv_x TYPE x LENGTH 4 VALUE '00000000'. FIELD-SYMBOLS TYPE c. ASSIGN lv_x TO CASTING. rv_c = . ENDMETHOD. METHOD length_utf8_hex. DATA: lv_xstring TYPE xstring, lv_char4 TYPE c LENGTH 4, lv_x TYPE x LENGTH 2. IF xstrlen( iv_data ) < 4. zcx_abapgit_exception=>raise( 'error converting to hex, LENGTH_UTF8_HEX' ). ENDIF. lv_xstring = iv_data(4). lv_char4 = zcl_abapgit_convert=>xstring_to_string_utf8( iv_data = lv_xstring iv_length = 4 ). TRANSLATE lv_char4 TO UPPER CASE. lv_x = lv_char4. rv_len = lv_x. ENDMETHOD. METHOD pkt_string. DATA: lv_x TYPE x, lv_len TYPE i. lv_len = strlen( iv_string ). IF lv_len >= 255. zcx_abapgit_exception=>raise( 'PKT, todo' ). ENDIF. lv_x = lv_len + 4. rv_pkt = '00' && lv_x && iv_string. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_transport IMPLEMENTATION. METHOD zif_abapgit_git_transport~branches. DATA: lo_client TYPE REF TO zcl_abapgit_http_client. branch_list( EXPORTING iv_url = iv_url iv_service = c_service-upload IMPORTING eo_client = lo_client eo_branch_list = ro_branch_list ). lo_client->close( ). ENDMETHOD. METHOD branch_list. CONSTANTS lc_content_regex TYPE string VALUE '^[0-9a-f]{4}#'. CONSTANTS lc_content_type TYPE string VALUE 'application/x-git--pack-advertisement'. DATA lv_data TYPE string. DATA lv_expected_content_type TYPE string. eo_client = zcl_abapgit_http=>create_by_url( iv_url = iv_url iv_service = iv_service ). lv_expected_content_type = lc_content_type. REPLACE '' IN lv_expected_content_type WITH iv_service. eo_client->check_smart_response( iv_expected_content_type = lv_expected_content_type iv_content_regex = lc_content_regex ). lv_data = eo_client->get_cdata( ). CREATE OBJECT eo_branch_list EXPORTING iv_data = lv_data. ENDMETHOD. METHOD check_report_status. DATA: lv_string TYPE string, lv_error TYPE string, lv_unpack_status TYPE string, lv_unpack_code TYPE string, lv_unpack_text TYPE string, lv_commnd_status TYPE string, lv_commnd_code TYPE string, lv_commnd_text TYPE string. " Based on https://git-scm.com/docs/pack-protocol/2.2.3#_report_status lv_string = iv_string. IF lv_string = ''. lv_error = 'Unexpected empty reply'. ELSEIF strlen( lv_string ) < 4. lv_error = 'Missing pkt length for unpack status'. ELSE. lv_string = lv_string+4. SPLIT lv_string AT cl_abap_char_utilities=>newline INTO lv_unpack_status lv_string. SPLIT lv_unpack_status AT space INTO lv_unpack_text lv_unpack_code. IF lv_unpack_text <> 'unpack'. lv_error = 'Unexpected unpack status'. ELSEIF lv_unpack_code <> 'ok'. lv_error = |Unpack not ok ({ lv_unpack_code })|. ELSEIF lv_string = ''. lv_error = 'Unexpected command status'. ELSEIF strlen( lv_string ) < 4. lv_error = 'Missing pkt length for command status'. ELSE. lv_string = lv_string+4. SPLIT lv_string AT cl_abap_char_utilities=>newline INTO lv_commnd_status lv_string. SPLIT lv_commnd_status AT space INTO lv_commnd_code lv_commnd_text. IF lv_commnd_code <> 'ok'. "=ng " Some pre-defined error messages IF lv_commnd_text CP '*pre-receive hook declined*'. lv_error = 'Pre-receive hook declined'. ELSEIF lv_commnd_text CP '*protected branch hook declined*'. lv_error = 'Protected branch hook declined'. ELSEIF lv_commnd_text CP '*push declined due to email privacy*'. lv_error = 'Push declined due to email privacy'. ELSEIF lv_commnd_text CP '*funny refname*'. lv_error = 'Funny refname'. ELSEIF lv_commnd_text CP '*failed to update ref*'. lv_error = 'Failed to update ref'. ELSEIF lv_commnd_text CP '*missing necessary objects*'. lv_error = 'Missing necessary objects'. ELSEIF lv_commnd_text CP '*refusing to delete the current branch*'. lv_error = 'Branch delete not allowed'. ELSEIF lv_commnd_text CP '*cannot lock ref*reference already exists*'. lv_error = 'Branch already exists'. ELSEIF lv_commnd_text CP '*cannot lock ref*but expected*'. lv_error = 'Branch cannot be locked'. ELSEIF lv_commnd_text CP '*invalid committer*'. lv_error = 'Invalid committer'. ELSE. " Otherwise return full error message lv_error = lv_commnd_text. ENDIF. ELSEIF strlen( lv_string ) < 4. lv_error = 'Missing flush-pkt'. ELSEIF lv_string <> '0000' AND lv_string <> '00000000'. " We update only one reference at a time so this should be the end lv_error = 'Unexpected end of status (flush-pkt)'. ENDIF. ENDIF. ENDIF. IF lv_error IS NOT INITIAL. zcx_abapgit_exception=>raise( |Git protocol error: { lv_error }| ). ENDIF. ENDMETHOD. METHOD find_branch. branch_list( EXPORTING iv_url = iv_url iv_service = iv_service IMPORTING eo_client = eo_client eo_branch_list = eo_branch_list ). IF ev_branch IS SUPPLIED. ev_branch = eo_branch_list->find_by_name( iv_branch_name )-sha1. ENDIF. ENDMETHOD. METHOD parse. CONSTANTS: lc_band1 TYPE x VALUE '01'. DATA: lv_len TYPE i, lv_contents TYPE xstring, lv_pack TYPE xstring. WHILE xstrlen( cv_data ) >= 4. lv_len = zcl_abapgit_git_utils=>length_utf8_hex( cv_data ). IF lv_len > xstrlen( cv_data ). zcx_abapgit_exception=>raise( 'parse, string length too large' ). ENDIF. lv_contents = cv_data(lv_len). IF lv_len = 0. cv_data = cv_data+4. CONTINUE. ELSE. cv_data = cv_data+lv_len. ENDIF. lv_contents = lv_contents+4. IF xstrlen( lv_contents ) > 1 AND lv_contents(1) = lc_band1. CONCATENATE lv_pack lv_contents+1 INTO lv_pack IN BYTE MODE. ENDIF. ENDWHILE. ev_pack = lv_pack. ENDMETHOD. METHOD receive_pack. DATA: lo_client TYPE REF TO zcl_abapgit_http_client, lv_cmd_pkt TYPE string, lv_line TYPE string, lv_tmp TYPE xstring, lv_xstring TYPE xstring, lv_string TYPE string, lv_cap_list TYPE string, lv_buffer TYPE string. find_branch( EXPORTING iv_url = iv_url iv_service = c_service-receive iv_branch_name = iv_branch_name IMPORTING eo_client = lo_client ). lo_client->set_headers( iv_url = iv_url iv_service = c_service-receive ). lv_cap_list = 'report-status'. lv_line = iv_old && ` ` && iv_new && ` ` && iv_branch_name && zcl_abapgit_git_utils=>get_null( ) && ` ` && lv_cap_list && cl_abap_char_utilities=>newline. lv_cmd_pkt = zcl_abapgit_git_utils=>pkt_string( lv_line ). lv_buffer = lv_cmd_pkt && '0000'. lv_tmp = zcl_abapgit_convert=>string_to_xstring_utf8( lv_buffer ). CONCATENATE lv_tmp iv_pack INTO lv_xstring IN BYTE MODE. lv_xstring = lo_client->send_receive_close( lv_xstring ). lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xstring ). check_report_status( lv_string ). ENDMETHOD. METHOD upload_pack. DATA: lv_capa TYPE string, lv_line TYPE string, lv_buffer TYPE string, lv_xstring TYPE xstring, lv_pack TYPE xstring. FIELD-SYMBOLS: LIKE LINE OF it_hashes. io_client->set_headers( iv_url = iv_url iv_service = c_service-upload ). LOOP AT it_hashes FROM 1 ASSIGNING . IF sy-tabix = 1. lv_capa = 'side-band-64k no-progress multi_ack'. lv_line = 'want' && ` ` && && ` ` && lv_capa && cl_abap_char_utilities=>newline. ELSE. lv_line = 'want' && ` ` && && cl_abap_char_utilities=>newline. ENDIF. lv_buffer = lv_buffer && zcl_abapgit_git_utils=>pkt_string( lv_line ). ENDLOOP. IF iv_deepen_level > 0. lv_buffer = lv_buffer && zcl_abapgit_git_utils=>pkt_string( |deepen { iv_deepen_level }| && cl_abap_char_utilities=>newline ). ENDIF. lv_buffer = lv_buffer && '0000' && '0009done' && cl_abap_char_utilities=>newline. lv_xstring = io_client->send_receive_close( zcl_abapgit_convert=>string_to_xstring_utf8( lv_buffer ) ). parse( IMPORTING ev_pack = lv_pack CHANGING cv_data = lv_xstring ). IF lv_pack IS INITIAL. zcx_abapgit_exception=>raise( 'Response could not be parsed - empty pack returned.' ). ENDIF. rt_objects = zcl_abapgit_git_pack=>decode( lv_pack ). ENDMETHOD. METHOD upload_pack_by_branch. DATA: lo_client TYPE REF TO zcl_abapgit_http_client, lt_hashes TYPE zif_abapgit_git_definitions=>ty_sha1_tt. FIELD-SYMBOLS: LIKE LINE OF it_branches. CLEAR: et_objects, ev_branch. find_branch( EXPORTING iv_url = iv_url iv_service = c_service-upload iv_branch_name = iv_branch_name IMPORTING eo_client = lo_client ev_branch = ev_branch ). IF it_branches IS INITIAL. APPEND ev_branch TO lt_hashes. ELSE. LOOP AT it_branches ASSIGNING . APPEND -sha1 TO lt_hashes. ENDLOOP. ENDIF. et_objects = upload_pack( io_client = lo_client iv_url = iv_url iv_deepen_level = iv_deepen_level it_hashes = lt_hashes ). ENDMETHOD. METHOD upload_pack_by_commit. DATA: lo_client TYPE REF TO zcl_abapgit_http_client, lt_hashes TYPE zif_abapgit_git_definitions=>ty_sha1_tt. CLEAR: et_objects, ev_commit. APPEND iv_hash TO lt_hashes. ev_commit = iv_hash. lo_client = zcl_abapgit_http=>create_by_url( iv_url = iv_url iv_service = c_service-upload ). et_objects = upload_pack( io_client = lo_client iv_url = iv_url iv_deepen_level = iv_deepen_level it_hashes = lt_hashes ). ENDMETHOD. METHOD branches. " This method is kept for compatibility reasons ro_branch_list = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_time IMPLEMENTATION. METHOD get_one_year_ago. * https://www.epochconverter.com CONSTANTS lc_epoch TYPE timestamp VALUE '19700101000000'. DATA lv_time TYPE timestamp. GET TIME STAMP FIELD lv_time. rv_time = cl_abap_tstmp=>subtract( tstmp1 = lv_time tstmp2 = lc_epoch ). rv_time = rv_time - 31536000. ENDMETHOD. METHOD get_unix. * returns seconds since Unix epoch, including timezone indicator CONSTANTS lc_epoch TYPE timestamp VALUE '19700101000000'. DATA lv_time TYPE timestamp. DATA lv_seconds TYPE i. GET TIME STAMP FIELD lv_time. lv_seconds = cl_abap_tstmp=>subtract( tstmp1 = lv_time tstmp2 = lc_epoch ). rv_time = lv_seconds. CONDENSE rv_time. rv_time+11 = '+000000'. ENDMETHOD. METHOD get_utc. CONSTANTS lc_epoch TYPE d VALUE '19700101'. DATA: lv_i TYPE i, lv_utcdiff TYPE t, lv_utcsign TYPE c LENGTH 1. lv_i = iv_unix(10). lv_utcsign = iv_unix+11. lv_utcdiff = iv_unix+12. " GMT + time-zone CASE lv_utcsign. WHEN '+'. lv_i = lv_i + lv_utcdiff. WHEN '-'. lv_i = lv_i - lv_utcdiff. ENDCASE. ev_time = lv_i MOD 86400. lv_i = lv_i - ev_time. lv_i = lv_i / 86400. ev_date = lv_i + lc_epoch. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_tag IMPLEMENTATION. METHOD add_peel. rv_text = iv_text && zif_abapgit_git_definitions=>c_git_branch-peel. ENDMETHOD. METHOD add_tag_prefix. rv_text = zif_abapgit_git_definitions=>c_git_branch-tags_prefix && iv_text. ENDMETHOD. METHOD remove_peel. rv_text = iv_text. REPLACE zif_abapgit_git_definitions=>c_git_branch-peel IN rv_text WITH ''. ENDMETHOD. METHOD remove_tag_prefix. rv_text = iv_text. REPLACE FIRST OCCURRENCE OF zif_abapgit_git_definitions=>c_git_branch-tags_prefix IN rv_text WITH ''. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_porcelain IMPLEMENTATION. METHOD build_trees. DATA: lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt, ls_tree LIKE LINE OF rt_trees, lv_len TYPE i, lt_folders TYPE ty_folders_tt. FIELD-SYMBOLS: LIKE LINE OF lt_folders, LIKE LINE OF lt_nodes, LIKE LINE OF lt_folders, LIKE LINE OF it_expanded. lt_folders = find_folders( it_expanded ). * start with the deepest folders SORT lt_folders BY count DESCENDING. LOOP AT lt_folders ASSIGNING . CLEAR lt_nodes. * files LOOP AT it_expanded ASSIGNING USING KEY path_name WHERE path = -path. APPEND INITIAL LINE TO lt_nodes ASSIGNING . -chmod = -chmod. -name = -name. -sha1 = -sha1. ENDLOOP. * folders LOOP AT lt_folders ASSIGNING WHERE count = -count + 1. lv_len = strlen( -path ). IF strlen( -path ) > lv_len AND -path(lv_len) = -path. APPEND INITIAL LINE TO lt_nodes ASSIGNING . -chmod = zif_abapgit_git_definitions=>c_chmod-dir. * extract folder name, this can probably be done easier using regular expressions -name = -path+lv_len. lv_len = strlen( -name ) - 1. -name = -name(lv_len). -sha1 = -sha1. ENDIF. ENDLOOP. CLEAR ls_tree. ls_tree-path = -path. ls_tree-data = zcl_abapgit_git_pack=>encode_tree( lt_nodes ). ls_tree-sha1 = zcl_abapgit_hash=>sha1_tree( ls_tree-data ). APPEND ls_tree TO rt_trees. -sha1 = ls_tree-sha1. ENDLOOP. ENDMETHOD. METHOD create_annotated_tag. DATA: lv_tag TYPE xstring, lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt, lv_pack TYPE xstring, ls_object LIKE LINE OF lt_objects, ls_tag TYPE zcl_abapgit_git_pack=>ty_tag, lv_new_tag_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1. * new tag ls_tag-object = is_tag-sha1. ls_tag-type = zif_abapgit_git_definitions=>c_type-commit. ls_tag-tag = is_tag-name. ls_tag-tagger_name = is_tag-tagger_name. ls_tag-tagger_email = is_tag-tagger_email. ls_tag-message = is_tag-message && |{ cl_abap_char_utilities=>newline }| && |{ cl_abap_char_utilities=>newline }| && is_tag-body. lv_tag = zcl_abapgit_git_pack=>encode_tag( ls_tag ). lv_new_tag_sha1 = zcl_abapgit_hash=>sha1_tag( lv_tag ). ls_object-sha1 = lv_new_tag_sha1. ls_object-type = zif_abapgit_git_definitions=>c_type-tag. ls_object-data = lv_tag. ls_object-index = 1. APPEND ls_object TO lt_objects. lv_pack = zcl_abapgit_git_pack=>encode( lt_objects ). zcl_abapgit_git_transport=>receive_pack( iv_url = iv_url iv_old = c_zero iv_new = lv_new_tag_sha1 iv_branch_name = is_tag-name iv_pack = lv_pack ). ENDMETHOD. METHOD create_branch. IF iv_name CS ` `. zcx_abapgit_exception=>raise( 'Branch name cannot contain blank spaces' ). ENDIF. zcl_abapgit_git_transport=>receive_pack( iv_url = iv_url iv_old = c_zero iv_new = iv_from iv_branch_name = iv_name iv_pack = empty_packfile( ) ). ENDMETHOD. METHOD create_lightweight_tag. zcl_abapgit_git_transport=>receive_pack( iv_url = iv_url iv_old = c_zero iv_new = is_tag-sha1 iv_branch_name = is_tag-name iv_pack = empty_packfile( ) ). ENDMETHOD. METHOD create_tag. IF is_tag-name CS ` `. zcx_abapgit_exception=>raise( 'Tag name cannot contain blank spaces' ). ENDIF. CASE is_tag-type. WHEN zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. create_annotated_tag( is_tag = is_tag iv_url = iv_url ). WHEN zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. create_lightweight_tag( is_tag = is_tag iv_url = iv_url ). WHEN OTHERS. zcx_abapgit_exception=>raise( |Invalid tag type: { is_tag-type }| ). ENDCASE. ENDMETHOD. METHOD delete_annotated_tag. DATA: lo_branches TYPE REF TO zcl_abapgit_git_branch_list, lv_tag TYPE string, ls_tag TYPE zif_abapgit_git_definitions=>ty_git_branch, lt_tags TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt. " For annotated tags, find the correct commit lo_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( iv_url ). lt_tags = lo_branches->get_tags_only( ). lv_tag = zcl_abapgit_git_tag=>remove_peel( is_tag-name ). READ TABLE lt_tags INTO ls_tag WITH KEY name_key COMPONENTS name = lv_tag. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Annotated tag { lv_tag } not found| ). ENDIF. zcl_abapgit_git_transport=>receive_pack( iv_url = iv_url iv_old = ls_tag-sha1 iv_new = c_zero iv_branch_name = ls_tag-name ). ENDMETHOD. METHOD delete_branch. zcl_abapgit_git_transport=>receive_pack( iv_url = iv_url iv_old = is_branch-sha1 iv_new = c_zero iv_branch_name = is_branch-name ). ENDMETHOD. METHOD delete_lightweight_tag. zcl_abapgit_git_transport=>receive_pack( iv_url = iv_url iv_old = is_tag-sha1 iv_new = c_zero iv_branch_name = is_tag-name ). ENDMETHOD. METHOD delete_tag. IF is_tag-name CS zif_abapgit_git_definitions=>c_git_branch-peel. delete_annotated_tag( is_tag = is_tag iv_url = iv_url ). ELSE. delete_lightweight_tag( is_tag = is_tag iv_url = iv_url ). ENDIF. ENDMETHOD. METHOD empty_packfile. " For avoiding "client MUST send an empty packfile" error " https://github.com/git/git/blob/master/Documentation/gitprotocol-pack.txt#L595-L599 DATA lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. rv_pack = zcl_abapgit_git_pack=>encode( lt_objects ). ENDMETHOD. METHOD find_folders. DATA: lt_paths TYPE TABLE OF string, lv_split TYPE string, lv_path TYPE string. FIELD-SYMBOLS: LIKE LINE OF rt_folders, LIKE LINE OF rt_folders, LIKE LINE OF it_expanded. LOOP AT it_expanded ASSIGNING . READ TABLE rt_folders WITH KEY path = -path TRANSPORTING NO FIELDS. IF sy-subrc <> 0. APPEND INITIAL LINE TO rt_folders ASSIGNING . -path = -path. ENDIF. ENDLOOP. * add empty folders LOOP AT rt_folders ASSIGNING . SPLIT -path AT '/' INTO TABLE lt_paths. CLEAR lv_path. LOOP AT lt_paths INTO lv_split. CONCATENATE lv_path lv_split '/' INTO lv_path. READ TABLE rt_folders WITH KEY path = lv_path TRANSPORTING NO FIELDS. IF sy-subrc <> 0. APPEND INITIAL LINE TO rt_folders ASSIGNING . -path = lv_path. ENDIF. ENDLOOP. ENDLOOP. LOOP AT rt_folders ASSIGNING . FIND ALL OCCURRENCES OF '/' IN -path MATCH COUNT -count. ENDLOOP. ENDMETHOD. METHOD full_tree. DATA: ls_object LIKE LINE OF it_objects, ls_commit TYPE zcl_abapgit_git_pack=>ty_commit. READ TABLE it_objects INTO ls_object WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-commit sha1 = iv_parent. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'commit not found' ). ENDIF. ls_commit = zcl_abapgit_git_pack=>decode_commit( ls_object-data ). rt_expanded = walk_tree( it_objects = it_objects iv_tree = ls_commit-tree iv_base = '/' ). ENDMETHOD. METHOD pull. DATA: ls_object TYPE zif_abapgit_definitions=>ty_object, ls_commit TYPE zcl_abapgit_git_pack=>ty_commit. READ TABLE it_objects INTO ls_object WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-commit sha1 = iv_commit. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Commit/Branch not found.' ). ENDIF. ls_commit = zcl_abapgit_git_pack=>decode_commit( ls_object-data ). walk( EXPORTING it_objects = it_objects iv_sha1 = ls_commit-tree iv_path = '/' CHANGING ct_files = rt_files ). ENDMETHOD. METHOD pull_by_branch. zcl_abapgit_git_transport=>upload_pack_by_branch( EXPORTING iv_url = iv_url iv_branch_name = iv_branch_name iv_deepen_level = iv_deepen_level IMPORTING et_objects = rs_result-objects ev_branch = rs_result-commit ). rs_result-files = pull( iv_commit = rs_result-commit it_objects = rs_result-objects ). ENDMETHOD. METHOD pull_by_commit. zcl_abapgit_git_transport=>upload_pack_by_commit( EXPORTING iv_url = iv_url iv_hash = iv_commit_hash iv_deepen_level = iv_deepen_level IMPORTING et_objects = rs_result-objects ev_commit = rs_result-commit ). rs_result-files = pull( iv_commit = rs_result-commit it_objects = rs_result-objects ). ENDMETHOD. METHOD push. DATA: lt_expanded TYPE zif_abapgit_git_definitions=>ty_expanded_tt, lt_blobs TYPE zif_abapgit_git_definitions=>ty_files_tt, lv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, lv_new_tree TYPE zif_abapgit_git_definitions=>ty_sha1, lt_trees TYPE ty_trees_tt, lt_stage TYPE zif_abapgit_definitions=>ty_stage_tt. FIELD-SYMBOLS: LIKE LINE OF lt_stage, LIKE LINE OF rs_result-updated_files, LIKE LINE OF lt_expanded. lt_expanded = full_tree( it_objects = it_old_objects iv_parent = iv_parent ). lt_stage = io_stage->get_all( ). LOOP AT lt_stage ASSIGNING . " Save file ref to updated files table APPEND INITIAL LINE TO rs_result-updated_files ASSIGNING . MOVE-CORRESPONDING -file TO . CASE -method. WHEN zif_abapgit_definitions=>c_method-add. APPEND -file TO lt_blobs. READ TABLE lt_expanded ASSIGNING WITH TABLE KEY path_name COMPONENTS name = -file-filename path = -file-path. IF sy-subrc <> 0. " new files APPEND INITIAL LINE TO lt_expanded ASSIGNING . -name = -file-filename. -path = -file-path. -chmod = zif_abapgit_git_definitions=>c_chmod-file. ENDIF. lv_sha1 = zcl_abapgit_hash=>sha1_blob( -file-data ). IF -sha1 <> lv_sha1. -sha1 = lv_sha1. ENDIF. -sha1 = lv_sha1. "New sha1 WHEN zif_abapgit_definitions=>c_method-rm. READ TABLE lt_expanded ASSIGNING WITH TABLE KEY path_name COMPONENTS name = -file-filename path = -file-path. ASSERT sy-subrc = 0. CLEAR -sha1. " Mark as deleted CLEAR -sha1. " Mark as deleted WHEN OTHERS. zcx_abapgit_exception=>raise( 'stage method not supported, todo' ). ENDCASE. ENDLOOP. DELETE lt_expanded WHERE sha1 IS INITIAL. lt_trees = build_trees( lt_expanded ). receive_pack_push( EXPORTING is_comment = is_comment it_trees = lt_trees iv_branch_name = iv_branch_name iv_url = iv_url iv_parent = iv_parent iv_parent2 = io_stage->get_merge_source( ) it_blobs = lt_blobs IMPORTING ev_new_commit = rs_result-branch et_new_objects = rs_result-new_objects ev_new_tree = lv_new_tree ). APPEND LINES OF it_old_objects TO rs_result-new_objects. walk( EXPORTING it_objects = rs_result-new_objects iv_sha1 = lv_new_tree iv_path = '/' CHANGING ct_files = rs_result-new_files ). ENDMETHOD. METHOD receive_pack_push. DATA: lv_time TYPE zcl_abapgit_git_time=>ty_unixtime, lv_commit TYPE xstring, lv_pack TYPE xstring, ls_object LIKE LINE OF et_new_objects, ls_commit TYPE zcl_abapgit_git_pack=>ty_commit, lv_uindex TYPE sy-index. FIELD-SYMBOLS: LIKE LINE OF it_trees, LIKE LINE OF it_blobs. lv_time = zcl_abapgit_git_time=>get_unix( ). READ TABLE it_trees ASSIGNING WITH KEY path = '/'. ASSERT sy-subrc = 0. * new commit ls_commit-committer = |{ is_comment-committer-name } <{ is_comment-committer-email }> { lv_time }|. IF is_comment-author-name IS NOT INITIAL. ls_commit-author = |{ is_comment-author-name } <{ is_comment-author-email }> { lv_time }|. ELSE. ls_commit-author = ls_commit-committer. ENDIF. ls_commit-tree = -sha1. ls_commit-parent = iv_parent. ls_commit-parent2 = iv_parent2. ls_commit-body = is_comment-comment. lv_commit = zcl_abapgit_git_pack=>encode_commit( ls_commit ). ls_object-sha1 = zcl_abapgit_hash=>sha1_commit( lv_commit ). ls_object-type = zif_abapgit_git_definitions=>c_type-commit. ls_object-data = lv_commit. APPEND ls_object TO et_new_objects. LOOP AT it_trees ASSIGNING . CLEAR ls_object. ls_object-sha1 = -sha1. READ TABLE et_new_objects WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-tree sha1 = ls_object-sha1 TRANSPORTING NO FIELDS. IF sy-subrc = 0. * two identical trees added at the same time, only add one to the pack CONTINUE. ENDIF. ls_object-type = zif_abapgit_git_definitions=>c_type-tree. ls_object-data = -data. lv_uindex = lv_uindex + 1. ls_object-index = lv_uindex. APPEND ls_object TO et_new_objects. ENDLOOP. LOOP AT it_blobs ASSIGNING . CLEAR ls_object. ls_object-sha1 = zcl_abapgit_hash=>sha1_blob( -data ). READ TABLE et_new_objects WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-blob sha1 = ls_object-sha1 TRANSPORTING NO FIELDS. IF sy-subrc = 0. * two identical files added at the same time, only add one blob to the pack CONTINUE. ENDIF. ls_object-type = zif_abapgit_git_definitions=>c_type-blob. * note -data can be empty, #1857 allow empty files - some more checks needed? ls_object-data = -data. lv_uindex = lv_uindex + 1. ls_object-index = lv_uindex. APPEND ls_object TO et_new_objects. ENDLOOP. lv_pack = zcl_abapgit_git_pack=>encode( et_new_objects ). ev_new_commit = zcl_abapgit_hash=>sha1_commit( lv_commit ). zcl_abapgit_git_transport=>receive_pack( iv_url = iv_url iv_old = iv_parent iv_new = ev_new_commit iv_branch_name = iv_branch_name iv_pack = lv_pack ). ev_new_tree = ls_commit-tree. ENDMETHOD. METHOD walk. DATA: lv_path TYPE string, ls_file LIKE LINE OF ct_files, lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt. FIELD-SYMBOLS: LIKE LINE OF it_objects, LIKE LINE OF it_objects, LIKE LINE OF lt_nodes. READ TABLE it_objects ASSIGNING WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-tree sha1 = iv_sha1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Walk, tree not found' ). ENDIF. lt_nodes = zcl_abapgit_git_pack=>decode_tree( -data ). LOOP AT lt_nodes ASSIGNING . IF -chmod = zif_abapgit_git_definitions=>c_chmod-file. READ TABLE it_objects ASSIGNING WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-blob sha1 = -sha1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Walk, blob not found' ). ENDIF. CLEAR ls_file. ls_file-path = iv_path. ls_file-filename = -name. ls_file-data = -data. ls_file-sha1 = -sha1. APPEND ls_file TO ct_files. ENDIF. ENDLOOP. LOOP AT lt_nodes ASSIGNING WHERE chmod = zif_abapgit_git_definitions=>c_chmod-dir. CONCATENATE iv_path -name '/' INTO lv_path. walk( EXPORTING it_objects = it_objects iv_sha1 = -sha1 iv_path = lv_path CHANGING ct_files = ct_files ). ENDLOOP. ENDMETHOD. METHOD walk_tree. DATA: ls_object LIKE LINE OF it_objects, lt_expanded LIKE rt_expanded, lt_nodes TYPE zcl_abapgit_git_pack=>ty_nodes_tt. FIELD-SYMBOLS: LIKE LINE OF rt_expanded, LIKE LINE OF lt_nodes. READ TABLE it_objects INTO ls_object WITH KEY type COMPONENTS type = zif_abapgit_git_definitions=>c_type-tree sha1 = iv_tree. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'tree not found' ). ENDIF. lt_nodes = zcl_abapgit_git_pack=>decode_tree( ls_object-data ). LOOP AT lt_nodes ASSIGNING . CASE -chmod. WHEN zif_abapgit_git_definitions=>c_chmod-file OR zif_abapgit_git_definitions=>c_chmod-executable OR zif_abapgit_git_definitions=>c_chmod-submodule. APPEND INITIAL LINE TO rt_expanded ASSIGNING . -path = iv_base. -name = -name. -sha1 = -sha1. -chmod = -chmod. WHEN zif_abapgit_git_definitions=>c_chmod-dir. lt_expanded = walk_tree( it_objects = it_objects iv_tree = -sha1 iv_base = iv_base && -name && '/' ). APPEND LINES OF lt_expanded TO rt_expanded. WHEN OTHERS. zcx_abapgit_exception=>raise( 'walk_tree: unknown chmod' ). ENDCASE. ENDLOOP. ENDMETHOD. ENDCLASS. *"* use this source file for the definition and implementation of *"* local helper classes, interface definitions and type *"* declarations CLASS kHGwlHhZbTrIxNkYzsWttffscEwAXR IMPLEMENTATION. METHOD constructor. mv_data = iv_data. ENDMETHOD. METHOD eat_byte. rv_x = mv_data(1). mv_data = mv_data+1. ENDMETHOD. METHOD get. rv_data = mv_data. ENDMETHOD. METHOD eat_bytes. rv_x = mv_data(iv_length). mv_data = mv_data+iv_length. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_pack IMPLEMENTATION. METHOD decode. DATA: lv_x TYPE x, lv_data TYPE xstring, lv_type TYPE c LENGTH 6, lv_zlib TYPE x LENGTH 2, lv_objects TYPE i, lv_len TYPE i, lv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, lv_ref_delta TYPE zif_abapgit_git_definitions=>ty_sha1, lv_compressed_len TYPE i, lv_compressed TYPE xstring, lv_decompressed TYPE xstring, lv_decompress_len TYPE i, lv_xstring TYPE xstring, lv_expected TYPE i, ls_object LIKE LINE OF rt_objects, lv_uindex TYPE sy-index. lv_data = iv_data. * header IF NOT xstrlen( lv_data ) > 4 OR lv_data(4) <> c_pack_start. zcx_abapgit_exception=>raise( |Unexpected pack header| ). ENDIF. lv_data = lv_data+4. * version IF lv_data(4) <> c_version. zcx_abapgit_exception=>raise( |Version not supported| ). ENDIF. lv_data = lv_data+4. * number of objects lv_xstring = lv_data(4). lv_objects = zcl_abapgit_convert=>xstring_to_int( lv_xstring ). lv_data = lv_data+4. DO lv_objects TIMES. lv_uindex = sy-index. lv_x = lv_data(1). lv_type = get_type( lv_x ). get_length( IMPORTING ev_length = lv_expected CHANGING cv_data = lv_data ). IF lv_type = zif_abapgit_git_definitions=>c_type-ref_d. lv_ref_delta = lv_data(20). lv_data = lv_data+20. ENDIF. * strip header, '789C', CMF + FLG lv_zlib = lv_data(2). IF lv_zlib <> c_zlib AND lv_zlib <> c_zlib_hmm. zcx_abapgit_exception=>raise( |Unexpected zlib header| ). ENDIF. lv_data = lv_data+2. ******************************* IF lv_zlib = c_zlib. cl_abap_gzip=>decompress_binary( EXPORTING gzip_in = lv_data IMPORTING raw_out = lv_decompressed raw_out_len = lv_decompress_len ). IF lv_expected <> lv_decompress_len. zcx_abapgit_exception=>raise( |Decompression failed| ). ENDIF. cl_abap_gzip=>compress_binary( EXPORTING raw_in = lv_decompressed IMPORTING gzip_out = lv_compressed gzip_out_len = lv_compressed_len ). IF xstrlen( lv_data ) <= lv_compressed_len OR lv_compressed(lv_compressed_len) <> lv_data(lv_compressed_len). "Lets try with zlib before error in out for good "This fixes issues with TFS 2017 and visualstudio.com Git repos zlib_decompress( CHANGING cv_data = lv_data cv_decompressed = lv_decompressed ). ELSE. lv_data = lv_data+lv_compressed_len. ENDIF. ELSEIF lv_zlib = c_zlib_hmm. * cl_abap_gzip compression works for header '789C', but does not work for * '7801', call custom implementation of DEFLATE algorithm. * The custom implementation could handle both, but most likely the kernel * implementation runs faster than the custom ABAP. zlib_decompress( CHANGING cv_data = lv_data cv_decompressed = lv_decompressed ). ENDIF. CLEAR ls_object. ls_object-adler32 = lv_data(4). lv_data = lv_data+4. " skip adler checksum IF lv_type = zif_abapgit_git_definitions=>c_type-ref_d. ls_object-sha1 = lv_ref_delta. TRANSLATE ls_object-sha1 TO LOWER CASE. ELSE. ls_object-sha1 = zcl_abapgit_hash=>sha1( iv_type = lv_type iv_data = lv_decompressed ). ENDIF. ls_object-type = lv_type. ls_object-data = lv_decompressed. ls_object-index = lv_uindex. APPEND ls_object TO rt_objects. ENDDO. * check SHA1 at end of pack lv_len = xstrlen( iv_data ) - 20. lv_xstring = iv_data(lv_len). lv_sha1 = zcl_abapgit_hash=>sha1_raw( lv_xstring ). IF to_upper( lv_sha1 ) <> lv_data. zcx_abapgit_exception=>raise( |SHA1 at end of pack doesn't match| ). ENDIF. decode_deltas( CHANGING ct_objects = rt_objects ). ENDMETHOD. METHOD decode_commit. DATA: lv_string TYPE string, lv_word TYPE string, lv_offset TYPE i, lv_length TYPE i, lv_length_gpgsig TYPE i, lv_trash TYPE string ##NEEDED, lt_string TYPE TABLE OF string. FIELD-SYMBOLS: LIKE LINE OF lt_string. lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( iv_data ). SPLIT lv_string AT cl_abap_char_utilities=>newline INTO TABLE lt_string. LOOP AT lt_string ASSIGNING . lv_length = strlen( ) + 1. lv_string = lv_string+lv_length. SPLIT AT space INTO lv_word lv_trash. CASE lv_word. WHEN 'tree'. rs_commit-tree = +5. WHEN 'parent'. IF rs_commit-parent IS INITIAL. rs_commit-parent = +7. ELSE. rs_commit-parent2 = +7. ENDIF. WHEN 'author'. rs_commit-author = +7. WHEN 'committer'. rs_commit-committer = +10. EXIT. " current loop WHEN OTHERS. ASSERT 1 = 0. ENDCASE. ENDLOOP. lv_length = strlen( lv_string ). IF lv_length >= 6 AND lv_string+0(6) = 'gpgsig'. FIND REGEX |-----END PGP SIGNATURE-----[[:space:]]+| IN lv_string MATCH OFFSET lv_offset MATCH LENGTH lv_length. lv_length = lv_length - 1. lv_length_gpgsig = lv_offset + lv_length - 7. lv_length = lv_offset + lv_length. rs_commit-gpgsig = lv_string+7(lv_length_gpgsig). lv_string = lv_string+lv_length. ENDIF. rs_commit-body = lv_string+1. IF rs_commit-author IS INITIAL OR rs_commit-committer IS INITIAL OR rs_commit-tree IS INITIAL. zcx_abapgit_exception=>raise( |multiple parents? not supported| ). ENDIF. ENDMETHOD. METHOD decode_deltas. DATA: ls_object LIKE LINE OF ct_objects, li_progress TYPE REF TO zif_abapgit_progress, lt_deltas LIKE ct_objects. LOOP AT ct_objects INTO ls_object USING KEY type WHERE type = zif_abapgit_git_definitions=>c_type-ref_d. INSERT ls_object INTO TABLE lt_deltas. ENDLOOP. DELETE ct_objects USING KEY type WHERE type = zif_abapgit_git_definitions=>c_type-ref_d. "Restore correct Delta Order SORT lt_deltas BY index. li_progress = zcl_abapgit_progress=>get_instance( lines( lt_deltas ) ). LOOP AT lt_deltas INTO ls_object. li_progress->show( iv_current = sy-tabix iv_text = 'Decode deltas' ). delta( EXPORTING is_object = ls_object CHANGING ct_objects = ct_objects ). ENDLOOP. ENDMETHOD. METHOD decode_tag. DATA: lv_string TYPE string, lv_word TYPE string, lv_trash TYPE string ##NEEDED, lt_string TYPE TABLE OF string. FIELD-SYMBOLS: LIKE LINE OF lt_string. lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( iv_data ). SPLIT lv_string AT cl_abap_char_utilities=>newline INTO TABLE lt_string. LOOP AT lt_string ASSIGNING . SPLIT AT space INTO lv_word lv_trash. CASE lv_word. WHEN 'object'. rs_tag-object = lv_trash. WHEN 'type'. rs_tag-type = lv_trash. WHEN 'tag'. rs_tag-tag = lv_trash. WHEN 'tagger'. FIND FIRST OCCURRENCE OF REGEX `(.*)<(.*)>` IN lv_trash SUBMATCHES rs_tag-tagger_name rs_tag-tagger_email. rs_tag-tagger_name = condense( rs_tag-tagger_name ). WHEN ''. " ignore blank lines CONTINUE. WHEN OTHERS. " these are the non empty line which don't start with a key word " the first one is the message, the rest are cumulated to the body IF rs_tag-message IS INITIAL. rs_tag-message = . ELSE. IF rs_tag-body IS NOT INITIAL. rs_tag-body = rs_tag-body && cl_abap_char_utilities=>newline. ENDIF. rs_tag-body = rs_tag-body && . ENDIF. ENDCASE. ENDLOOP. ENDMETHOD. METHOD decode_tree. CONSTANTS: lc_sha_length TYPE i VALUE 20, lc_null TYPE x VALUE '00'. DATA: lv_xstring TYPE xstring, lv_chmod TYPE zif_abapgit_git_definitions=>ty_chmod, lv_name TYPE string, lv_string TYPE string, lv_len TYPE i, lv_offset TYPE i, lv_cursor TYPE i, lv_match TYPE i, ls_node TYPE ty_node. DO. FIND FIRST OCCURRENCE OF lc_null IN SECTION OFFSET lv_cursor OF iv_data IN BYTE MODE MATCH OFFSET lv_match. IF sy-subrc <> 0. EXIT. ENDIF. lv_len = lv_match - lv_cursor. lv_xstring = iv_data+lv_cursor(lv_len). lv_string = zcl_abapgit_convert=>xstring_to_string_utf8( lv_xstring ). SPLIT lv_string AT space INTO lv_chmod lv_name. CLEAR ls_node. ls_node-chmod = lv_chmod. IF ls_node-chmod <> zif_abapgit_git_definitions=>c_chmod-dir AND ls_node-chmod <> zif_abapgit_git_definitions=>c_chmod-file AND ls_node-chmod <> zif_abapgit_git_definitions=>c_chmod-executable AND ls_node-chmod <> zif_abapgit_git_definitions=>c_chmod-submodule. zcx_abapgit_exception=>raise( |Unknown chmod| ). ENDIF. lv_offset = lv_match + 1. ls_node-name = lv_name. ls_node-sha1 = iv_data+lv_offset(lc_sha_length). TRANSLATE ls_node-sha1 TO LOWER CASE. APPEND ls_node TO rt_nodes. lv_cursor = lv_match + 1 + lc_sha_length. ENDDO. ENDMETHOD. METHOD delta. CONSTANTS: lc_1 TYPE x VALUE '01', lc_2 TYPE x VALUE '02', lc_4 TYPE x VALUE '04', lc_8 TYPE x VALUE '08', lc_16 TYPE x VALUE '10', lc_32 TYPE x VALUE '20', lc_64 TYPE x VALUE '40', lc_128 TYPE x VALUE '80'. DATA: lv_base TYPE xstring, lv_result TYPE xstring, lv_offset TYPE i, lo_stream TYPE REF TO kHGwlHhZbTrIxNkYzsWttffscEwAXR, lv_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1, ls_object LIKE LINE OF ct_objects, lv_len TYPE i, lv_tmp TYPE xstring, lv_org TYPE x. FIELD-SYMBOLS: LIKE LINE OF ct_objects. CREATE OBJECT lo_stream EXPORTING iv_data = is_object-data. * find base READ TABLE ct_objects ASSIGNING WITH KEY sha COMPONENTS sha1 = is_object-sha1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Base not found, { is_object-sha1 }| ). ELSEIF -type = zif_abapgit_git_definitions=>c_type-ref_d. * sanity check zcx_abapgit_exception=>raise( |Delta, base eq delta| ). ENDIF. lv_base = -data. * skip the 2 headers delta_header( lo_stream ). delta_header( lo_stream ). WHILE xstrlen( lo_stream->get( ) ) > 0. lv_org = lo_stream->eat_byte( ). IF lv_org BIT-AND lc_128 = lc_128. " MSB = 1 lv_offset = 0. IF lv_org BIT-AND lc_1 = lc_1. lv_offset = lo_stream->eat_byte( ). ENDIF. IF lv_org BIT-AND lc_2 = lc_2. lv_offset = lv_offset + lo_stream->eat_byte( ) * 256. ENDIF. IF lv_org BIT-AND lc_4 = lc_4. lv_offset = lv_offset + lo_stream->eat_byte( ) * 65536. ENDIF. IF lv_org BIT-AND lc_8 = lc_8. lv_offset = lv_offset + lo_stream->eat_byte( ) * 16777216. " hmm, overflow? ENDIF. lv_len = 0. IF lv_org BIT-AND lc_16 = lc_16. lv_len = lo_stream->eat_byte( ). ENDIF. IF lv_org BIT-AND lc_32 = lc_32. lv_len = lv_len + lo_stream->eat_byte( ) * 256. ENDIF. IF lv_org BIT-AND lc_64 = lc_64. lv_len = lv_len + lo_stream->eat_byte( ) * 65536. ENDIF. IF lv_len = 0. lv_len = 65536. ENDIF. CONCATENATE lv_result lv_base+lv_offset(lv_len) INTO lv_result IN BYTE MODE. ELSE. " lv_bitbyte(1) = '0' * insert from delta lv_len = lv_org. " convert to int lv_tmp = lo_stream->eat_bytes( lv_len ). CONCATENATE lv_result lv_tmp INTO lv_result IN BYTE MODE. ENDIF. ENDWHILE. lv_sha1 = zcl_abapgit_hash=>sha1( iv_type = -type iv_data = lv_result ). CLEAR ls_object. ls_object-sha1 = lv_sha1. ls_object-type = -type. ls_object-data = lv_result. ls_object-index = -index. "Retain sort index APPEND ls_object TO ct_objects. ENDMETHOD. METHOD delta_header. DATA: lv_bitbyte TYPE zif_abapgit_git_definitions=>ty_bitbyte, lv_bits TYPE string, lv_x TYPE x. lv_bits = ''. DO. lv_x = io_stream->eat_byte( ). lv_bitbyte = zcl_abapgit_convert=>x_to_bitbyte( lv_x ). CONCATENATE lv_bitbyte+1 lv_bits INTO lv_bits. IF lv_bitbyte(1) = '0'. EXIT. " current loop ENDIF. ENDDO. rv_header = zcl_abapgit_convert=>bitbyte_to_int( lv_bits ). ENDMETHOD. METHOD encode. DATA: lv_sha1 TYPE x LENGTH 20, lv_adler32 TYPE zif_abapgit_git_definitions=>ty_adler32, lv_compressed TYPE xstring, lv_xstring TYPE xstring, li_progress TYPE REF TO zif_abapgit_progress, lv_objects_total TYPE i. FIELD-SYMBOLS: LIKE LINE OF it_objects. rv_data = c_pack_start. CONCATENATE rv_data c_version INTO rv_data IN BYTE MODE. lv_xstring = zcl_abapgit_convert=>int_to_xstring4( lines( it_objects ) ). CONCATENATE rv_data lv_xstring INTO rv_data IN BYTE MODE. lv_objects_total = lines( it_objects ). li_progress = zcl_abapgit_progress=>get_instance( lv_objects_total ). LOOP AT it_objects ASSIGNING . li_progress->show( iv_current = sy-tabix iv_text = |Encoding objects ( { sy-tabix } of { lv_objects_total } )| ). lv_xstring = type_and_length( iv_type = -type iv_length = xstrlen( -data ) ). CONCATENATE rv_data lv_xstring INTO rv_data IN BYTE MODE. cl_abap_gzip=>compress_binary( EXPORTING raw_in = -data IMPORTING gzip_out = lv_compressed ). CONCATENATE rv_data c_zlib lv_compressed INTO rv_data IN BYTE MODE. IF NOT -adler32 IS INITIAL. lv_adler32 = -adler32. ELSE. lv_adler32 = zcl_abapgit_hash=>adler32( -data ). ENDIF. CONCATENATE rv_data lv_adler32 INTO rv_data IN BYTE MODE. ENDLOOP. lv_sha1 = to_upper( zcl_abapgit_hash=>sha1_raw( rv_data ) ). CONCATENATE rv_data lv_sha1 INTO rv_data IN BYTE MODE. ENDMETHOD. METHOD encode_commit. DATA: lv_string TYPE string, lv_tmp TYPE string, lv_tree_lower TYPE string, lv_parent_lower TYPE string. lv_tree_lower = is_commit-tree. TRANSLATE lv_tree_lower TO LOWER CASE. lv_string = ''. CONCATENATE 'tree' lv_tree_lower INTO lv_tmp SEPARATED BY space. CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. IF NOT is_commit-parent IS INITIAL. lv_parent_lower = is_commit-parent. TRANSLATE lv_parent_lower TO LOWER CASE. CONCATENATE 'parent' lv_parent_lower INTO lv_tmp SEPARATED BY space. CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. ENDIF. IF NOT is_commit-parent2 IS INITIAL. lv_parent_lower = is_commit-parent2. TRANSLATE lv_parent_lower TO LOWER CASE. CONCATENATE 'parent' lv_parent_lower INTO lv_tmp SEPARATED BY space. CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. ENDIF. CONCATENATE 'author' is_commit-author INTO lv_tmp SEPARATED BY space. CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. CONCATENATE 'committer' is_commit-committer INTO lv_tmp SEPARATED BY space. CONCATENATE lv_string lv_tmp cl_abap_char_utilities=>newline INTO lv_string. IF NOT is_commit-gpgsig IS INITIAL. CONCATENATE 'gpgsig' is_commit-gpgsig INTO lv_tmp SEPARATED BY space. CONCATENATE lv_string lv_tmp INTO lv_string. ENDIF. CONCATENATE lv_string cl_abap_char_utilities=>newline is_commit-body INTO lv_string. rv_data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). ENDMETHOD. METHOD encode_tag. DATA: lv_string TYPE string, lv_time TYPE zcl_abapgit_git_time=>ty_unixtime. lv_time = zcl_abapgit_git_time=>get_unix( ). lv_string = |object { is_tag-object }{ cl_abap_char_utilities=>newline }| && |type { is_tag-type }{ cl_abap_char_utilities=>newline }| && |tag { zcl_abapgit_git_tag=>remove_tag_prefix( is_tag-tag ) }{ cl_abap_char_utilities=>newline }| && |tagger { is_tag-tagger_name } <{ is_tag-tagger_email }> { lv_time }| && |{ cl_abap_char_utilities=>newline }| && |{ cl_abap_char_utilities=>newline }| && |{ is_tag-message }|. rv_data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). ENDMETHOD. METHOD encode_tree. CONSTANTS: lc_null TYPE x VALUE '00'. DATA: lv_string TYPE string, lt_nodes LIKE it_nodes, lv_hex20 TYPE x LENGTH 20, lv_xstring TYPE xstring. FIELD-SYMBOLS: LIKE LINE OF it_nodes. lt_nodes = sort_tree( it_nodes ). LOOP AT lt_nodes ASSIGNING . ASSERT NOT -chmod IS INITIAL. ASSERT NOT -name IS INITIAL. ASSERT NOT -sha1 IS INITIAL. CONCATENATE -chmod -name INTO lv_string SEPARATED BY space. lv_xstring = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). lv_hex20 = to_upper( -sha1 ). CONCATENATE rv_data lv_xstring lc_null lv_hex20 INTO rv_data IN BYTE MODE. ENDLOOP. ENDMETHOD. METHOD get_length. * https://github.com/git/git/blob/master/Documentation/technical/pack-format.txt * n-byte sizeN (as long as MSB is set, each 7-bit) * size0..sizeN form 4+7+7+..+7 bit integer, size0 * is the least significant part, and sizeN is the * most significant part. DATA: lv_x TYPE x, lv_length_bits TYPE string, lv_bitbyte TYPE zif_abapgit_git_definitions=>ty_bitbyte. lv_x = cv_data(1). lv_bitbyte = zcl_abapgit_convert=>x_to_bitbyte( lv_x ). cv_data = cv_data+1. lv_length_bits = lv_bitbyte+4. WHILE lv_bitbyte(1) <> '0'. lv_x = cv_data(1). lv_bitbyte = zcl_abapgit_convert=>x_to_bitbyte( lv_x ). cv_data = cv_data+1. CONCATENATE lv_bitbyte+1 lv_length_bits INTO lv_length_bits. ENDWHILE. ev_length = zcl_abapgit_convert=>bitbyte_to_int( lv_length_bits ). ENDMETHOD. METHOD get_type. CONSTANTS: lc_mask TYPE x VALUE 112. DATA: lv_xtype TYPE x. lv_xtype = iv_x BIT-AND lc_mask. CASE lv_xtype. WHEN 16. rv_type = zif_abapgit_git_definitions=>c_type-commit. WHEN 32. rv_type = zif_abapgit_git_definitions=>c_type-tree. WHEN 48. rv_type = zif_abapgit_git_definitions=>c_type-blob. WHEN 64. rv_type = zif_abapgit_git_definitions=>c_type-tag. WHEN 112. rv_type = zif_abapgit_git_definitions=>c_type-ref_d. WHEN OTHERS. zcx_abapgit_exception=>raise( |Todo, unknown git pack type| ). ENDCASE. ENDMETHOD. METHOD sort_tree. TYPES: BEGIN OF ty_sort, sort TYPE string, node TYPE ty_node, END OF ty_sort. DATA: lt_sort TYPE STANDARD TABLE OF ty_sort WITH DEFAULT KEY. FIELD-SYMBOLS: LIKE LINE OF lt_sort, LIKE LINE OF it_nodes. LOOP AT it_nodes ASSIGNING . APPEND INITIAL LINE TO lt_sort ASSIGNING . IF -chmod = zif_abapgit_git_definitions=>c_chmod-dir. CONCATENATE -name '/' INTO -sort. ELSE. -sort = -name. ENDIF. -node = . ENDLOOP. * following has to be done, or unpack will fail on server side SORT lt_sort BY sort ASCENDING. LOOP AT lt_sort ASSIGNING . APPEND -node TO rt_nodes. ENDLOOP. ENDMETHOD. METHOD type_and_length. * see http://stefan.saasen.me/articles/git-clone-in-haskell-from-the-bottom-up/#pack_file_objects DATA: lv_type TYPE i, lv_length TYPE i, lv_hex TYPE x LENGTH 1. CASE iv_type. WHEN zif_abapgit_git_definitions=>c_type-commit. lv_type = 16. WHEN zif_abapgit_git_definitions=>c_type-tree. lv_type = 32. WHEN zif_abapgit_git_definitions=>c_type-blob. lv_type = 48. WHEN zif_abapgit_git_definitions=>c_type-tag. lv_type = 64. WHEN zif_abapgit_git_definitions=>c_type-ref_d. lv_type = 112. WHEN OTHERS. zcx_abapgit_exception=>raise( |Unexpected object type while encoding pack| ). ENDCASE. lv_length = iv_length. * first byte IF lv_length > 15. lv_hex = 128. ENDIF. lv_hex = lv_hex + lv_type + lv_length MOD 16. rv_xstring = lv_hex. lv_length = lv_length DIV 16. * subsequent bytes WHILE lv_length >= 128. lv_hex = 128 + lv_length MOD 128. CONCATENATE rv_xstring lv_hex INTO rv_xstring IN BYTE MODE. lv_length = lv_length DIV 128. ENDWHILE. * last byte IF lv_length > 0. lv_hex = lv_length. CONCATENATE rv_xstring lv_hex INTO rv_xstring IN BYTE MODE. ENDIF. ENDMETHOD. METHOD zlib_decompress. DATA: ls_data TYPE zcl_abapgit_zlib=>ty_decompress, lv_compressed_len TYPE i, lv_adler32 TYPE zif_abapgit_git_definitions=>ty_adler32. ls_data = zcl_abapgit_zlib=>decompress( cv_data ). lv_compressed_len = ls_data-compressed_len. cv_decompressed = ls_data-raw. IF lv_compressed_len IS INITIAL. zcx_abapgit_exception=>raise( |Decompression failed :o/| ). ENDIF. cv_data = cv_data+lv_compressed_len. lv_adler32 = zcl_abapgit_hash=>adler32( cv_decompressed ). IF cv_data(4) <> lv_adler32. cv_data = cv_data+1. ENDIF. IF cv_data(4) <> lv_adler32. cv_data = cv_data+1. ENDIF. IF cv_data(4) <> lv_adler32. zcx_abapgit_exception=>raise( |Wrong Adler checksum| ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_factory IMPLEMENTATION. METHOD get_v2_porcelain. CREATE OBJECT ri_v2 TYPE zcl_abapgit_gitv2_porcelain. ENDMETHOD. METHOD get_git_transport. IF gi_git_transport IS INITIAL. CREATE OBJECT gi_git_transport TYPE zcl_abapgit_git_transport. ENDIF. ri_git_transport = gi_git_transport. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_commit IMPLEMENTATION. METHOD extract_author_data. " Unix time stamps are in same time zone, so ignore the zone FIND REGEX zif_abapgit_definitions=>c_author_regex IN iv_author SUBMATCHES ev_author ev_email ev_time. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error author regex value='{ iv_author }'| ). ENDIF. ENDMETHOD. METHOD clear_missing_parents. "Part of #4719 to handle cut commit sequences, todo FIELD-SYMBOLS: TYPE zif_abapgit_git_definitions=>ty_commit. LOOP AT ct_commits ASSIGNING . IF is_missing( it_commits = ct_commits iv_sha1 = -parent1 ) = abap_true. CLEAR -parent1. ENDIF. IF is_missing( it_commits = ct_commits iv_sha1 = -parent2 ) = abap_true. CLEAR -parent2. ENDIF. ENDLOOP. ENDMETHOD. METHOD get_1st_child_commit. DATA: lt_1stchild_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt, ls_parent LIKE LINE OF it_commit_sha1s, lt_commit_sha1s LIKE it_commit_sha1s. FIELD-SYMBOLS: TYPE zif_abapgit_git_definitions=>ty_commit. CLEAR: es_1st_commit. * get all reachable next commits lt_commit_sha1s = it_commit_sha1s. LOOP AT ct_commits ASSIGNING WHERE parent1 IN lt_commit_sha1s OR parent2 IN lt_commit_sha1s. INSERT INTO TABLE lt_1stchild_commits. ENDLOOP. * return oldest one SORT lt_1stchild_commits BY time ASCENDING. READ TABLE lt_1stchild_commits INTO es_1st_commit INDEX 1. * remove from available commits DELETE ct_commits WHERE sha1 = es_1st_commit-sha1. * set relevant parent commit sha1s IF lines( lt_1stchild_commits ) = 1. CLEAR et_commit_sha1s. ELSE. et_commit_sha1s = it_commit_sha1s. ENDIF. ls_parent-sign = 'I'. ls_parent-option = 'EQ'. ls_parent-low = es_1st_commit-sha1. INSERT ls_parent INTO TABLE et_commit_sha1s. ENDMETHOD. METHOD get_by_branch. DATA: li_progress TYPE REF TO zif_abapgit_progress, lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. li_progress = zcl_abapgit_progress=>get_instance( 1 ). li_progress->show( iv_current = 1 iv_text = |Get git commits { iv_repo_url }| ). zcl_abapgit_git_transport=>upload_pack_by_branch( EXPORTING iv_url = iv_repo_url iv_branch_name = iv_branch_name iv_deepen_level = iv_deepen_level IMPORTING ev_branch = rs_pull_result-commit et_objects = lt_objects ). DELETE lt_objects WHERE type <> zif_abapgit_git_definitions=>c_type-commit. rs_pull_result-commits = parse_commits( lt_objects ). IF iv_sorted = abap_true. sort_commits( CHANGING ct_commits = rs_pull_result-commits ). ENDIF. ENDMETHOD. METHOD get_by_commit. DATA: li_progress TYPE REF TO zif_abapgit_progress, lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. li_progress = zcl_abapgit_progress=>get_instance( 1 ). li_progress->show( iv_current = 1 iv_text = |Get git commits { iv_repo_url }| ). zcl_abapgit_git_transport=>upload_pack_by_commit( EXPORTING iv_url = iv_repo_url iv_deepen_level = iv_deepen_level iv_hash = iv_commit_hash IMPORTING et_objects = lt_objects ). DELETE lt_objects WHERE type <> zif_abapgit_git_definitions=>c_type-commit. rt_commits = parse_commits( lt_objects ). sort_commits( CHANGING ct_commits = rt_commits ). ENDMETHOD. METHOD is_missing. IF iv_sha1 IS NOT INITIAL. READ TABLE it_commits TRANSPORTING NO FIELDS WITH KEY sha1 = iv_sha1. rv_result = boolc( sy-subrc <> 0 ). ENDIF. ENDMETHOD. METHOD parse_commits. DATA: ls_commit TYPE zif_abapgit_git_definitions=>ty_commit, lt_body TYPE STANDARD TABLE OF string WITH DEFAULT KEY, ls_raw TYPE zcl_abapgit_git_pack=>ty_commit. FIELD-SYMBOLS: LIKE LINE OF it_objects, TYPE string. LOOP AT it_objects ASSIGNING USING KEY type WHERE type = zif_abapgit_git_definitions=>c_type-commit. ls_raw = zcl_abapgit_git_pack=>decode_commit( -data ). CLEAR ls_commit. ls_commit-sha1 = -sha1. ls_commit-parent1 = ls_raw-parent. ls_commit-parent2 = ls_raw-parent2. SPLIT ls_raw-body AT cl_abap_char_utilities=>newline INTO TABLE lt_body. READ TABLE lt_body WITH KEY table_line = ' -----END PGP SIGNATURE-----' TRANSPORTING NO FIELDS. IF sy-subrc = 0. DELETE lt_body TO sy-tabix. DELETE lt_body TO 2. ENDIF. READ TABLE lt_body INDEX 1 INTO ls_commit-message. "#EC CI_SUBRC " The second line is always empty. Therefore we omit it. LOOP AT lt_body ASSIGNING FROM 3. INSERT INTO TABLE ls_commit-body. ENDLOOP. extract_author_data( EXPORTING iv_author = ls_raw-author IMPORTING ev_author = ls_commit-author ev_email = ls_commit-email ev_time = ls_commit-time ). APPEND ls_commit TO rt_commits. ENDLOOP. ENDMETHOD. METHOD reverse_sort_order. DATA: lt_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt. FIELD-SYMBOLS: TYPE zif_abapgit_git_definitions=>ty_commit. LOOP AT ct_commits ASSIGNING . INSERT INTO lt_commits INDEX 1. ENDLOOP. ct_commits = lt_commits. FREE lt_commits. ENDMETHOD. METHOD sort_commits. DATA: lt_sorted_commits TYPE zif_abapgit_git_definitions=>ty_commit_tt, ls_next_commit TYPE zif_abapgit_git_definitions=>ty_commit, lt_parents TYPE ty_sha1_range, ls_parent LIKE LINE OF lt_parents. FIELD-SYMBOLS: TYPE zif_abapgit_git_definitions=>ty_commit. " find initial commit READ TABLE ct_commits ASSIGNING WITH KEY parent1 = space. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Cannot find initial commit. Too many commits. Action not possible.| ). ENDIF. ls_parent-sign = 'I'. ls_parent-option = 'EQ'. ls_parent-low = -sha1. INSERT ls_parent INTO TABLE lt_parents. " first commit INSERT INTO TABLE lt_sorted_commits. " remove from available commits DELETE ct_commits WHERE sha1 = -sha1. DO. get_1st_child_commit( EXPORTING it_commit_sha1s = lt_parents IMPORTING et_commit_sha1s = lt_parents es_1st_commit = ls_next_commit CHANGING ct_commits = ct_commits ). IF ls_next_commit IS INITIAL. EXIT. "DO ENDIF. INSERT ls_next_commit INTO TABLE lt_sorted_commits. ENDDO. ct_commits = lt_sorted_commits. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_git_branch_list IMPLEMENTATION. METHOD complete_heads_branch_name. IF iv_branch_name CP zif_abapgit_git_definitions=>c_git_branch-heads. rv_name = iv_branch_name. ELSE. rv_name = zif_abapgit_git_definitions=>c_git_branch-heads_prefix && iv_branch_name. ENDIF. ENDMETHOD. METHOD constructor. parse_branch_list( EXPORTING iv_data = iv_data IMPORTING et_list = mt_branches ev_head_symref = mv_head_symref ). ENDMETHOD. METHOD find_by_name. IF iv_branch_name IS INITIAL. zcx_abapgit_exception=>raise( 'Branch name empty' ). ENDIF. IF iv_branch_name CP zif_abapgit_git_definitions=>c_git_branch-tags. rs_branch = find_tag_by_name( iv_branch_name ). ELSE. READ TABLE mt_branches INTO rs_branch WITH TABLE KEY name_key COMPONENTS name = iv_branch_name. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |{ get_description( iv_branch_name ) } not found| ). ENDIF. ENDIF. ENDMETHOD. METHOD find_tag_by_name. READ TABLE mt_branches INTO rs_branch WITH TABLE KEY name_key COMPONENTS name = zcl_abapgit_git_tag=>add_peel( iv_branch_name ). IF sy-subrc <> 0. READ TABLE mt_branches INTO rs_branch WITH TABLE KEY name_key COMPONENTS name = iv_branch_name. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |{ get_description( iv_branch_name ) } not found| ). ENDIF. ENDIF. ENDMETHOD. METHOD get_all. rt_branches = mt_branches. ENDMETHOD. METHOD get_branches_only. FIELD-SYMBOLS LIKE LINE OF mt_branches. LOOP AT mt_branches ASSIGNING . IF -type = zif_abapgit_git_definitions=>c_git_branch_type-branch. APPEND TO rt_branches. ENDIF. ENDLOOP. ENDMETHOD. METHOD get_description. CASE get_type( iv_branch_name ). WHEN zif_abapgit_git_definitions=>c_git_branch_type-branch. rv_description = 'Branch'. WHEN zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. rv_description = 'Tag'. WHEN zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. rv_description = 'Annotated Tag'. WHEN OTHERS. rv_description = 'Branch'. ENDCASE. rv_description = |{ rv_description } "{ get_display_name( iv_branch_name ) }"|. ENDMETHOD. METHOD get_display_name. rv_display_name = iv_branch_name. IF rv_display_name CP zif_abapgit_git_definitions=>c_git_branch-heads. REPLACE FIRST OCCURRENCE OF zif_abapgit_git_definitions=>c_git_branch-heads_prefix IN rv_display_name WITH ''. ELSEIF rv_display_name CP zif_abapgit_git_definitions=>c_git_branch-tags. rv_display_name = zcl_abapgit_git_tag=>remove_tag_prefix( zcl_abapgit_git_tag=>remove_peel( rv_display_name ) ). ENDIF. ENDMETHOD. METHOD get_head_symref. rv_head_symref = mv_head_symref. ENDMETHOD. METHOD get_tags_only. FIELD-SYMBOLS LIKE LINE OF mt_branches. LOOP AT mt_branches ASSIGNING WHERE type = zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag OR type = zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. APPEND TO rt_tags. ENDLOOP. ENDMETHOD. METHOD get_type. FIELD-SYMBOLS: TYPE LINE OF string_table. rv_type = zif_abapgit_git_definitions=>c_git_branch_type-other. IF iv_branch_name CP zif_abapgit_git_definitions=>c_git_branch-heads OR iv_branch_name = zif_abapgit_git_definitions=>c_head_name. rv_type = zif_abapgit_git_definitions=>c_git_branch_type-branch. ELSEIF iv_branch_name CP zif_abapgit_git_definitions=>c_git_branch-tags. READ TABLE it_result ASSIGNING INDEX iv_current_row_index + 1. IF sy-subrc = 0 AND CP '*' && zcl_abapgit_git_tag=>add_peel( iv_branch_name ). rv_type = zif_abapgit_git_definitions=>c_git_branch_type-annotated_tag. ELSE. rv_type = zif_abapgit_git_definitions=>c_git_branch_type-lightweight_tag. ENDIF. ENDIF. ENDMETHOD. METHOD normalize_branch_name. rv_name = iv_branch_name. " Force convert to string REPLACE ALL OCCURRENCES OF ` ` IN rv_name WITH '-'. " Disallow space in branch name ENDMETHOD. METHOD parse_branch_list. DATA: lt_result TYPE TABLE OF string, lv_hash TYPE zif_abapgit_git_definitions=>ty_sha1, lv_name TYPE string, lv_head_params TYPE string, lv_char TYPE c, lv_data LIKE LINE OF lt_result, lv_current_row_index TYPE syst-tabix. FIELD-SYMBOLS: LIKE LINE OF et_list. CLEAR: et_list, ev_head_symref. lv_data = skip_first_pkt( iv_data ). SPLIT lv_data AT cl_abap_char_utilities=>newline INTO TABLE lt_result. LOOP AT lt_result INTO lv_data. lv_current_row_index = sy-tabix. IF sy-tabix = 1 AND strlen( lv_data ) > 12 AND lv_data(4) = '0000' AND lv_data+8(3) = 'ERR'. lv_name = lv_data+8. zcx_abapgit_exception=>raise( lv_name ). ELSEIF sy-tabix = 1 AND strlen( lv_data ) > 49. lv_hash = lv_data+8. lv_name = lv_data+49. lv_char = zcl_abapgit_git_utils=>get_null( ). SPLIT lv_name AT lv_char INTO lv_name lv_head_params. ev_head_symref = parse_head_params( lv_head_params ). IF ev_head_symref IS INITIAL AND lv_name CS 'refs/heads/'. ev_head_symref = lv_name. ENDIF. ELSEIF sy-tabix > 1 AND strlen( lv_data ) > 45. lv_hash = lv_data+4. lv_name = lv_data+45. ELSEIF sy-tabix = 1 AND strlen( lv_data ) = 8 AND lv_data(8) = '00000000'. zcx_abapgit_exception=>raise( 'No branches, create branch manually by adding file' ). ELSE. CONTINUE. ENDIF. ASSERT lv_name IS NOT INITIAL. APPEND INITIAL LINE TO et_list ASSIGNING . -sha1 = lv_hash. -name = lv_name. -display_name = get_display_name( lv_name ). -type = get_type( iv_branch_name = lv_name it_result = lt_result iv_current_row_index = lv_current_row_index ). IF -name = zif_abapgit_git_definitions=>c_head_name OR -name = ev_head_symref. -is_head = abap_true. ENDIF. ENDLOOP. ENDMETHOD. METHOD parse_head_params. DATA: ls_match TYPE match_result, ls_submatch LIKE LINE OF ls_match-submatches. FIND FIRST OCCURRENCE OF REGEX '\ssymref=HEAD:([^\s]+)' IN iv_data RESULTS ls_match. READ TABLE ls_match-submatches INTO ls_submatch INDEX 1. IF sy-subrc IS INITIAL. rv_head_symref = iv_data+ls_submatch-offset(ls_submatch-length). ENDIF. ENDMETHOD. METHOD skip_first_pkt. DATA: lv_hex TYPE x LENGTH 1, lv_length TYPE i. * channel ASSERT iv_data(2) = '00'. lv_hex = to_upper( iv_data+2(2) ). lv_length = lv_hex. rv_data = iv_data+lv_length. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GIT_ADD_PATCH IMPLEMENTATION. METHOD calculate_patch. FIELD-SYMBOLS: LIKE LINE OF mt_diff. LOOP AT mt_diff ASSIGNING . CASE -result. WHEN zif_abapgit_definitions=>c_diff-unchanged. INSERT -old INTO TABLE rt_patch. WHEN zif_abapgit_definitions=>c_diff-insert. IF -patch_flag = abap_true. INSERT -new INTO TABLE rt_patch. ENDIF. WHEN zif_abapgit_definitions=>c_diff-delete. IF -patch_flag = abap_false. INSERT -old INTO TABLE rt_patch. ENDIF. WHEN zif_abapgit_definitions=>c_diff-update. IF -patch_flag = abap_true. INSERT -new INTO TABLE rt_patch. ELSE. INSERT -old INTO TABLE rt_patch. ENDIF. WHEN OTHERS. zcx_abapgit_exception=>raise( |Unknown result| ). ENDCASE. ENDLOOP. ENDMETHOD. METHOD constructor. mt_diff = it_diff. ENDMETHOD. METHOD get_patch. IF mt_patch IS INITIAL. mt_patch = calculate_patch( ). ENDIF. rt_patch = mt_patch. ENDMETHOD. METHOD get_patch_binary. DATA: lv_string TYPE string. IF mt_patch IS INITIAL. mt_patch = calculate_patch( ). ENDIF. CONCATENATE LINES OF mt_patch INTO lv_string SEPARATED BY cl_abap_char_utilities=>newline. lv_string = lv_string && cl_abap_char_utilities=>newline. rv_patch_binary = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_GITV2_PORCELAIN IMPLEMENTATION. METHOD decode_pack. DATA lv_xstring TYPE xstring. DATA lv_contents TYPE xstring. DATA lv_pack TYPE xstring. DATA lv_pktlen TYPE i. DATA lv_hex4 TYPE xstring. lv_xstring = iv_xstring. * The data transfer of the packfile is always multiplexed, using the same semantics of the * side-band-64k capability from protocol version 1 WHILE xstrlen( lv_xstring ) > 0. lv_hex4 = lv_xstring(4). lv_pktlen = zcl_abapgit_git_utils=>length_utf8_hex( lv_hex4 ). IF lv_pktlen = 0. EXIT. ELSEIF lv_pktlen = 1. * its a delimiter package lv_xstring = lv_xstring+4. CONTINUE. ENDIF. lv_contents = lv_xstring(lv_pktlen). IF lv_contents+4(1) = '01'. CONCATENATE lv_pack lv_contents+5 INTO lv_pack IN BYTE MODE. ENDIF. lv_xstring = lv_xstring+lv_pktlen. ENDWHILE. rt_objects = zcl_abapgit_git_pack=>decode( lv_pack ). ENDMETHOD. METHOD send_command. CONSTANTS lc_content_regex TYPE string VALUE '^[0-9a-f]{4}#'. DATA lo_client TYPE REF TO zcl_abapgit_http_client. DATA lv_cmd_pkt TYPE string. DATA lt_headers TYPE zcl_abapgit_http=>ty_headers. DATA ls_header LIKE LINE OF lt_headers. DATA lv_argument TYPE string. ls_header-key = 'Git-Protocol'. ls_header-value = 'version=2'. APPEND ls_header TO lt_headers. lo_client = zcl_abapgit_http=>create_by_url( iv_url = iv_url iv_service = c_service-upload it_headers = lt_headers ). lo_client->check_smart_response( iv_expected_content_type = |application/x-git-{ iv_service }-pack-advertisement| iv_content_regex = lc_content_regex ). lv_cmd_pkt = zcl_abapgit_git_utils=>pkt_string( |command={ iv_command }\n| ) && zcl_abapgit_git_utils=>pkt_string( |agent={ zcl_abapgit_http=>get_agent( ) }\n| ). IF lines( it_arguments ) > 0. lv_cmd_pkt = lv_cmd_pkt && c_delim_pkt. LOOP AT it_arguments INTO lv_argument. lv_cmd_pkt = lv_cmd_pkt && zcl_abapgit_git_utils=>pkt_string( lv_argument ). ENDLOOP. ENDIF. lv_cmd_pkt = lv_cmd_pkt && c_flush_pkt. lo_client->set_header( iv_key = '~request_uri' iv_value = zcl_abapgit_url=>path_name( iv_url ) && |/git-{ iv_service }-pack| ). lo_client->set_header( iv_key = '~request_method' iv_value = 'POST' ). lo_client->set_header( iv_key = 'Content-Type' iv_value = |application/x-git-{ iv_service }-pack-request| ). lo_client->set_header( iv_key = 'Accept' iv_value = |application/x-git-{ iv_service }-pack-result| ). rv_response = lo_client->send_receive_close( zcl_abapgit_convert=>string_to_xstring_utf8( lv_cmd_pkt ) ). ENDMETHOD. METHOD zif_abapgit_gitv2_porcelain~commits_last_year. DATA lv_xstring TYPE xstring. DATA lt_arguments TYPE string_table. DATA lv_argument TYPE string. DATA lv_sha1 LIKE LINE OF it_sha1. ASSERT lines( it_sha1 ) > 0. lv_argument = |deepen-since { zcl_abapgit_git_time=>get_one_year_ago( ) }|. APPEND lv_argument TO lt_arguments. LOOP AT it_sha1 INTO lv_sha1. lv_argument = |want { lv_sha1 }|. APPEND lv_argument TO lt_arguments. ENDLOOP. * 'filter object:type=commit' doesn't work on github APPEND 'filter blob:none' TO lt_arguments. APPEND 'no-progress' TO lt_arguments. APPEND 'done' TO lt_arguments. lv_xstring = send_command( iv_url = iv_url iv_service = c_service-upload iv_command = |fetch| it_arguments = lt_arguments ). rt_objects = decode_pack( lv_xstring ). DELETE rt_objects WHERE type <> zif_abapgit_git_definitions=>c_type-commit. ENDMETHOD. METHOD zif_abapgit_gitv2_porcelain~list_branches. DATA lv_xstring TYPE xstring. DATA lt_arguments TYPE string_table. DATA lv_argument TYPE string. DATA lv_data TYPE string. IF iv_prefix IS NOT INITIAL. lv_argument = |ref-prefix { iv_prefix }|. APPEND lv_argument TO lt_arguments. ENDIF. lv_xstring = send_command( iv_url = iv_url iv_service = c_service-upload iv_command = |ls-refs| it_arguments = lt_arguments ). " add dummy packet so the v1 branch parsing can be reused lv_data = |0004\n{ zcl_abapgit_convert=>xstring_to_string_utf8( lv_xstring ) }|. CREATE OBJECT ro_list EXPORTING iv_data = lv_data. ENDMETHOD. METHOD zif_abapgit_gitv2_porcelain~list_no_blobs. DATA lt_sha1 TYPE zif_abapgit_git_definitions=>ty_sha1_tt. DATA lt_objects TYPE zif_abapgit_definitions=>ty_objects_tt. ASSERT iv_sha1 IS NOT INITIAL. APPEND iv_sha1 TO lt_sha1. lt_objects = zif_abapgit_gitv2_porcelain~list_no_blobs_multi( iv_url = iv_url it_sha1 = lt_sha1 ). rt_expanded = zcl_abapgit_git_porcelain=>full_tree( it_objects = lt_objects iv_parent = iv_sha1 ). ENDMETHOD. METHOD zif_abapgit_gitv2_porcelain~list_no_blobs_multi. DATA lv_xstring TYPE xstring. DATA lt_arguments TYPE string_table. DATA lv_argument TYPE string. DATA lv_sha1 LIKE LINE OF it_sha1. ASSERT lines( it_sha1 ) > 0. APPEND 'deepen 1' TO lt_arguments. LOOP AT it_sha1 INTO lv_sha1. lv_argument = |want { lv_sha1 }|. APPEND lv_argument TO lt_arguments. ENDLOOP. APPEND 'filter blob:none' TO lt_arguments. APPEND 'no-progress' TO lt_arguments. APPEND 'done' TO lt_arguments. lv_xstring = send_command( iv_url = iv_url iv_service = c_service-upload iv_command = |fetch| it_arguments = lt_arguments ). rt_objects = decode_pack( lv_xstring ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_exit IMPLEMENTATION. METHOD get_instance. DATA lv_class_name TYPE string. IF gi_global_exit IS NOT INITIAL. ri_exit = gi_global_exit. RETURN. ENDIF. lv_class_name = 'ZCL_ABAPGIT_USER_EXIT'. IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. " Prevent accidental usage of exit handlers in the developer version lv_class_name = |\\PROGRAM={ sy-repid }\\CLASS={ lv_class_name }|. ENDIF. " Prevent non-mocked exit calls in unit tests IF is_running_in_test_context( ) = abap_false. TRY. CREATE OBJECT gi_exit TYPE (lv_class_name). CATCH cx_sy_create_object_error ##NO_HANDLER. ENDTRY. ENDIF. CREATE OBJECT gi_global_exit TYPE zcl_abapgit_exit. " this class ri_exit = gi_global_exit. ENDMETHOD. METHOD is_running_in_test_context. IF sy-sysid = 'ABC'. " always run on open-abap rv_running_in_test_context = abap_true. RETURN. ENDIF. " Check if the local test class can be accessed by RTTI. If so the current process is running in a unit test. " Note this approach only works for the developer version. The standalone version will always report not running in " test context which should be fine as there are no unit tests delivered in it. cl_abap_typedescr=>describe_by_name( EXPORTING p_name = |\\PROGRAM={ sy-repid }\\CLASS=LTCL_TEST| EXCEPTIONS type_not_found = 1 OTHERS = 2 ). rv_running_in_test_context = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD zif_abapgit_exit~adjust_display_commit_url. IF gi_exit IS NOT INITIAL. TRY. gi_exit->adjust_display_commit_url( EXPORTING iv_repo_url = iv_repo_url iv_repo_name = iv_repo_name iv_repo_key = iv_repo_key iv_commit_hash = iv_commit_hash CHANGING cv_display_url = cv_display_url ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~adjust_display_filename. IF gi_exit IS NOT INITIAL. TRY. rv_filename = gi_exit->adjust_display_filename( is_repo_meta = is_repo_meta iv_filename = iv_filename ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. IF rv_filename IS INITIAL. rv_filename = iv_filename. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~allow_sap_objects. IF gi_exit IS NOT INITIAL. TRY. rv_allowed = gi_exit->allow_sap_objects( ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~change_local_host. IF gi_exit IS NOT INITIAL. TRY. gi_exit->change_local_host( CHANGING ct_hosts = ct_hosts ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~change_max_parallel_processes. IF gi_exit IS NOT INITIAL. TRY. gi_exit->change_max_parallel_processes( EXPORTING iv_package = iv_package CHANGING cv_max_processes = cv_max_processes ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~change_proxy_authentication. IF gi_exit IS NOT INITIAL. TRY. gi_exit->change_proxy_authentication( EXPORTING iv_repo_url = iv_repo_url CHANGING cv_proxy_authentication = cv_proxy_authentication ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~change_proxy_port. IF gi_exit IS NOT INITIAL. TRY. gi_exit->change_proxy_port( EXPORTING iv_repo_url = iv_repo_url CHANGING cv_proxy_port = cv_proxy_port ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~change_proxy_url. IF gi_exit IS NOT INITIAL. TRY. gi_exit->change_proxy_url( EXPORTING iv_repo_url = iv_repo_url CHANGING cv_proxy_url = cv_proxy_url ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~change_rfc_server_group. IF gi_exit IS NOT INITIAL. TRY. gi_exit->change_rfc_server_group( CHANGING cv_group = cv_group ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~change_supported_data_objects. IF gi_exit IS NOT INITIAL. TRY. gi_exit->change_supported_data_objects( CHANGING ct_objects = ct_objects ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~change_supported_object_types. IF gi_exit IS NOT INITIAL. TRY. gi_exit->change_supported_object_types( CHANGING ct_types = ct_types ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~change_tadir. IF gi_exit IS NOT INITIAL. TRY. gi_exit->change_tadir( EXPORTING iv_package = iv_package ii_log = ii_log is_dot_abapgit = is_dot_abapgit iv_ignore_subpackages = iv_ignore_subpackages iv_only_local_objects = iv_only_local_objects CHANGING ct_tadir = ct_tadir ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~create_http_client. IF gi_exit IS NOT INITIAL. TRY. ri_client = gi_exit->create_http_client( iv_url ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~custom_serialize_abap_clif. " This exit might be called twice per object " 1st call: it_source = initial " Can be used for serializing complete source " If source is returned, there will be no second call " 2nd call: it_source = code as serialized by abapGit " Can be used for post-processing of source IF gi_exit IS NOT INITIAL. TRY. rt_source = gi_exit->custom_serialize_abap_clif( is_class_key = is_class_key it_source = it_source ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. IF rt_source IS INITIAL. rt_source = it_source. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~deserialize_postprocess. IF gi_exit IS NOT INITIAL. TRY. gi_exit->deserialize_postprocess( is_step = is_step ii_log = ii_log ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~determine_transport_request. IF gi_exit IS NOT INITIAL. TRY. gi_exit->determine_transport_request( EXPORTING io_repo = io_repo iv_transport_type = iv_transport_type CHANGING cv_transport_request = cv_transport_request ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~enhance_repo_toolbar. IF gi_exit IS NOT INITIAL. TRY. gi_exit->enhance_repo_toolbar( io_menu = io_menu iv_key = iv_key iv_act = iv_act ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~get_ci_tests. IF gi_exit IS NOT INITIAL. TRY. gi_exit->get_ci_tests( EXPORTING iv_object = iv_object CHANGING ct_ci_repos = ct_ci_repos ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~get_ssl_id. IF gi_exit IS NOT INITIAL. TRY. rv_ssl_id = gi_exit->get_ssl_id( ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. IF rv_ssl_id IS INITIAL. rv_ssl_id = 'ANONYM'. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~http_client. IF gi_exit IS NOT INITIAL. TRY. gi_exit->http_client( iv_url = iv_url ii_client = ii_client ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~on_event. IF gi_exit IS NOT INITIAL. TRY. rs_handled = gi_exit->on_event( ii_event ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~pre_calculate_repo_status. IF gi_exit IS NOT INITIAL. TRY. gi_exit->pre_calculate_repo_status( EXPORTING is_repo_meta = is_repo_meta CHANGING ct_local = ct_local ct_remote = ct_remote ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~serialize_postprocess. IF gi_exit IS NOT INITIAL. TRY. gi_exit->serialize_postprocess( EXPORTING iv_package = iv_package ii_log = ii_log CHANGING ct_files = ct_files ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~validate_before_push. IF gi_exit IS NOT INITIAL. TRY. gi_exit->validate_before_push( is_comment = is_comment io_stage = io_stage io_repo = io_repo ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~wall_message_list. IF gi_exit IS NOT INITIAL. TRY. gi_exit->wall_message_list( ii_html ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. METHOD zif_abapgit_exit~wall_message_repo. IF gi_exit IS NOT INITIAL. TRY. gi_exit->wall_message_repo( is_repo_meta = is_repo_meta ii_html = ii_html ). CATCH cx_sy_ref_is_initial cx_sy_dyn_call_illegal_method ##NO_HANDLER. ENDTRY. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_auth IMPLEMENTATION. METHOD is_allowed. DATA: li_auth TYPE REF TO zif_abapgit_auth. TRY. CREATE OBJECT li_auth TYPE ('ZCL_ABAPGIT_AUTH_EXIT'). rv_allowed = li_auth->is_allowed( iv_authorization = iv_authorization iv_param = iv_param ). CATCH cx_sy_create_object_error. rv_allowed = abap_true. ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_user_record IMPLEMENTATION. METHOD get_title. * the queried username might not exist, so this method is static DATA ls_user_address TYPE addr3_val. CALL FUNCTION 'SUSR_USER_ADDRESS_READ' EXPORTING user_name = iv_username IMPORTING user_address = ls_user_address EXCEPTIONS user_address_not_found = 1 OTHERS = 2. IF sy-subrc = 0. rv_title = ls_user_address-name_text. ENDIF. ENDMETHOD. METHOD check_user_exists. DATA lt_return TYPE STANDARD TABLE OF bapiret2 WITH DEFAULT KEY. DATA ls_address TYPE bapiaddr3. DATA lt_smtp TYPE TABLE OF bapiadsmtp. DATA ls_smtp LIKE LINE OF lt_smtp. CALL FUNCTION 'BAPI_USER_GET_DETAIL' EXPORTING username = iv_user IMPORTING address = ls_address TABLES return = lt_return addsmtp = lt_smtp. LOOP AT lt_return TRANSPORTING NO FIELDS WHERE type CA 'EA'. zcx_abapgit_exception=>raise( |User: { iv_user } not found| ). ENDLOOP. ev_fullname = ls_address-fullname. " Choose the first email from SU01 SORT lt_smtp BY consnumber ASCENDING. LOOP AT lt_smtp INTO ls_smtp. ev_email = ls_smtp-e_mail. EXIT. ENDLOOP. ENDMETHOD. METHOD constructor. DATA ls_user TYPE ty_user. " Get user details TRY. check_user_exists( EXPORTING iv_user = iv_user IMPORTING ev_fullname = ms_user-name ev_email = ms_user-email ). CATCH zcx_abapgit_exception. " Could not find user, try to get from other clients get_user_dtls_from_other_clnt( iv_user ). ENDTRY. " If the user has been found add it to the list IF ms_user-name IS NOT INITIAL AND ms_user-email IS NOT INITIAL. ls_user-user = iv_user. ls_user-o_user = me. INSERT ls_user INTO TABLE gt_user. ENDIF. ENDMETHOD. METHOD get_email. rv_email = ms_user-email. ENDMETHOD. METHOD get_instance. FIELD-SYMBOLS TYPE ty_user. READ TABLE gt_user ASSIGNING WITH TABLE KEY user = iv_user. IF sy-subrc = 0. ro_user = -o_user. ELSE. CREATE OBJECT ro_user EXPORTING iv_user = iv_user. ENDIF. ENDMETHOD. METHOD get_name. rv_name = ms_user-name. ENDMETHOD. METHOD get_user_dtls_from_other_clnt. CONSTANTS lc_cc_category TYPE string VALUE 'C'. TYPES ty_dev_clients TYPE SORTED TABLE OF sy-mandt WITH UNIQUE KEY table_line. DATA lt_dev_clients TYPE ty_dev_clients. FIELD-SYMBOLS LIKE LINE OF lt_dev_clients. " Could not find the user, try other development clients SELECT mandt FROM t000 INTO TABLE lt_dev_clients WHERE cccategory = lc_cc_category AND mandt <> sy-mandt ORDER BY PRIMARY KEY. LOOP AT lt_dev_clients ASSIGNING . SELECT SINGLE p~name_text a~smtp_addr INTO (ms_user-name, ms_user-email) FROM usr21 AS u INNER JOIN adrp AS p ON p~persnumber = u~persnumber AND p~client = u~mandt INNER JOIN adr6 AS a ON a~persnumber = u~persnumber AND a~addrnumber = u~addrnumber AND a~client = u~mandt CLIENT SPECIFIED WHERE u~mandt = AND u~bname = iv_user AND p~date_from <= sy-datum AND p~date_to >= sy-datum AND a~date_from <= sy-datum. IF sy-subrc = 0. EXIT. ENDIF. ENDLOOP. ENDMETHOD. METHOD reset. CLEAR gt_user. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_settings IMPLEMENTATION. METHOD get_activate_wo_popup. rv_act_wo_popup = ms_user_settings-activate_wo_popup. ENDMETHOD. METHOD get_adt_jump_enabled. rv_adt_jump_enabled = ms_user_settings-adt_jump_enabled. ENDMETHOD. METHOD get_commitmsg_body_size. rv_length = ms_settings-commitmsg_body_size. ENDMETHOD. METHOD get_commitmsg_comment_default. rv_default = ms_settings-commitmsg_comment_deflt. ENDMETHOD. METHOD get_commitmsg_comment_length. rv_length = ms_settings-commitmsg_comment_length. ENDMETHOD. METHOD get_commitmsg_hide_author. rv_hide_author = ms_settings-commitmsg_hide_author. ENDMETHOD. METHOD get_experimental_features. IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. rv_features = ms_settings-experimental_features. ENDIF. ENDMETHOD. METHOD get_icon_scaling. rv_scaling = ms_user_settings-icon_scaling. ENDMETHOD. METHOD get_link_hints_enabled. rv_link_hints_enabled = ms_user_settings-link_hints_enabled. ENDMETHOD. METHOD get_link_hint_key. rv_link_hint_key = ms_user_settings-link_hint_key. ENDMETHOD. METHOD get_max_lines. rv_lines = ms_user_settings-max_lines. ENDMETHOD. METHOD get_parallel_proc_disabled. rv_disable_parallel_proc = ms_user_settings-parallel_proc_disabled. ENDMETHOD. METHOD get_proxy_authentication. rv_auth = ms_settings-proxy_auth. ENDMETHOD. METHOD get_proxy_bypass. rt_bypass = ms_settings-proxy_bypass. ENDMETHOD. METHOD get_proxy_port. rv_port = ms_settings-proxy_port. ENDMETHOD. METHOD get_proxy_url. rv_proxy_url = ms_settings-proxy_url. ENDMETHOD. METHOD get_run_critical_tests. IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_false. rv_run = ms_settings-run_critical_tests. ENDIF. ENDMETHOD. METHOD get_settings_xml. DATA: li_output TYPE REF TO zif_abapgit_xml_output. CREATE OBJECT li_output TYPE zcl_abapgit_xml_output. li_output->add( iv_name = zcl_abapgit_persistence_db=>c_type_settings ig_data = ms_settings ). rv_settings_xml = li_output->render( ). ENDMETHOD. METHOD get_show_default_repo. rv_show_default_repo = ms_user_settings-show_default_repo. ENDMETHOD. METHOD get_ui_theme. DATA lv_frontend_theme TYPE string. DATA lv_cl_gui TYPE string. lv_cl_gui = 'CL_GUI_RESOURCES'. rv_ui_theme = ms_user_settings-ui_theme. IF rv_ui_theme = c_ui_theme-synced_with_gui AND iv_resolve_synced = abap_true. TRY. CALL METHOD (lv_cl_gui)=>get_themename IMPORTING themename = lv_frontend_theme EXCEPTIONS get_std_resource_error = 1 OTHERS = 2. IF sy-subrc <> 0. rv_ui_theme = c_ui_theme-default. RETURN. ENDIF. CATCH cx_sy_dyn_call_error. rv_ui_theme = c_ui_theme-default. RETURN. ENDTRY. CASE lv_frontend_theme. WHEN 'Belize'. rv_ui_theme = c_ui_theme-belize. WHEN OTHERS. rv_ui_theme = c_ui_theme-default. ENDCASE. ENDIF. ENDMETHOD. METHOD get_user_settings. rs_settings = ms_user_settings. ENDMETHOD. METHOD set_activate_wo_popup. ms_user_settings-activate_wo_popup = iv_act_wo_popup. ENDMETHOD. METHOD set_adt_jump_enanbled. ms_user_settings-adt_jump_enabled = iv_adt_jump_enabled. ENDMETHOD. METHOD set_commitmsg_body_size. ms_settings-commitmsg_body_size = iv_length. ENDMETHOD. METHOD set_commitmsg_comment_default. ms_settings-commitmsg_comment_deflt = iv_default. ENDMETHOD. METHOD set_commitmsg_comment_length. ms_settings-commitmsg_comment_length = iv_length. ENDMETHOD. METHOD set_commitmsg_hide_author. ms_settings-commitmsg_hide_author = iv_hide_author. ENDMETHOD. METHOD set_defaults. CLEAR ms_settings. set_proxy_authentication( abap_false ). set_run_critical_tests( abap_false ). set_experimental_features( '' ). set_max_lines( 500 ). set_adt_jump_enanbled( abap_true ). set_show_default_repo( abap_false ). set_commitmsg_comment_length( c_commitmsg_comment_length_dft ). set_commitmsg_body_size( c_commitmsg_body_size_dft ). set_default_link_hint_key( ). set_icon_scaling( '' ). ENDMETHOD. METHOD set_default_link_hint_key. " Since #5859 'f' is used for "focus filter", we use 't' as the new default set_link_hint_key( |t| ). ENDMETHOD. METHOD set_experimental_features. ms_settings-experimental_features = iv_features. ENDMETHOD. METHOD set_icon_scaling. ms_user_settings-icon_scaling = iv_scaling. IF ms_user_settings-icon_scaling NA c_icon_scaling. ms_user_settings-icon_scaling = ''. " Reset to default ENDIF. ENDMETHOD. METHOD set_link_hints_enabled. ms_user_settings-link_hints_enabled = iv_link_hints_enabled. ENDMETHOD. METHOD set_link_hint_key. ms_user_settings-link_hint_key = iv_link_hint_key. ENDMETHOD. METHOD set_max_lines. ms_user_settings-max_lines = iv_lines. ENDMETHOD. METHOD set_parallel_proc_disabled. ms_user_settings-parallel_proc_disabled = iv_disable_parallel_proc. ENDMETHOD. METHOD set_proxy_authentication. ms_settings-proxy_auth = iv_auth. ENDMETHOD. METHOD set_proxy_bypass. ms_settings-proxy_bypass = it_bypass. ENDMETHOD. METHOD set_proxy_port. ms_settings-proxy_port = iv_port. ENDMETHOD. METHOD set_proxy_url. ms_settings-proxy_url = iv_url. ENDMETHOD. METHOD set_run_critical_tests. ms_settings-run_critical_tests = iv_run. ENDMETHOD. METHOD set_show_default_repo. ms_user_settings-show_default_repo = iv_show_default_repo. ENDMETHOD. METHOD set_ui_theme. ms_user_settings-ui_theme = iv_ui_theme. IF ms_user_settings-ui_theme <> c_ui_theme-default AND ms_user_settings-ui_theme <> c_ui_theme-dark AND ms_user_settings-ui_theme <> c_ui_theme-belize AND ms_user_settings-ui_theme <> c_ui_theme-synced_with_gui. ms_user_settings-ui_theme = c_ui_theme-default. " Reset to default ENDIF. ENDMETHOD. METHOD set_user_settings. ms_user_settings = is_user_settings. IF ms_user_settings-link_hint_key IS INITIAL. set_default_link_hint_key( ). ENDIF. ENDMETHOD. METHOD set_xml_settings. DATA: lo_input TYPE REF TO zif_abapgit_xml_input. CREATE OBJECT lo_input TYPE zcl_abapgit_xml_input EXPORTING iv_xml = iv_settings_xml. CLEAR ms_settings. lo_input->read( EXPORTING iv_name = zcl_abapgit_persistence_db=>c_type_settings CHANGING cg_data = ms_settings ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_language IMPLEMENTATION. METHOD class_constructor. DATA lv_dummy TYPE string. GET LOCALE LANGUAGE gv_login_language COUNTRY lv_dummy MODIFIER lv_dummy. ENDMETHOD. METHOD restore_login_language. SET LOCALE LANGUAGE gv_login_language. ENDMETHOD. METHOD set_current_language. SET LOCALE LANGUAGE iv_language. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_feature IMPLEMENTATION. METHOD is_enabled. DATA: lv_features TYPE string, lt_features TYPE string_table. IF zcl_abapgit_factory=>get_environment( )->is_merged( ) = abap_true. RETURN. ENDIF. lv_features = zcl_abapgit_persist_factory=>get_settings( )->read( )->get_experimental_features( ). CONDENSE lv_features NO-GAPS. rv_run = boolc( lv_features = abap_true ). IF iv_feature IS NOT INITIAL. SPLIT lv_features AT ',' INTO TABLE lt_features. READ TABLE lt_features TRANSPORTING NO FIELDS WITH TABLE KEY table_line = iv_feature. rv_run = boolc( rv_run = abap_true OR sy-subrc = 0 ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_environment IMPLEMENTATION. METHOD is_system_changes_allowed. DATA: lv_systemedit TYPE tadir-edtflag, lv_sys_cliinddep_edit TYPE t000-ccnocliind, lv_is_shadow TYPE abap_bool, ls_upginfo TYPE uvers, lv_is_upgrade TYPE abap_bool. CALL FUNCTION 'TR_SYS_PARAMS' IMPORTING systemedit = lv_systemedit sys_cliinddep_edit = lv_sys_cliinddep_edit EXCEPTIONS no_systemname = 1 no_systemtype = 2 OTHERS = 3. IF sy-subrc <> 0. " Assume system can't be changed RETURN. ENDIF. CALL FUNCTION 'UPG_IS_SHADOW_SYSTEM' IMPORTING ev_shadow = lv_is_shadow. CALL FUNCTION 'UPG_GET_ACTIVE_COMP_UPGRADE' EXPORTING iv_component = 'SAP_BASIS' iv_upgtype = 'A' iv_buffered = abap_false IMPORTING ev_upginfo = ls_upginfo EXCEPTIONS OTHERS = 4. IF sy-subrc = 0 AND ls_upginfo-putstatus NA 'ITU'. lv_is_upgrade = abap_true. ENDIF. " SAP system has status 'not modifiable' (TK 102) " Changes to repository objects are not permitted in this client (TK 729) " Shadow system " Running upgrade rv_result = boolc( lv_systemedit <> 'N' AND lv_sys_cliinddep_edit NA '23' AND lv_is_shadow <> abap_true AND lv_is_upgrade <> abap_true ). ENDMETHOD. METHOD zif_abapgit_environment~compare_with_inactive. rv_result = zif_abapgit_environment~is_sap_cloud_platform( ). ENDMETHOD. METHOD zif_abapgit_environment~get_basis_release. SELECT SINGLE release extrelease FROM cvers INTO (rs_result-release, rs_result-sp) WHERE component = 'SAP_BASIS' ##SUBRC_OK. ENDMETHOD. METHOD zif_abapgit_environment~is_merged. DATA lr_marker TYPE REF TO data ##NEEDED. IF mv_is_merged = abap_undefined. TRY. CREATE DATA lr_marker TYPE REF TO ('LIF_ABAPMERGE_MARKER'). "No exception --> marker found mv_is_merged = abap_true. CATCH cx_sy_create_data_error. mv_is_merged = abap_false. ENDTRY. ENDIF. rv_result = mv_is_merged. ENDMETHOD. METHOD zif_abapgit_environment~is_repo_object_changes_allowed. IF mv_modifiable = abap_undefined. mv_modifiable = is_system_changes_allowed( ). ENDIF. rv_result = mv_modifiable. ENDMETHOD. METHOD zif_abapgit_environment~is_restart_required. " This method will be used in the context of SAP Cloud Platform: " Pull/Push operations are executed in background jobs. " In case of the respective application server needs to be restarted, " it is required to terminate the background job and reschedule again. rv_result = abap_false. TRY. CALL METHOD ('CL_APJ_SCP_TOOLS')=>('IS_RESTART_REQUIRED') RECEIVING restart_required = rv_result. CATCH cx_sy_dyn_call_illegal_method cx_sy_dyn_call_illegal_class. rv_result = abap_false. ENDTRY. ENDMETHOD. METHOD zif_abapgit_environment~is_sap_cloud_platform. IF mv_cloud = abap_undefined. TRY. CALL METHOD ('CL_COS_UTILITIES')=>('IS_SAP_CLOUD_PLATFORM') RECEIVING rv_is_sap_cloud_platform = mv_cloud. CATCH cx_sy_dyn_call_error. mv_cloud = abap_false. ENDTRY. ENDIF. rv_result = mv_cloud. ENDMETHOD. METHOD zif_abapgit_environment~is_sap_object_allowed. rv_allowed = cl_enh_badi_def_utility=>is_sap_system( ). IF rv_allowed = abap_true. RETURN. ENDIF. rv_allowed = zcl_abapgit_exit=>get_instance( )->allow_sap_objects( ). ENDMETHOD. METHOD zif_abapgit_environment~get_system_language_filter. DATA lv_translation_detective_lang TYPE spras. DATA lv_pseudo_translation_language TYPE spras. FIELD-SYMBOLS LIKE LINE OF rt_system_language_filter. " Translation Object Detective " https://help.sap.com/docs/ABAP_PLATFORM_NEW/ceb25152cb0d4adba664cebea2bf4670/88a3d3cbccf64601975acabaccdfde45.html CALL FUNCTION 'CONVERSION_EXIT_ISOLA_INPUT' EXPORTING input = '1Q' IMPORTING output = lv_translation_detective_lang EXCEPTIONS unknown_language = 1 OTHERS = 2. IF sy-subrc = 1. " The language for Translation Object Detective was not setup ENDIF. IF NOT lv_translation_detective_lang IS INITIAL. APPEND INITIAL LINE TO rt_system_language_filter ASSIGNING . -sign = 'E'. -option = 'EQ'. -low = lv_translation_detective_lang. ENDIF. " 1943470 - Using technical language key 2Q to create pseudo-translations of ABAP developments " https://launchpad.support.sap.com/#/notes/1943470 CALL FUNCTION 'CONVERSION_EXIT_ISOLA_INPUT' EXPORTING input = '2Q' IMPORTING output = lv_pseudo_translation_language EXCEPTIONS unknown_language = 1 OTHERS = 2. IF sy-subrc = 1. " The language for Pseudo Translation was not setup ENDIF. IF NOT lv_pseudo_translation_language IS INITIAL. APPEND INITIAL LINE TO rt_system_language_filter ASSIGNING . -sign = 'E'. -option = 'EQ'. -low = lv_pseudo_translation_language. ENDIF. ENDMETHOD. METHOD zif_abapgit_environment~is_variant_maintenance. DATA: lt_variscreens TYPE STANDARD TABLE OF rsdynnr WITH NON-UNIQUE DEFAULT KEY. " Memory is set in LSVARF08 / EXPORT_SCREEN_TABLES. IMPORT variscreens = lt_variscreens FROM MEMORY ID '%_SCRNR_%'. rv_is_variant_maintenance = boolc( lines( lt_variscreens ) > 0 ). ENDMETHOD. METHOD zif_abapgit_environment~init_parallel_processing. DATA: lv_group TYPE rzlli_apcl. lv_group = iv_group. " SPBT_INITIALIZE gives error PBT_ENV_ALREADY_INITIALIZED if called " multiple times in same session CALL FUNCTION 'SPBT_INITIALIZE' EXPORTING group_name = lv_group IMPORTING free_pbt_wps = rv_free_work_processes EXCEPTIONS invalid_group_name = 1 internal_error = 2 pbt_env_already_initialized = 3 currently_no_resources_avail = 4 no_pbt_resources_found = 5 cant_init_different_pbt_groups = 6 OTHERS = 7. " If SPBT_INITIALIZE fails, check transactions RZ12, SM50, SM21, SARFC ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_abap_language_vers IMPLEMENTATION. METHOD check_abap_language_version. " Check if ABAP language version matches repository setting IF is_item-abap_language_version IS NOT INITIAL AND iv_abap_language_version <> is_item-abap_language_version. zcx_abapgit_exception=>raise( |Object { is_item-obj_type } { is_item-obj_name } has { get_description( iv_abap_language_version ) }| && | but repository is set to { get_description( is_item-abap_language_version ) }| ). ENDIF. ENDMETHOD. METHOD constructor. mo_dot_abapgit = io_dot_abapgit. IF zcl_abapgit_feature=>is_enabled( c_feature_flag ) = abap_false. mv_has_abap_language_vers = abap_undefined. ELSEIF get_abap_language_vers_by_repo( ) = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. mv_has_abap_language_vers = abap_undefined. ELSEIF get_abap_language_vers_by_repo( ) = zif_abapgit_dot_abapgit=>c_abap_language_version-ignore. mv_has_abap_language_vers = abap_false. ELSE. mv_has_abap_language_vers = abap_true. ENDIF. ENDMETHOD. METHOD get_abap_language_vers_by_devc. DATA lv_class TYPE string. DATA lv_abap_lang_version_devc TYPE string. DATA lo_abap_language_version_cfg TYPE REF TO object. lv_class = 'CL_ABAP_LANGUAGE_VERSION_CFG'. TRY. CALL METHOD (lv_class)=>('GET_INSTANCE') RECEIVING ro_instance = lo_abap_language_version_cfg. " For non-existing packages, GET_PACKAGE_DEFAULT_VERSION returns "standard" " but we want to return "undefined" in this case to allow any new packages IF zcl_abapgit_factory=>get_sap_package( iv_package )->exists( ) = abap_true. CALL METHOD lo_abap_language_version_cfg->('IF_ABAP_LANGUAGE_VERSION_CFG~GET_PACKAGE_DEFAULT_VERSION') EXPORTING iv_package_name = iv_package RECEIVING rv_default_language_version = lv_abap_lang_version_devc. ELSE. lv_abap_lang_version_devc = '-'. ENDIF. CASE lv_abap_lang_version_devc. WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-standard. rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-standard. WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-key_user. rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-key_user. WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-cloud_development. rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development. WHEN OTHERS. rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. ENDCASE. CATCH cx_root. rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. ENDTRY. ENDMETHOD. METHOD get_abap_language_vers_by_objt. DATA lv_class TYPE string. DATA lo_abap_language_version TYPE REF TO object. IF mv_has_abap_language_vers = abap_undefined. rv_allowed_abap_langu_version = c_any_abap_language_version. ELSEIF mv_has_abap_language_vers = abap_false. rv_allowed_abap_langu_version = c_no_abap_language_version. ELSE. " abap_true lv_class = 'CL_ABAP_LANGUAGE_VERSION'. TRY. CALL METHOD (lv_class)=>('GET_INSTANCE') RECEIVING ro_version_handler = lo_abap_language_version. CALL METHOD lo_abap_language_version->('IF_ABAP_LANGUAGE_VERSION~GET_DEFAULT_VERSION') EXPORTING iv_object_type = iv_object_type iv_package = iv_package RECEIVING rv_default_version = rv_allowed_abap_langu_version. CATCH cx_root. rv_allowed_abap_langu_version = get_default_abap_language_vers( iv_object_type ). ENDTRY. ENDIF. ENDMETHOD. METHOD get_abap_language_vers_by_repo. rv_abap_language_version = mo_dot_abapgit->get_abap_language_version( ). IF rv_abap_language_version IS INITIAL. rv_abap_language_version = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. ENDIF. ENDMETHOD. METHOD get_default_abap_language_vers. IF zcl_abapgit_factory=>get_environment( )->is_sap_cloud_platform( ) = abap_true. " On BTP, default to ABAP for Cloud Development rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_cloud-cloud_development. ELSE. " Differentiate between source code object and non-source code objects CASE iv_object_type. WHEN 'BDEF' OR 'CLAS' OR 'FUGR' OR 'FUGS' OR 'INTF' OR 'PROG' OR 'TYPE'. rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard. WHEN OTHERS. rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version-standard. ENDCASE. ENDIF. ENDMETHOD. METHOD get_description. CASE iv_abap_language_version. WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-standard OR zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard. rv_description = 'Standard ABAP'. WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-key_user OR zif_abapgit_aff_types_v1=>co_abap_language_version_src-key_user. rv_description = 'ABAP for Key Users'. WHEN zif_abapgit_aff_types_v1=>co_abap_language_version-cloud_development OR zif_abapgit_aff_types_v1=>co_abap_language_version_src-cloud_development. rv_description = 'ABAP for Cloud Development'. WHEN OTHERS. rv_description = 'Undefined'. ENDCASE. rv_description = |ABAP language version "{ rv_description }"|. ENDMETHOD. METHOD get_repo_abap_language_version. DATA lv_abap_language_version TYPE string. IF mv_has_abap_language_vers <> abap_undefined. " abap_true or abap_false lv_abap_language_version = mo_dot_abapgit->get_abap_language_version( ). ENDIF. CASE lv_abap_language_version. WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-standard. rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-standard. WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-key_user. rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-key_user. WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-cloud_development. rv_abap_language_version = zif_abapgit_aff_types_v1=>co_abap_language_version_src-cloud_development. WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-ignore. rv_abap_language_version = c_no_abap_language_version. WHEN OTHERS. " undefined or feature off rv_abap_language_version = c_any_abap_language_version. ENDCASE. ENDMETHOD. METHOD is_import_allowed. DATA lv_package_version TYPE string. lv_package_version = get_abap_language_vers_by_devc( iv_package ). CASE get_abap_language_vers_by_repo( ). WHEN zif_abapgit_dot_abapgit=>c_abap_language_version-undefined OR zif_abapgit_dot_abapgit=>c_abap_language_version-ignore. rv_allowed = abap_true. WHEN OTHERS. IF get_abap_language_vers_by_repo( ) = lv_package_version. " allow packages that match repo setting rv_allowed = abap_true. ELSEIF lv_package_version = zif_abapgit_dot_abapgit=>c_abap_language_version-undefined. " always allow new packages rv_allowed = abap_true. ELSE. rv_allowed = abap_false. ENDIF. ENDCASE. ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_DATA_UTILS IMPLEMENTATION. METHOD build_config_filename. rv_filename = to_lower( |{ is_config-name }.{ zif_abapgit_data_config=>c_config }| && |.{ zif_abapgit_data_config=>c_default_format }| ). REPLACE ALL OCCURRENCES OF '/' IN rv_filename WITH '#'. ENDMETHOD. METHOD build_data_filename. rv_filename = to_lower( |{ is_config-name }.{ is_config-type }| && |.{ zif_abapgit_data_config=>c_default_format }| ). REPLACE ALL OCCURRENCES OF '/' IN rv_filename WITH '#'. ENDMETHOD. METHOD build_table_itab. DATA lo_type TYPE REF TO cl_abap_typedescr. DATA lo_data TYPE REF TO cl_abap_structdescr. DATA lo_table TYPE REF TO cl_abap_tabledescr. DATA lt_keys TYPE abap_table_keydescr_tab. DATA lt_names TYPE ty_names. FIELD-SYMBOLS LIKE LINE OF lt_names. FIELD-SYMBOLS LIKE LINE OF lt_keys. FIELD-SYMBOLS LIKE LINE OF -components. cl_abap_structdescr=>describe_by_name( EXPORTING p_name = iv_name RECEIVING p_descr_ref = lo_type EXCEPTIONS type_not_found = 1 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Table { iv_name } not found for data serialization| ). ENDIF. TRY. lo_data ?= lo_type. " Get primary key to ensure unique entries IF lo_data->is_ddic_type( ) = abap_true. lt_names = list_key_fields( iv_name ). APPEND INITIAL LINE TO lt_keys ASSIGNING . -access_kind = cl_abap_tabledescr=>tablekind_hashed. -key_kind = cl_abap_tabledescr=>keydefkind_user. -is_primary = abap_true. -is_unique = abap_true. LOOP AT lt_names ASSIGNING . APPEND INITIAL LINE TO -components ASSIGNING . -name = . ENDLOOP. ENDIF. IF lines( lt_names ) = 0. lo_table = cl_abap_tabledescr=>get( lo_data ). ELSE. lo_table = cl_abap_tabledescr=>get_with_keys( p_line_type = lo_data p_keys = lt_keys ). ENDIF. CREATE DATA rr_data TYPE HANDLE lo_table. CATCH cx_root. zcx_abapgit_exception=>raise( |Error creating internal table for data serialization| ). ENDTRY. ENDMETHOD. METHOD does_table_exist. " This is slow but ensures that the table actually exists and is not just buffered by RTTI " If we just rely on RTTI, uninstalling and reinstalling a table in the same session will lead to dumps TRY. build_table_itab( iv_name ). rv_exists = abap_true. CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. ENDMETHOD. METHOD is_customizing_table. DATA lv_contflag TYPE c LENGTH 1. DATA lo_table TYPE REF TO object. DATA lo_content TYPE REF TO object. DATA lo_delivery_class TYPE REF TO object. FIELD-SYMBOLS TYPE any. TRY. CALL METHOD ('XCO_CP_ABAP_DICTIONARY')=>database_table EXPORTING iv_name = iv_name(16) RECEIVING ro_database_table = lo_table. CALL METHOD lo_table->('IF_XCO_DATABASE_TABLE~CONTENT') RECEIVING ro_content = lo_content. CALL METHOD lo_content->('IF_XCO_DBT_CONTENT~GET_DELIVERY_CLASS') RECEIVING ro_delivery_class = lo_delivery_class. ASSIGN lo_delivery_class->('VALUE') TO . lv_contflag = . CATCH cx_sy_dyn_call_illegal_class cx_no_check. " Catching SAP standard exception CX_NO_CHECK, " because of the expected exception CX_XCO_RUNTIME_EXCEPTION " could not be used here directly to keep the indirect usage approach. SELECT SINGLE contflag FROM ('DD02L') INTO lv_contflag WHERE tabname = iv_name. ENDTRY. IF lv_contflag = 'C'. rv_customizing = abap_true. ELSEIF lv_contflag IS NOT INITIAL. rv_customizing = abap_false. ELSE. rv_customizing = abap_undefined. " table does not exist ENDIF. ENDMETHOD. METHOD jump. " Run SE16 with authorization check CALL FUNCTION 'RS_TABLE_LIST_CREATE' EXPORTING table_name = is_item-obj_name EXCEPTIONS table_is_structure = 1 table_not_exists = 2 db_not_exists = 3 no_permission = 4 no_change_allowed = 5 table_is_gtt = 6 OTHERS = 7. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Table { is_item-obj_name } cannot be displayed| ). ENDIF. ENDMETHOD. METHOD list_key_fields. DATA lo_obj TYPE REF TO object. DATA lv_tabname TYPE c LENGTH 16. DATA lr_ddfields TYPE REF TO data. DATA lv_workaround TYPE c LENGTH 20. DATA lr_struct TYPE REF TO cl_abap_structdescr. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE simple. FIELD-SYMBOLS TYPE ANY TABLE. * convert to correct type, lv_tabname = iv_name. TRY. CALL METHOD ('XCO_CP_ABAP_DICTIONARY')=>database_table EXPORTING iv_name = lv_tabname RECEIVING ro_database_table = lo_obj. ASSIGN lo_obj->('IF_XCO_DATABASE_TABLE~FIELDS->IF_XCO_DBT_FIELDS_FACTORY~KEY') TO . IF sy-subrc <> 0. * fallback to RTTI, KEY field does not exist in S/4 2020 RAISE EXCEPTION TYPE cx_sy_dyn_call_illegal_class. ENDIF. lo_obj = . CALL METHOD lo_obj->('IF_XCO_DBT_FIELDS~GET_NAMES') RECEIVING rt_names = rt_names. CATCH cx_sy_dyn_call_illegal_class cx_no_check. lv_workaround = 'DDFIELDS'. CREATE DATA lr_ddfields TYPE (lv_workaround). ASSIGN lr_ddfields->* TO . ASSERT sy-subrc = 0. lr_struct ?= cl_abap_typedescr=>describe_by_name( lv_tabname ). lr_struct->get_ddic_field_list( RECEIVING p_field_list = EXCEPTIONS not_found = 1 no_ddic_type = 2 ). IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Table { iv_name } not found| ). ENDIF. LOOP AT ASSIGNING . ASSIGN COMPONENT 'KEYFLAG' OF STRUCTURE TO . IF sy-subrc <> 0 OR <> abap_true. CONTINUE. ENDIF. ASSIGN COMPONENT 'FIELDNAME' OF STRUCTURE TO . ASSERT sy-subrc = 0. APPEND TO rt_names. ENDLOOP. ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_data_supporter IMPLEMENTATION. METHOD get_supported_objects. DATA: lt_tables TYPE STANDARD TABLE OF tabname, lv_tabname TYPE tabname, ls_object LIKE LINE OF mt_supported_objects, li_exit TYPE REF TO zif_abapgit_exit. " For safety reasons, by default only customer-defined customizing tables are supported SELECT dd02l~tabname FROM dd09l JOIN dd02l ON dd09l~tabname = dd02l~tabname AND dd09l~as4local = dd02l~as4local AND dd09l~as4vers = dd02l~as4vers INTO TABLE lt_tables WHERE dd02l~tabclass = 'TRANSP' AND dd09l~tabart = 'APPL2' AND dd09l~as4user <> 'SAP' AND dd09l~as4local = 'A' "Only active tables AND dd02l~contflag = 'C' "Only customizing tables ORDER BY dd02l~tabname. LOOP AT lt_tables INTO lv_tabname. ls_object-type = zif_abapgit_data_config=>c_data_type-tabu. ls_object-name = lv_tabname. INSERT ls_object INTO TABLE mt_supported_objects. ENDLOOP. " The list of supported objects can be enhanced using an exit " Name patterns are allowed. For example, TABU T009* li_exit = zcl_abapgit_exit=>get_instance( ). li_exit->change_supported_data_objects( CHANGING ct_objects = mt_supported_objects ). ENDMETHOD. METHOD zif_abapgit_data_supporter~is_object_supported. FIELD-SYMBOLS LIKE LINE OF mt_supported_objects. IF mt_supported_objects IS INITIAL. get_supported_objects( ). ENDIF. READ TABLE mt_supported_objects TRANSPORTING NO FIELDS WITH TABLE KEY type = iv_type name = iv_name. IF sy-subrc = 0. rv_supported = abap_true. ELSE. " Check if object name matches pattern LOOP AT mt_supported_objects ASSIGNING WHERE type = iv_type. IF iv_name CP -name. rv_supported = abap_true. RETURN. ENDIF. ENDLOOP. ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_data_serializer IMPLEMENTATION. METHOD convert_itab_to_json. DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. DATA lv_string TYPE string. DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. FIELD-SYMBOLS TYPE ANY TABLE. ASSIGN ir_data->* TO . TRY. lo_ajson = zcl_abapgit_ajson=>create_empty( ). lo_ajson->keep_item_order( ). lo_ajson->set( iv_path = '/' iv_val = ). IF iv_skip_initial = abap_true. lo_ajson = zcl_abapgit_ajson=>create_from( ii_source_json = lo_ajson ii_filter = zcl_abapgit_ajson_filter_lib=>create_empty_filter( ) ). ENDIF. lv_string = lo_ajson->stringify( 2 ). CATCH zcx_abapgit_ajson_error INTO lx_ajson. zcx_abapgit_exception=>raise( lx_ajson->get_text( ) ). ENDTRY. rv_data = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ). ENDMETHOD. METHOD read_database_table. DATA lv_records TYPE i. DATA lv_where LIKE LINE OF it_where. DATA lx_sql TYPE REF TO cx_sy_sql_error. FIELD-SYMBOLS TYPE ANY TABLE. rr_data = zcl_abapgit_data_utils=>build_table_itab( iv_name ). ASSIGN rr_data->* TO . TRY. LOOP AT it_where INTO lv_where. SELECT * FROM (iv_name) APPENDING TABLE WHERE (lv_where) ORDER BY PRIMARY KEY. ENDLOOP. IF lines( it_where ) = 0. SELECT * FROM (iv_name) INTO TABLE ORDER BY PRIMARY KEY. ENDIF. CATCH cx_sy_sql_error INTO lx_sql. zcx_abapgit_exception=>raise( iv_text = lx_sql->get_text( ) ix_previous = lx_sql ). ENDTRY. lv_records = lines( ). IF lv_records > c_max_records. zcx_abapgit_exception=>raise( |Too many records selected from table { iv_name } (selected { lv_records }, max { c_max_records })| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_data_serializer~serialize. DATA lt_configs TYPE zif_abapgit_data_config=>ty_config_tt. DATA ls_config LIKE LINE OF lt_configs. DATA ls_file LIKE LINE OF rt_files. DATA lr_data TYPE REF TO data. ls_file-path = zif_abapgit_data_config=>c_default_path. lt_configs = ii_config->get_configs( ). LOOP AT lt_configs INTO ls_config. ASSERT ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. " todo ASSERT ls_config-name IS NOT INITIAL. IF zcl_abapgit_data_utils=>does_table_exist( ls_config-name ) = abap_true. lr_data = read_database_table( iv_name = ls_config-name it_where = ls_config-where ). ls_file-data = convert_itab_to_json( ir_data = lr_data iv_skip_initial = ls_config-skip_initial ). ELSE. ls_file-data = zcl_abapgit_convert=>string_to_xstring_utf8( '[]' ). ENDIF. ls_file-filename = zcl_abapgit_data_utils=>build_data_filename( ls_config ). ls_file-sha1 = zcl_abapgit_hash=>sha1_blob( ls_file-data ). APPEND ls_file TO rt_files. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_data_factory IMPLEMENTATION. METHOD get_config. CREATE OBJECT ri_config TYPE zcl_abapgit_data_config. ENDMETHOD. METHOD get_deserializer. IF gi_deserializer IS INITIAL. CREATE OBJECT gi_deserializer TYPE zcl_abapgit_data_deserializer. ENDIF. ri_deserializer = gi_deserializer. ENDMETHOD. METHOD get_serializer. IF gi_serializer IS INITIAL. CREATE OBJECT gi_serializer TYPE zcl_abapgit_data_serializer. ENDIF. ri_serializer = gi_serializer. ENDMETHOD. METHOD get_supporter. IF gi_supporter IS INITIAL. CREATE OBJECT gi_supporter TYPE zcl_abapgit_data_supporter. ENDIF. ri_supporter = gi_supporter. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_data_deserializer IMPLEMENTATION. METHOD convert_json_to_itab. DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. FIELD-SYMBOLS TYPE ANY TABLE. ASSIGN ir_data->* TO . TRY. lo_ajson = zcl_abapgit_ajson=>parse( zcl_abapgit_convert=>xstring_to_string_utf8( is_file-data ) ). lo_ajson->zif_abapgit_ajson~to_abap( IMPORTING ev_container = ). CATCH zcx_abapgit_ajson_error INTO lx_ajson. zcx_abapgit_exception=>raise( lx_ajson->get_text( ) ). ENDTRY. ENDMETHOD. METHOD determine_transport_request. DATA li_exit TYPE REF TO zif_abapgit_exit. li_exit = zcl_abapgit_exit=>get_instance( ). " Use transport from repo settings if maintained, or determine via user exit. " If transport keeps empty here, it'll requested later via popup. rv_transport_request = io_repo->get_local_settings( )-customizing_request. li_exit->determine_transport_request( EXPORTING io_repo = io_repo iv_transport_type = iv_transport_type CHANGING cv_transport_request = rv_transport_request ). ENDMETHOD. METHOD is_table_allowed_to_edit. " Is the object supported (by default or based on exit)? rv_allowed_to_edit = zcl_abapgit_data_factory=>get_supporter( )->is_object_supported( iv_type = is_result-type iv_name = is_result-name ). ENDMETHOD. METHOD preview_database_changes. * method currently distinguishes between records be deleted and inserted (comparison of complete record) FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE any. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE ANY TABLE. ASSIGN ir_db_data->* TO . ASSIGN ir_lc_data->* TO . rs_result-type = zif_abapgit_data_config=>c_data_type-tabu. rs_result-name = iv_name. rs_result-deletes = zcl_abapgit_data_utils=>build_table_itab( iv_name ). rs_result-inserts = zcl_abapgit_data_utils=>build_table_itab( iv_name ). rs_result-updates = zcl_abapgit_data_utils=>build_table_itab( iv_name ). ASSIGN rs_result-deletes->* TO . ASSIGN rs_result-inserts->* TO . ASSIGN rs_result-updates->* TO . = . = . " Remove identical records LOOP AT ASSIGNING . READ TABLE ASSIGNING FROM . IF sy-subrc = 0. IF <> . " Identical key but not identical component values INSERT INTO TABLE . ENDIF. DELETE TABLE FROM . DELETE TABLE FROM . ENDIF. ENDLOOP. ENDMETHOD. METHOD read_database_table. DATA lv_where LIKE LINE OF it_where. FIELD-SYMBOLS TYPE ANY TABLE. rr_data = zcl_abapgit_data_utils=>build_table_itab( iv_name ). ASSIGN rr_data->* TO . LOOP AT it_where INTO lv_where. SELECT * FROM (iv_name) APPENDING TABLE WHERE (lv_where) ORDER BY PRIMARY KEY. ENDLOOP. IF lines( it_where ) = 0. SELECT * FROM (iv_name) INTO TABLE ORDER BY PRIMARY KEY. ENDIF. ENDMETHOD. METHOD write_database_table. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE ANY TABLE. FIELD-SYMBOLS TYPE ANY TABLE. IF zcl_abapgit_data_utils=>does_table_exist( iv_name ) = abap_false. zcx_abapgit_exception=>raise( |Table { iv_name } not found for data deserialization| ). ENDIF. ASSIGN ir_del->* TO . ASSIGN ir_ins->* TO . ASSIGN ir_upd->* TO . IF lines( ) > 0. DELETE (iv_name) FROM TABLE . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error deleting { lines( ) } records from table { iv_name }| ). ENDIF. ENDIF. IF lines( ) > 0. INSERT (iv_name) FROM TABLE . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error inserting { lines( ) } records into table { iv_name }| ). ENDIF. ENDIF. IF lines( ) > 0. UPDATE (iv_name) FROM TABLE . IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Error updating { lines( ) } records into table { iv_name }| ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_data_deserializer~actualize. * this method updates the database DATA ls_result LIKE LINE OF it_result. DATA li_cts_api TYPE REF TO zif_abapgit_cts_api. FIELD-SYMBOLS: TYPE ANY TABLE, TYPE ANY TABLE, TYPE ANY TABLE. LOOP AT it_result INTO ls_result. ASSERT ls_result-type = zif_abapgit_data_config=>c_data_type-tabu. " todo ASSERT ls_result-name IS NOT INITIAL. " Did the user flagged this object for update? READ TABLE is_checks-overwrite TRANSPORTING NO FIELDS WITH KEY object_type_and_name COMPONENTS obj_type = ls_result-type obj_name = ls_result-name decision = zif_abapgit_definitions=>c_yes. IF sy-subrc <> 0. CONTINUE. ENDIF. IF is_table_allowed_to_edit( ls_result ) = abap_false. zcx_abapgit_exception=>raise( |Table { ls_result-name } not supported for updating data| ). ENDIF. write_database_table( iv_name = ls_result-name ir_del = ls_result-deletes ir_ins = ls_result-inserts ir_upd = ls_result-updates ). ASSIGN ls_result-inserts->* TO . ASSIGN ls_result-deletes->* TO . ASSIGN ls_result-updates->* TO . IF zcl_abapgit_data_utils=>is_customizing_table( ls_result-name ) = abap_true. IF li_cts_api IS INITIAL. li_cts_api = zcl_abapgit_factory=>get_cts_api( ). ENDIF. li_cts_api->create_transport_entries( iv_transport = is_checks-customizing-transport it_table_ins = it_table_upd = it_table_del = iv_tabname = |{ ls_result-name }| ). ENDIF. INSERT ls_result-file INTO TABLE rt_accessed_files. " data file INSERT ls_result-config INTO TABLE rt_accessed_files. " config file ENDLOOP. ENDMETHOD. METHOD zif_abapgit_data_deserializer~deserialize. * this method does not persist any changes to the database DATA lt_configs TYPE zif_abapgit_data_config=>ty_config_tt. DATA ls_config LIKE LINE OF lt_configs. DATA lr_lc_data TYPE REF TO data. DATA lr_db_data TYPE REF TO data. DATA ls_file LIKE LINE OF it_files. DATA ls_result LIKE LINE OF rt_result. lt_configs = ii_config->get_configs( ). LOOP AT lt_configs INTO ls_config. ASSERT ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. " todo ASSERT ls_config-name IS NOT INITIAL. lr_lc_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ). READ TABLE it_files INTO ls_file WITH KEY file_path COMPONENTS path = zif_abapgit_data_config=>c_default_path filename = zcl_abapgit_data_utils=>build_data_filename( ls_config ). IF sy-subrc = 0. convert_json_to_itab( ir_data = lr_lc_data is_file = ls_file ). lr_db_data = read_database_table( iv_name = ls_config-name it_where = ls_config-where ). ls_result = preview_database_changes( iv_name = ls_config-name ir_lc_data = lr_lc_data ir_db_data = lr_db_data ). MOVE-CORRESPONDING ls_file TO ls_result-file. " data file READ TABLE it_files INTO ls_file WITH KEY file_path COMPONENTS path = zif_abapgit_data_config=>c_default_path filename = zcl_abapgit_data_utils=>build_config_filename( ls_config ). ASSERT sy-subrc = 0. MOVE-CORRESPONDING ls_file TO ls_result-config. " config file INSERT ls_result INTO TABLE rt_result. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_data_deserializer~deserialize_check. DATA lt_configs TYPE zif_abapgit_data_config=>ty_config_tt. lt_configs = ii_config->get_configs( ). IF lt_configs IS NOT INITIAL. rs_checks-required = abap_true. rs_checks-type-request = zif_abapgit_cts_api=>c_transport_type-cust_request. rs_checks-type-task = zif_abapgit_cts_api=>c_transport_type-cust_task. rs_checks-transport = determine_transport_request( io_repo = io_repo iv_transport_type = rs_checks-type ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_data_config IMPLEMENTATION. METHOD dump. DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. TRY. lo_ajson = zcl_abapgit_ajson=>create_empty( ). lo_ajson->zif_abapgit_ajson~set( iv_path = '/' iv_val = is_config ). rv_json = zcl_abapgit_convert=>string_to_xstring_utf8( lo_ajson->stringify( 2 ) ). CATCH zcx_abapgit_ajson_error INTO lx_ajson. zcx_abapgit_exception=>raise( lx_ajson->get_text( ) ). ENDTRY. ENDMETHOD. METHOD zif_abapgit_data_config~add_config. DATA lv_where TYPE string. FIELD-SYMBOLS LIKE LINE OF mt_config. ASSERT is_config-type IS NOT INITIAL. ASSERT is_config-name IS NOT INITIAL. ASSERT is_config-name = to_upper( is_config-name ). INSERT is_config INTO TABLE mt_config. IF sy-subrc <> 0. * append to existing READ TABLE mt_config ASSIGNING WITH KEY type = is_config-type name = is_config-name. ASSERT sy-subrc = 0. LOOP AT is_config-where INTO lv_where. READ TABLE -where TRANSPORTING NO FIELDS WITH KEY table_line = lv_where. IF sy-subrc <> 0. INSERT lv_where INTO TABLE -where. ENDIF. ENDLOOP. ENDIF. ENDMETHOD. METHOD zif_abapgit_data_config~from_json. DATA ls_file LIKE LINE OF it_files. DATA ls_config TYPE zif_abapgit_data_config=>ty_config. DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error. CLEAR mt_config. LOOP AT it_files INTO ls_file USING KEY file_path WHERE path = zif_abapgit_data_config=>c_default_path AND filename CP |*.{ zif_abapgit_data_config=>c_config }.{ zif_abapgit_data_config=>c_default_format }|. TRY. lo_ajson = zcl_abapgit_ajson=>parse( zcl_abapgit_convert=>xstring_to_string_utf8( ls_file-data ) ). lo_ajson->zif_abapgit_ajson~to_abap( IMPORTING ev_container = ls_config ). CATCH zcx_abapgit_ajson_error INTO lx_ajson. zcx_abapgit_exception=>raise( lx_ajson->get_text( ) ). ENDTRY. zif_abapgit_data_config~add_config( ls_config ). ENDLOOP. ENDMETHOD. METHOD zif_abapgit_data_config~get_configs. rt_configs = mt_config. ENDMETHOD. METHOD zif_abapgit_data_config~remove_config. ASSERT is_config-type IS NOT INITIAL. ASSERT is_config-name IS NOT INITIAL. ASSERT is_config-name = to_upper( is_config-name ). DELETE mt_config WHERE name = is_config-name AND type = is_config-type. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Not found' ). ENDIF. ENDMETHOD. METHOD zif_abapgit_data_config~to_json. DATA ls_config LIKE LINE OF mt_config. DATA ls_file LIKE LINE OF rt_files. ls_file-path = zif_abapgit_data_config=>c_default_path. LOOP AT mt_config INTO ls_config. ls_file-data = dump( ls_config ). ls_file-sha1 = zcl_abapgit_hash=>sha1_blob( ls_file-data ). ls_config-type = zif_abapgit_data_config=>c_config. ls_file-filename = zcl_abapgit_data_utils=>build_data_filename( ls_config ). APPEND ls_file TO rt_files. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_data_config~update_config. zif_abapgit_data_config~remove_config( is_config ). zif_abapgit_data_config~add_config( is_config ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_transport_objects IMPLEMENTATION. METHOD constructor. mt_transport_objects = it_transport_objects. ENDMETHOD. METHOD to_stage. DATA: ls_transport_object LIKE LINE OF mt_transport_objects, ls_local_file TYPE zif_abapgit_definitions=>ty_file_item, ls_object_status TYPE zif_abapgit_definitions=>ty_result. LOOP AT mt_transport_objects INTO ls_transport_object. LOOP AT it_object_statuses INTO ls_object_status WHERE obj_name = ls_transport_object-obj_name AND obj_type = ls_transport_object-object AND NOT lstate IS INITIAL. CASE ls_object_status-lstate. WHEN zif_abapgit_definitions=>c_state-added OR zif_abapgit_definitions=>c_state-modified. IF ls_transport_object-delflag = abap_true. zcx_abapgit_exception=>raise( |Object { ls_transport_object-object }| && | { ls_transport_object-obj_name } should be added/modified,| && | but has deletion flag in transport| ). ENDIF. READ TABLE is_stage_objects-local INTO ls_local_file WITH KEY item-obj_name = ls_transport_object-obj_name item-obj_type = ls_transport_object-object file-filename = ls_object_status-filename. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Object { ls_transport_object-object }| && | { ls_transport_object-obj_name } not found in the local repository files| ). ELSE. io_stage->add( iv_path = ls_local_file-file-path iv_filename = ls_local_file-file-filename iv_data = ls_local_file-file-data ). ENDIF. WHEN zif_abapgit_definitions=>c_state-deleted. io_stage->rm( iv_path = ls_object_status-path iv_filename = ls_object_status-filename ). WHEN OTHERS. ASSERT 0 = 1. "Unexpected state ENDCASE. ENDLOOP. IF sy-subrc <> 0. " Since not all objects in a transport might be in the local repo " i.e. generated SADL objects, we don't add these objects to " the stage. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr DEFINITION DEFERRED. CLASS kHGwlFZZSwYWAxVpEdIbTqkphOFmih DEFINITION DEFERRED. * renamed: zcl_abapgit_transport_mass :: lcl_gui CLASS kHGwlFZZSwYWAxVpEdIbTqkphOFmih DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS f4_folder RETURNING VALUE(rv_folder) TYPE string RAISING zcx_abapgit_exception. CLASS-METHODS open_folder_frontend IMPORTING iv_folder TYPE string RAISING zcx_abapgit_exception. CLASS-METHODS select_tr_requests RETURNING VALUE(rt_trkorr) TYPE trwbo_request_headers. ENDCLASS. CLASS kHGwlFZZSwYWAxVpEdIbTqkphOFmih IMPLEMENTATION. METHOD f4_folder. DATA: lv_title TYPE string, lo_fe_serv TYPE REF TO zif_abapgit_frontend_services. lo_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). lv_title = 'Choose the destination folder for the ZIP files'. lo_fe_serv->directory_browse( EXPORTING iv_window_title = lv_title CHANGING cv_selected_folder = rv_folder ). ENDMETHOD. METHOD open_folder_frontend. IF iv_folder IS INITIAL. RETURN. ENDIF. zcl_abapgit_ui_factory=>get_frontend_services( )->execute( iv_document = iv_folder ). ENDMETHOD. METHOD select_tr_requests. DATA: ls_popup TYPE strhi_popup, ls_selection TYPE trwbo_selection. ls_popup-start_column = 5. ls_popup-start_row = 5. " Prepare the selection ls_selection-trkorrpattern = space. ls_selection-client = space. ls_selection-stdrequest = space. ls_selection-reqfunctions = 'K'. ls_selection-reqstatus = 'RNODL'. " Call transport selection popup CALL FUNCTION 'TRINT_SELECT_REQUESTS' EXPORTING iv_username_pattern = '*' iv_via_selscreen = 'X' is_selection = ls_selection iv_complete_projects = space iv_title = 'abapGit Transport Mass Downloader' is_popup = ls_popup IMPORTING et_requests = rt_trkorr EXCEPTIONS action_aborted_by_user = 1 OTHERS = 2. IF sy-subrc <> 0. CLEAR rt_trkorr. ELSE. SORT rt_trkorr BY trkorr. DELETE ADJACENT DUPLICATES FROM rt_trkorr COMPARING trkorr. ENDIF. ENDMETHOD. ENDCLASS. * renamed: zcl_abapgit_transport_mass :: lcl_transport_zipper CLASS kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr DEFINITION FINAL. PUBLIC SECTION. TYPES ty_folder TYPE string. TYPES ty_filename TYPE string. CONSTANTS c_zip_ext TYPE string VALUE '.zip'. METHODS constructor IMPORTING iv_folder TYPE ty_folder RAISING zcx_abapgit_exception. METHODS generate_files IMPORTING it_trkorr TYPE trwbo_request_headers ig_logic TYPE any RAISING zcx_abapgit_exception. METHODS get_folder RETURNING VALUE(rv_full_folder) TYPE ty_folder. CLASS-METHODS does_folder_exist IMPORTING iv_folder TYPE string RETURNING VALUE(rv_folder_exist) TYPE abap_bool RAISING zcx_abapgit_exception. PRIVATE SECTION. DATA: mv_timestamp TYPE string, mv_separator TYPE c, mv_full_folder TYPE ty_folder. METHODS get_full_folder IMPORTING iv_folder TYPE ty_folder RETURNING VALUE(rv_full_folder) TYPE ty_folder RAISING zcx_abapgit_exception. METHODS get_filename IMPORTING is_trkorr TYPE trwbo_request_header RETURNING VALUE(rv_filename) TYPE ty_filename. ENDCLASS. CLASS kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr IMPLEMENTATION. METHOD constructor. DATA lo_fe_serv TYPE REF TO zif_abapgit_frontend_services. lo_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). mv_timestamp = |{ sy-datlo }_{ sy-timlo }|. mv_full_folder = get_full_folder( iv_folder ). TRY. lo_fe_serv->get_file_separator( CHANGING cv_file_separator = mv_separator ). CATCH zcx_abapgit_exception. "Default MS Windows separator mv_separator = '\'. ENDTRY. ENDMETHOD. METHOD get_folder. rv_full_folder = mv_full_folder. ENDMETHOD. METHOD does_folder_exist. rv_folder_exist = zcl_abapgit_ui_factory=>get_frontend_services( )->directory_exist( iv_folder ). ENDMETHOD. METHOD get_full_folder. DATA: lv_sep TYPE c, lv_rc TYPE i, lo_fe_serv TYPE REF TO zif_abapgit_frontend_services. lo_fe_serv = zcl_abapgit_ui_factory=>get_frontend_services( ). lo_fe_serv->get_file_separator( CHANGING cv_file_separator = lv_sep ). rv_full_folder = |{ iv_folder }{ lv_sep }{ mv_timestamp }|. IF does_folder_exist( rv_full_folder ) = abap_false. lo_fe_serv->directory_create( EXPORTING iv_directory = rv_full_folder CHANGING cv_rc = lv_rc ). ENDIF. ENDMETHOD. METHOD get_filename. " Generate filename rv_filename = |{ is_trkorr-trkorr }_{ is_trkorr-as4text }_{ mv_timestamp }{ c_zip_ext }|. " Remove reserved characters (for Windows based systems) TRANSLATE rv_filename USING '/ \ : " * > < ? | '. rv_filename = |{ mv_full_folder }{ mv_separator }{ rv_filename }|. ENDMETHOD. METHOD generate_files. DATA: ls_trkorr LIKE LINE OF it_trkorr, lv_zipbinstring TYPE xstring. LOOP AT it_trkorr INTO ls_trkorr. lv_zipbinstring = zcl_abapgit_transport_mass=>zip( is_trkorr = ls_trkorr iv_logic = ig_logic iv_show_log_popup = abap_false ). zcl_abapgit_zip=>save_binstring_to_localfile( iv_binstring = lv_zipbinstring iv_filename = get_filename( ls_trkorr ) ). ENDLOOP. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_transport_mass IMPLEMENTATION. METHOD run. DATA: lt_trkorr TYPE trwbo_request_headers, lo_transport_zipper TYPE REF TO kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr, lx_except TYPE REF TO cx_root, lv_folder TYPE string, lv_text TYPE string. TRY. lt_trkorr = kHGwlFZZSwYWAxVpEdIbTqkphOFmih=>select_tr_requests( ). IF lt_trkorr[] IS NOT INITIAL. lv_folder = kHGwlFZZSwYWAxVpEdIbTqkphOFmih=>f4_folder( ). IF lv_folder IS INITIAL. * Empty folder zcx_abapgit_exception=>raise( 'Empty destination folder' ). ENDIF. * Instantiate transport zipper object that will also create the timestamped output folder CREATE OBJECT lo_transport_zipper TYPE kHGwlFZZSwYWAxVpEdIbDiDKiqhGgr EXPORTING iv_folder = lv_folder. * Generate the local zip files from the given list of transport requests lo_transport_zipper->generate_files( it_trkorr = lt_trkorr ig_logic = zcl_abapgit_ui_factory=>get_popups( )->popup_folder_logic( ) ). * Open output folder if user asked it kHGwlFZZSwYWAxVpEdIbTqkphOFmih=>open_folder_frontend( lo_transport_zipper->get_folder( ) ). ELSE. * No data found for the provided selection criteria zcx_abapgit_exception=>raise( 'No transport requests selected' ). ENDIF. CATCH zcx_abapgit_exception INTO lx_except. lv_text = lx_except->get_text( ). MESSAGE lv_text TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_transport_2_branch IMPLEMENTATION. METHOD create. DATA: lv_branch_name TYPE string, ls_comment TYPE zif_abapgit_git_definitions=>ty_comment, lo_stage TYPE REF TO zcl_abapgit_stage, ls_stage_objects TYPE zif_abapgit_definitions=>ty_stage_files, lt_object_statuses TYPE zif_abapgit_definitions=>ty_results_tt. lv_branch_name = zcl_abapgit_git_branch_list=>complete_heads_branch_name( zcl_abapgit_git_branch_list=>normalize_branch_name( is_transport_to_branch-branch_name ) ). io_repository->create_branch( lv_branch_name ). CREATE OBJECT lo_stage. ls_stage_objects = zcl_abapgit_factory=>get_stage_logic( )->get( io_repository ). lt_object_statuses = zcl_abapgit_repo_status=>calculate( io_repository ). stage_transport_objects( it_transport_objects = it_transport_objects io_stage = lo_stage is_stage_objects = ls_stage_objects it_object_statuses = lt_object_statuses ). ls_comment = generate_commit_message( is_transport_to_branch ). io_repository->push( is_comment = ls_comment io_stage = lo_stage ). ENDMETHOD. METHOD generate_commit_message. rs_comment-committer-name = sy-uname. rs_comment-committer-email = |{ rs_comment-committer-name }@localhost|. rs_comment-comment = is_transport_to_branch-commit_text. ENDMETHOD. METHOD stage_transport_objects. DATA lo_transport_objects TYPE REF TO zcl_abapgit_transport_objects. CREATE OBJECT lo_transport_objects EXPORTING it_transport_objects = it_transport_objects. lo_transport_objects->to_stage( io_stage = io_stage is_stage_objects = is_stage_objects it_object_statuses = it_object_statuses ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_TRANSPORT IMPLEMENTATION. METHOD add_all_objects_to_trans_req. DATA: ls_request TYPE trwbo_request_header, lt_e071 TYPE tr_objects, lv_text TYPE string, lv_answer TYPE c LENGTH 1, lv_lock_objects TYPE trparflag, lt_log TYPE sprot_u_tab. lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = `Lock objects?` iv_text_question = `Shall all objects be locked in the transport request?` iv_display_cancel_button = abap_true ). CASE lv_answer. WHEN '1'. lv_lock_objects = abap_true. WHEN '2'. lv_lock_objects = abap_false. WHEN OTHERS. RETURN. ENDCASE. lt_e071 = collect_all_objects( iv_key ). " We used TR_REQUEST_CHOICE before, but it issues its error log with " write lists which are not compatible with abapGit. " There we user TRINT_REQUEST_CHOICE which returns the error log " and display the log ourselves. CALL FUNCTION 'TRINT_REQUEST_CHOICE' EXPORTING iv_request_types = 'FTCOK' iv_lock_objects = lv_lock_objects iv_with_error_log = abap_false IMPORTING es_request = ls_request et_log = lt_log TABLES it_e071 = lt_e071 EXCEPTIONS invalid_request = 1 invalid_request_type = 2 user_not_owner = 3 no_objects_appended = 4 enqueue_error = 5 cancelled_by_user = 6 recursive_call = 7 OTHERS = 8. IF sy-subrc = 0. lv_text = |Objects successfully added to { ls_request-trkorr }|. MESSAGE lv_text TYPE 'S'. RETURN. ENDIF. IF lines( lt_log ) > 0. show_log( it_log = lt_log iv_title = `Error log` ). ELSE. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD collect_all_objects. DATA: lt_objects TYPE scts_tadir, lt_objects_all LIKE lt_objects, ls_e071 LIKE LINE OF rt_objects, lo_repo TYPE REF TO zcl_abapgit_repo, lv_package TYPE zif_abapgit_persistence=>ty_repo-package, lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt. FIELD-SYMBOLS: TYPE devclass, TYPE tadir. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( iv_key ). lv_package = lo_repo->get_package( ). lt_packages = zcl_abapgit_factory=>get_sap_package( lv_package )->list_subpackages( ). INSERT lv_package INTO TABLE lt_packages. LOOP AT lt_packages ASSIGNING . CLEAR: lt_objects. CALL FUNCTION 'TRINT_SELECT_OBJECTS' EXPORTING iv_devclass = iv_via_selscreen = abap_false IMPORTING et_objects_tadir = lt_objects EXCEPTIONS cancelled_by_user = 1 invalid_input = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. INSERT LINES OF lt_objects INTO TABLE lt_objects_all. ENDLOOP. IF lines( lt_objects_all ) = 0. zcx_abapgit_exception=>raise( |No objects found| ). ENDIF. LOOP AT lt_objects_all ASSIGNING . CLEAR: ls_e071. MOVE-CORRESPONDING TO ls_e071. INSERT ls_e071 INTO TABLE rt_objects. ENDLOOP. ENDMETHOD. METHOD find_top_package. * assumption: all objects in transport share a common super package DATA: lt_obj TYPE zif_abapgit_sap_package=>ty_devclass_tt, lt_super TYPE zif_abapgit_sap_package=>ty_devclass_tt, lv_super LIKE LINE OF lt_super, lv_index TYPE i. FIELD-SYMBOLS: LIKE LINE OF it_tadir. READ TABLE it_tadir INDEX 1 ASSIGNING . ASSERT sy-subrc = 0. lt_super = zcl_abapgit_factory=>get_sap_package( -devclass )->list_superpackages( ). LOOP AT it_tadir ASSIGNING . lt_obj = zcl_abapgit_factory=>get_sap_package( -devclass )->list_superpackages( ). * filter out possibilities from lt_super LOOP AT lt_super INTO lv_super. lv_index = sy-tabix. READ TABLE lt_obj FROM lv_super TRANSPORTING NO FIELDS. IF sy-subrc <> 0. DELETE lt_super INDEX lv_index. ENDIF. ENDLOOP. ENDLOOP. READ TABLE lt_super INDEX lines( lt_super ) INTO rv_package. ENDMETHOD. METHOD read_requests. DATA lt_requests LIKE rt_requests. FIELD-SYMBOLS LIKE LINE OF it_trkorr. LOOP AT it_trkorr ASSIGNING . CALL FUNCTION 'TR_READ_REQUEST_WITH_TASKS' EXPORTING iv_trkorr = IMPORTING et_requests = lt_requests EXCEPTIONS invalid_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. APPEND LINES OF lt_requests TO rt_requests. ENDLOOP. ENDMETHOD. METHOD resolve. DATA: lv_object TYPE tadir-object, lv_obj_name TYPE tadir-obj_name, ls_tadir TYPE zif_abapgit_definitions=>ty_tadir, lv_result TYPE trpari-s_checked, ls_tadir_sap TYPE tadir. FIELD-SYMBOLS: LIKE LINE OF it_requests, LIKE LINE OF -objects. LOOP AT it_requests ASSIGNING . LOOP AT -objects ASSIGNING . " VARX, see https://github.com/abapGit/abapGit/issues/3107 IF -pgmid = 'LIMU' AND -object <> 'VARX'. CALL FUNCTION 'TR_CHECK_TYPE' EXPORTING wi_e071 = IMPORTING we_tadir = ls_tadir_sap pe_result = lv_result. IF lv_result NA 'TL' OR ls_tadir_sap IS INITIAL. zcx_abapgit_exception=>raise( 'error from TR_CHECK_TYPE' ). ENDIF. lv_object = ls_tadir_sap-object. lv_obj_name = ls_tadir_sap-obj_name. ELSE. lv_object = -object. lv_obj_name = -obj_name. ENDIF. ls_tadir = zcl_abapgit_factory=>get_tadir( )->read_single( iv_object = lv_object iv_obj_name = lv_obj_name ). IF ls_tadir-delflag IS INITIAL OR iv_deleted_objects = abap_true. APPEND ls_tadir TO rt_tadir. ENDIF. ENDLOOP. ENDLOOP. SORT rt_tadir BY object ASCENDING obj_name ASCENDING. DELETE ADJACENT DUPLICATES FROM rt_tadir COMPARING object obj_name. DELETE rt_tadir WHERE table_line IS INITIAL. ENDMETHOD. METHOD show_log. DATA: li_log TYPE REF TO zif_abapgit_log, lv_message TYPE string. FIELD-SYMBOLS: TYPE sprot_u. CREATE OBJECT li_log TYPE zcl_abapgit_log EXPORTING iv_title = iv_title. LOOP AT it_log ASSIGNING . MESSAGE ID -ag TYPE -severity NUMBER -msgnr WITH -var1 -var2 -var3 -var4 INTO lv_message. li_log->add( iv_msg = lv_message iv_type = -severity ). ENDLOOP. zcl_abapgit_log_viewer=>show_log( li_log ). ENDMETHOD. METHOD to_tadir. DATA lt_requests TYPE trwbo_requests. DATA lt_trkorr TYPE ty_trkorr_tt. IF iv_trkorr IS INITIAL. RETURN. ENDIF. INSERT iv_trkorr INTO TABLE lt_trkorr. lt_requests = read_requests( lt_trkorr ). rt_tadir = resolve( it_requests = lt_requests iv_deleted_objects = iv_deleted_objects ). ENDMETHOD. METHOD zip. DATA: lt_requests TYPE trwbo_requests, lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt, lv_package TYPE devclass, lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit, ls_local_settings TYPE zif_abapgit_persistence=>ty_repo-local_settings, lt_trkorr TYPE ty_trkorr_tt, lv_trkorr TYPE trkorr. IF is_trkorr IS SUPPLIED. APPEND is_trkorr-trkorr TO lt_trkorr. ELSE. lv_trkorr = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_transport( ). IF lv_trkorr IS NOT INITIAL. APPEND lv_trkorr TO lt_trkorr. ENDIF. ENDIF. IF lines( lt_trkorr ) = 0. RETURN. ENDIF. lt_requests = read_requests( lt_trkorr ). lt_tadir = resolve( lt_requests ). IF lines( lt_tadir ) = 0. zcx_abapgit_exception=>raise( 'empty transport' ). ENDIF. lv_package = find_top_package( lt_tadir ). IF lv_package IS INITIAL. zcx_abapgit_exception=>raise( 'error finding super package' ). ENDIF. lo_dot_abapgit = zcl_abapgit_dot_abapgit=>build_default( ). IF iv_logic IS SUPPLIED AND iv_logic IS NOT INITIAL. lo_dot_abapgit->set_folder_logic( iv_logic ). ELSE. lo_dot_abapgit->set_folder_logic( zcl_abapgit_ui_factory=>get_popups( )->popup_folder_logic( ) ). ENDIF. rv_xstr = zcl_abapgit_zip=>export( iv_package = lv_package io_dot_abapgit = lo_dot_abapgit is_local_settings = ls_local_settings it_filter = lt_tadir iv_show_log = iv_show_log_popup ). ENDMETHOD. ENDCLASS. CLASS ZCL_ABAPGIT_DEFAULT_TRANSPORT IMPLEMENTATION. METHOD clear. CALL FUNCTION 'TR_TASK_RESET' EXPORTING iv_username = is_default_task-username iv_order = is_default_task-ordernum iv_task = is_default_task-tasknum iv_dialog = abap_false EXCEPTIONS invalid_username = 1 invalid_order = 2 invalid_task = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD constructor. store( ). ENDMETHOD. METHOD restore. IF ms_save IS INITIAL. " There wasn't a default transport request before " so we needn't restore anything. RETURN. ENDIF. CALL FUNCTION 'TR_TASK_SET' EXPORTING iv_order = ms_save-ordernum iv_task = ms_save-tasknum EXCEPTIONS invalid_username = 1 invalid_category = 2 invalid_client = 3 invalid_validdays = 4 invalid_order = 5 invalid_task = 6 OTHERS = 7. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD set_internal. CALL FUNCTION 'TR_TASK_SET' EXPORTING iv_order = iv_transport iv_validdays = 1 EXCEPTIONS invalid_username = 1 invalid_category = 2 invalid_client = 3 invalid_validdays = 4 invalid_order = 5 invalid_task = 6 OTHERS = 7. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD store. ms_save = zif_abapgit_default_transport~get( ). ENDMETHOD. METHOD zif_abapgit_default_transport~get. DATA lt_e070use TYPE STANDARD TABLE OF e070use WITH DEFAULT KEY. DATA ls_line LIKE LINE OF lt_e070use. CALL FUNCTION 'TR_TASK_GET' TABLES tt_e070use = lt_e070use EXCEPTIONS invalid_username = 1 invalid_category = 2 invalid_client = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. READ TABLE lt_e070use INTO ls_line INDEX 1. IF sy-subrc = 0. MOVE-CORRESPONDING ls_line TO rs_default_task. ENDIF. ENDMETHOD. METHOD zif_abapgit_default_transport~reset. DATA: ls_default_task TYPE e070use. IF mv_is_set_by_abapgit = abap_false. " if the default transport request task isn't set " by us there is nothing to do. RETURN. ENDIF. CLEAR mv_is_set_by_abapgit. ls_default_task = zif_abapgit_default_transport~get( ). IF ls_default_task IS NOT INITIAL. clear( ls_default_task ). ENDIF. restore( ). ENDMETHOD. METHOD zif_abapgit_default_transport~set. " checks whether object changes of the package are reordered in transport " requests. If true then we set the default task, so that no annoying " transport request popups are shown while deserializing. IF mv_is_set_by_abapgit = abap_true. " the default transport request task is already set by us " -> no reason to do it again. RETURN. ENDIF. IF iv_transport IS INITIAL. zcx_abapgit_exception=>raise( |No transport request was supplied| ). ENDIF. set_internal( iv_transport ). mv_is_set_by_abapgit = abap_true. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_cts_api IMPLEMENTATION. METHOD get_current_transport_for_obj. DATA: lv_object_lockable TYPE abap_bool, lv_locked TYPE abap_bool, lv_transport_request TYPE trkorr, lv_task TYPE trkorr, lv_tr_object_name TYPE trobj_name. lv_tr_object_name = iv_object_name. CALL FUNCTION 'TR_CHECK_OBJECT_LOCK' EXPORTING wi_pgmid = iv_program_id wi_object = iv_object_type wi_objname = lv_tr_object_name IMPORTING we_lockable_object = lv_object_lockable we_locked = lv_locked we_lock_order = lv_transport_request we_lock_task = lv_task EXCEPTIONS empty_key = 1 no_systemname = 2 no_systemtype = 3 unallowed_lock_order = 4 OTHERS = 5. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF lv_locked = abap_false. zcx_abapgit_exception=>raise( |Object { iv_program_id }-{ iv_object_type }-{ iv_object_name } is not locked| ). ENDIF. IF lv_object_lockable = abap_false. zcx_abapgit_exception=>raise( |Object type { iv_program_id }-{ iv_object_type } not lockable| ). ENDIF. rv_transport = lv_transport_request. ENDMETHOD. METHOD get_current_transport_from_db. " This method is used for objects that are included in transports but not locked " for example, namespaces (NSPC) SELECT SINGLE a~trkorr FROM e070 AS a JOIN e071 AS b ON a~trkorr = b~trkorr INTO rv_transport WHERE ( a~trstatus = 'D' OR a~trstatus = 'L' ) AND a~trfunction <> 'G' AND b~pgmid = iv_program_id AND b~object = iv_object_type AND b~obj_name = iv_object_name. ENDMETHOD. METHOD is_object_locked_in_transport. DATA: ls_object_key TYPE e071, lv_type_check_result TYPE c LENGTH 1, ls_lock_key TYPE tlock_int, lv_lock_flag TYPE c LENGTH 1. ls_object_key-pgmid = iv_program_id. ls_object_key-object = iv_object_type. ls_object_key-obj_name = iv_object_name. CALL FUNCTION 'TR_CHECK_TYPE' EXPORTING wi_e071 = ls_object_key IMPORTING pe_result = lv_type_check_result we_lock_key = ls_lock_key. IF lv_type_check_result <> 'L'. zcx_abapgit_exception=>raise( |Object type { iv_program_id }-{ iv_object_type } not lockable| ). ENDIF. CALL FUNCTION 'TRINT_CHECK_LOCKS' EXPORTING wi_lock_key = ls_lock_key IMPORTING we_lockflag = lv_lock_flag EXCEPTIONS empty_key = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. rv_locked = boolc( lv_lock_flag <> space ). ENDMETHOD. METHOD is_object_type_lockable. DATA: ls_object_key TYPE e071, lv_type_check_result TYPE c LENGTH 1. ls_object_key-pgmid = iv_program_id. ls_object_key-object = iv_object_type. ls_object_key-obj_name = '_'. " Dummy value #2071 CALL FUNCTION 'TR_CHECK_TYPE' EXPORTING wi_e071 = ls_object_key IMPORTING pe_result = lv_type_check_result. rv_lockable = boolc( lv_type_check_result = 'L' ). ENDMETHOD. METHOD is_object_type_transportable. DATA: ls_object_key TYPE e071, lv_type_check_result TYPE c LENGTH 1. ls_object_key-pgmid = iv_program_id. ls_object_key-object = iv_object_type. ls_object_key-obj_name = '_'. " Dummy value #2071 CALL FUNCTION 'TR_CHECK_TYPE' EXPORTING wi_e071 = ls_object_key IMPORTING pe_result = lv_type_check_result. rv_transportable = boolc( lv_type_check_result CA 'RTL' ). ENDMETHOD. METHOD zif_abapgit_cts_api~change_transport_type. DATA: ls_request_header TYPE trwbo_request_header, lt_request_headers TYPE trwbo_request_headers. CALL FUNCTION 'ENQUEUE_E_TRKORR' EXPORTING trkorr = iv_transport_request EXCEPTIONS foreign_lock = 1 system_failure = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'TR_READ_REQUEST_WITH_TASKS' EXPORTING iv_trkorr = iv_transport_request IMPORTING et_request_headers = lt_request_headers EXCEPTIONS invalid_input = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. LOOP AT lt_request_headers INTO ls_request_header WHERE trfunction = iv_transport_type_from. CALL FUNCTION 'TRINT_READ_REQUEST_HEADER' EXPORTING iv_read_e070 = abap_true iv_read_e070c = abap_true CHANGING cs_request = ls_request_header EXCEPTIONS empty_trkorr = 1 not_exist_e070 = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CALL FUNCTION 'TRINT_CHANGE_TRFUNCTION' EXPORTING iv_new_trfunction = iv_transport_type_to CHANGING cs_request_header = ls_request_header EXCEPTIONS action_aborted_by_user = 1 change_not_allowed = 2 db_access_error = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. CALL FUNCTION 'DEQUEUE_E_TRKORR' EXPORTING trkorr = iv_transport_request. ENDMETHOD. METHOD zif_abapgit_cts_api~confirm_transport_messages. TYPES: BEGIN OF ty_s_message, id TYPE symsgid, ty TYPE symsgty, no TYPE symsgno, v1 TYPE symsgv, v2 TYPE symsgv, v3 TYPE symsgv, v4 TYPE symsgv, END OF ty_s_message. DATA ls_message TYPE ty_s_message. FIELD-SYMBOLS: TYPE STANDARD TABLE. IF mv_confirm_transp_msgs_called = abap_true. RETURN. ENDIF. " remember the call to avoid duplicates in GT_CONFIRMED_MESSAGES mv_confirm_transp_msgs_called = abap_true. " Auto-confirm certain messages (requires SAP Note 1609940) PERFORM dummy IN PROGRAM saplstrd IF FOUND. "load function group STRD once into memory ASSIGN ('(SAPLSTRD)GT_CONFIRMED_MESSAGES') TO . IF sy-subrc <> 0. RETURN. ENDIF. " Object can only be created in package of namespace ls_message-id = 'TR'. ls_message-no = '007'. INSERT ls_message INTO TABLE . " Original system set to "SAP" ls_message-id = 'TR'. ls_message-no = '013'. INSERT ls_message INTO TABLE . " Make repairs in foreign namespaces only if they are urgent ls_message-id = 'TR'. ls_message-no = '852'. INSERT ls_message INTO TABLE . " Make repairs in foreign namespaces only if they are urgent ls_message-id = 'TK'. ls_message-no = '016'. INSERT ls_message INTO TABLE . rv_messages_confirmed = abap_true. ENDMETHOD. METHOD zif_abapgit_cts_api~create_transport_entries. DATA lt_tables TYPE tredt_objects. DATA lt_table_keys TYPE STANDARD TABLE OF e071k. DATA lv_with_dialog TYPE abap_bool. cl_table_utilities_brf=>create_transport_entries( EXPORTING it_table_ins = it_table_ins it_table_upd = it_table_upd it_table_del = it_table_del iv_tabname = iv_tabname CHANGING ct_e071 = lt_tables ct_e071k = lt_table_keys ). " cl_table_utilities_brf=>write_transport_entries does not allow passing a request CALL FUNCTION 'TR_OBJECTS_CHECK' TABLES wt_ko200 = lt_tables EXCEPTIONS cancel_edit_other_error = 1 show_only_other_error = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. IF iv_transport IS INITIAL. lv_with_dialog = abap_true. ENDIF. CALL FUNCTION 'TRINT_OBJECTS_CHECK_AND_INSERT' EXPORTING iv_order = iv_transport iv_with_dialog = lv_with_dialog CHANGING ct_ko200 = lt_tables ct_e071k = lt_table_keys EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_cts_api~get_r3tr_obj_for_limu_obj. CLEAR ev_object. CLEAR ev_obj_name. IF iv_object = 'MESS'. ev_object = 'MSAG'. ev_obj_name = substring( val = iv_obj_name len = strlen( iv_obj_name ) - 3 ). RETURN. ENDIF. CALL FUNCTION 'GET_R3TR_OBJECT_FROM_LIMU_OBJ' EXPORTING p_limu_objtype = iv_object p_limu_objname = iv_obj_name IMPORTING p_r3tr_objtype = ev_object p_r3tr_objname = ev_obj_name EXCEPTIONS no_mapping = 1 OTHERS = 2. IF sy-subrc <> 0 OR ev_obj_name IS INITIAL. zcx_abapgit_exception=>raise( |No R3TR Object found for { iv_object } { iv_obj_name }| ). ENDIF. ENDMETHOD. METHOD zif_abapgit_cts_api~get_transports_for_list. DATA lv_request TYPE trkorr. DATA lt_tlock TYPE SORTED TABLE OF tlock WITH NON-UNIQUE KEY object hikey. DATA ls_object_key TYPE e071. DATA lv_type_check_result TYPE c LENGTH 1. DATA ls_lock_key TYPE tlock_int. DATA ls_transport LIKE LINE OF rt_transports. FIELD-SYMBOLS LIKE LINE OF it_items. FIELD-SYMBOLS LIKE LINE OF lt_tlock. * Workarounds to improve performance, note that IT_ITEMS might * contain 1000s of rows, see standard logic in function module * TR_CHECK_OBJECT_LOCK * avoid database lookups in TLOCK for each item, SELECT * FROM tlock INTO TABLE lt_tlock. IF sy-subrc <> 0. RETURN. ENDIF. LOOP AT it_items ASSIGNING . CLEAR lv_request. ls_object_key-pgmid = 'R3TR'. ls_object_key-object = -obj_type. ls_object_key-obj_name = -obj_name. CALL FUNCTION 'TR_CHECK_TYPE' EXPORTING wi_e071 = ls_object_key IMPORTING we_lock_key = ls_lock_key pe_result = lv_type_check_result. IF lv_type_check_result = 'L'. LOOP AT lt_tlock ASSIGNING WHERE object = ls_lock_key-obj AND hikey >= ls_lock_key-low AND lokey <= ls_lock_key-hi. "#EC PORTABLE lv_request = -trkorr. EXIT. ENDLOOP. ELSEIF is_object_type_transportable( -obj_type ) = abap_true. lv_request = get_current_transport_from_db( iv_object_type = -obj_type iv_object_name = -obj_name ). ENDIF. IF lv_request IS NOT INITIAL. ls_transport-obj_type = -obj_type. ls_transport-obj_name = -obj_name. ls_transport-trkorr = lv_request. INSERT ls_transport INTO TABLE rt_transports. ENDIF. ENDLOOP. ENDMETHOD. METHOD zif_abapgit_cts_api~get_transport_for_object. IF is_item-obj_type IS NOT INITIAL AND is_item-obj_name IS NOT INITIAL. IF is_object_type_lockable( is_item-obj_type ) = abap_true AND is_object_locked_in_transport( iv_object_type = is_item-obj_type iv_object_name = is_item-obj_name ) = abap_true. rv_transport = get_current_transport_for_obj( iv_object_type = is_item-obj_type iv_object_name = is_item-obj_name ). ELSEIF is_object_type_transportable( is_item-obj_type ) = abap_true. rv_transport = get_current_transport_from_db( iv_object_type = is_item-obj_type iv_object_name = is_item-obj_name ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_cts_api~insert_transport_object. CALL FUNCTION 'RS_CORR_INSERT' EXPORTING object = iv_obj_name object_class = iv_object devclass = iv_package master_language = iv_language mode = iv_mode global_lock = abap_true suppress_dialog = abap_true EXCEPTIONS cancelled = 1 permission_failure = 2 unknown_objectclass = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_cts_api~is_chrec_possible_for_package. IF iv_package IS NOT INITIAL. rv_possible = zcl_abapgit_factory=>get_sap_package( iv_package )->are_changes_recorded_in_tr_req( ). ENDIF. ENDMETHOD. METHOD zif_abapgit_cts_api~list_open_requests_by_user. TYPES: BEGIN OF ty_e070, trkorr TYPE e070-trkorr, trfunction TYPE e070-trfunction, strkorr TYPE e070-strkorr, END OF ty_e070. DATA lt_e070 TYPE STANDARD TABLE OF ty_e070 WITH DEFAULT KEY. * find all tasks first SELECT trkorr trfunction strkorr FROM e070 INTO TABLE lt_e070 WHERE as4user = sy-uname AND trstatus = zif_abapgit_cts_api=>c_transport_status-modifiable AND strkorr <> '' ORDER BY PRIMARY KEY. IF lines( lt_e070 ) > 0. SELECT trkorr FROM e070 INTO TABLE rt_trkorr FOR ALL ENTRIES IN lt_e070 WHERE trkorr = lt_e070-strkorr AND trfunction = zif_abapgit_cts_api=>c_transport_type-wb_request. ENDIF. ENDMETHOD. METHOD zif_abapgit_cts_api~list_r3tr_by_request. TYPES: BEGIN OF ty_contents, trkorr TYPE e071-trkorr, as4pos TYPE e071-as4pos, pgmid TYPE e071-pgmid, object TYPE e071-object, obj_name TYPE e071-obj_name, END OF ty_contents. DATA lt_tasks TYPE STANDARD TABLE OF trkorr WITH DEFAULT KEY. DATA lt_contents TYPE STANDARD TABLE OF ty_contents WITH DEFAULT KEY. DATA ls_contents LIKE LINE OF lt_contents. DATA ls_list LIKE LINE OF rt_list. SELECT trkorr FROM e070 INTO TABLE lt_tasks WHERE strkorr = iv_request ORDER BY PRIMARY KEY. IF sy-subrc <> 0. RETURN. ENDIF. SELECT trkorr as4pos pgmid object obj_name FROM e071 INTO TABLE lt_contents FOR ALL ENTRIES IN lt_tasks WHERE trkorr = lt_tasks-table_line ORDER BY PRIMARY KEY. IF sy-subrc <> 0. RETURN. ENDIF. LOOP AT lt_contents INTO ls_contents. CASE ls_contents-pgmid. WHEN 'R3TR'. ls_list-object = ls_contents-object. ls_list-obj_name = ls_contents-obj_name. INSERT ls_list INTO TABLE rt_list. WHEN 'LIMU'. TRY. zif_abapgit_cts_api~get_r3tr_obj_for_limu_obj( EXPORTING iv_object = ls_contents-object iv_obj_name = ls_contents-obj_name IMPORTING ev_object = ls_list-object ev_obj_name = ls_list-obj_name ). INSERT ls_list INTO TABLE rt_list. CATCH zcx_abapgit_exception. ENDTRY. ENDCASE. ENDLOOP. SORT rt_list BY object obj_name. DELETE ADJACENT DUPLICATES FROM rt_list COMPARING object obj_name. ENDMETHOD. METHOD zif_abapgit_cts_api~read. DATA ls_request TYPE trwbo_request. DATA ls_key LIKE LINE OF ls_request-keys. FIELD-SYMBOLS LIKE LINE OF rs_request-keys. ls_request-h-trkorr = iv_trkorr. CALL FUNCTION 'TRINT_READ_REQUEST' EXPORTING iv_read_e070 = abap_true iv_read_e07t = abap_true iv_read_e070c = abap_true iv_read_e070m = abap_true iv_read_objs_keys = abap_true iv_read_objs = abap_true iv_read_attributes = abap_true CHANGING cs_request = ls_request EXCEPTIONS error_occured = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. * move to output structure rs_request-trstatus = ls_request-h-trstatus. LOOP AT ls_request-keys INTO ls_key. APPEND INITIAL LINE TO rs_request-keys ASSIGNING . MOVE-CORRESPONDING ls_key TO . ENDLOOP. ENDMETHOD. METHOD zif_abapgit_cts_api~read_description. SELECT SINGLE as4text FROM e07t INTO rv_description WHERE trkorr = iv_trkorr AND langu = sy-langu ##SUBRC_OK. ENDMETHOD. METHOD zif_abapgit_cts_api~read_user. SELECT SINGLE as4user FROM e070 INTO rv_uname WHERE trkorr = iv_trkorr ##SUBRC_OK. ENDMETHOD. METHOD zif_abapgit_cts_api~validate_transport_request. CONSTANTS: BEGIN OF c_tr_status, modifiable TYPE trstatus VALUE 'D', modifiable_protected TYPE trstatus VALUE 'L', END OF c_tr_status. DATA ls_request TYPE zif_abapgit_cts_api=>ty_transport_data. ls_request = zif_abapgit_cts_api~read( iv_transport_request ). IF ls_request-trstatus <> c_tr_status-modifiable AND ls_request-trstatus <> c_tr_status-modifiable_protected. " Task/request &1 has already been released MESSAGE e064(tk) WITH iv_transport_request INTO zcx_abapgit_exception=>null. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_background_push_fi IMPLEMENTATION. METHOD build_comment. DATA: lt_objects TYPE STANDARD TABLE OF string WITH DEFAULT KEY, lv_str TYPE string. FIELD-SYMBOLS: LIKE LINE OF is_files-local. LOOP AT is_files-local ASSIGNING . lv_str = |{ -item-obj_type } { -item-obj_name }|. APPEND lv_str TO lt_objects. ENDLOOP. SORT lt_objects AS TEXT. DELETE ADJACENT DUPLICATES FROM lt_objects. IF lines( lt_objects ) = 1. rv_comment = |BG: { lv_str }|. ELSE. rv_comment = 'BG: Multiple objects'. LOOP AT lt_objects INTO lv_str. CONCATENATE rv_comment cl_abap_char_utilities=>newline lv_str INTO rv_comment. ENDLOOP. ENDIF. ENDMETHOD. METHOD push_fixed. DATA: ls_comment TYPE zif_abapgit_git_definitions=>ty_comment, ls_files TYPE zif_abapgit_definitions=>ty_stage_files, lo_stage TYPE REF TO zcl_abapgit_stage. FIELD-SYMBOLS: LIKE LINE OF ls_files-local, LIKE LINE OF ls_files-remote. ls_files = zcl_abapgit_factory=>get_stage_logic( )->get( io_repo ). ASSERT lines( ls_files-local ) > 0 OR lines( ls_files-remote ) > 0. CREATE OBJECT lo_stage. LOOP AT ls_files-local ASSIGNING . mi_log->add_info( |stage: { -file-path } { -file-filename }| ). lo_stage->add( iv_path = -file-path iv_filename = -file-filename iv_data = -file-data ). ENDLOOP. LOOP AT ls_files-remote ASSIGNING . mi_log->add_info( |removed: { -path } { -filename }| ). lo_stage->rm( iv_path = -path iv_filename = -filename ). ENDLOOP. ls_comment-committer-name = iv_name. ls_comment-committer-email = iv_email. ls_comment-comment = build_comment( ls_files ). io_repo->push( is_comment = ls_comment io_stage = lo_stage ). ENDMETHOD. METHOD zif_abapgit_background~get_description. rv_description = 'Automatic push, fixed author'. ENDMETHOD. METHOD zif_abapgit_background~get_settings. DATA: ls_setting LIKE LINE OF ct_settings. READ TABLE ct_settings WITH KEY key = c_settings-name INTO ls_setting. IF sy-subrc <> 0. ls_setting-key = c_settings-name. ls_setting-value = 'foobar'. APPEND ls_setting TO ct_settings. ENDIF. READ TABLE ct_settings WITH KEY key = c_settings-email INTO ls_setting. IF sy-subrc <> 0. ls_setting-key = c_settings-email. ls_setting-value = 'foobar@localhost'. APPEND ls_setting TO ct_settings. ENDIF. ENDMETHOD. METHOD zif_abapgit_background~run. DATA: ls_files TYPE zif_abapgit_definitions=>ty_stage_files, ls_setting LIKE LINE OF it_settings, lv_name TYPE string, lv_email TYPE string. mi_log = ii_log. ls_files = zcl_abapgit_factory=>get_stage_logic( )->get( io_repo ). IF lines( ls_files-local ) = 0 AND lines( ls_files-remote ) = 0. ii_log->add_info( 'Nothing to stage' ). RETURN. ENDIF. READ TABLE it_settings WITH KEY key = c_settings-name INTO ls_setting. "#EC CI_SUBRC lv_name = ls_setting-value. READ TABLE it_settings WITH KEY key = c_settings-email INTO ls_setting. "#EC CI_SUBRC lv_email = ls_setting-value. push_fixed( io_repo = io_repo iv_name = lv_name iv_email = lv_email ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_background_push_au IMPLEMENTATION. METHOD build_comment. DATA: lt_objects TYPE STANDARD TABLE OF string WITH DEFAULT KEY, lv_str TYPE string. FIELD-SYMBOLS: LIKE LINE OF is_files-local. LOOP AT is_files-local ASSIGNING . lv_str = |{ -item-obj_type } { -item-obj_name }|. APPEND lv_str TO lt_objects. ENDLOOP. SORT lt_objects AS TEXT. DELETE ADJACENT DUPLICATES FROM lt_objects. IF lines( lt_objects ) = 1. rv_comment = |BG: { lv_str }|. ELSE. rv_comment = 'BG: Multiple objects'. LOOP AT lt_objects INTO lv_str. CONCATENATE rv_comment cl_abap_char_utilities=>newline lv_str INTO rv_comment. ENDLOOP. ENDIF. ENDMETHOD. METHOD determine_user_details. DATA: lo_user_record TYPE REF TO zcl_abapgit_user_record. lo_user_record = zcl_abapgit_user_record=>get_instance( iv_changed_by ). rs_user-name = lo_user_record->get_name( ). rs_user-email = lo_user_record->get_email( ). * If no email, fall back to localhost/default email IF rs_user-email IS INITIAL. rs_user-email = |{ iv_changed_by }@localhost|. ENDIF. * If no full name maintained, just use changed by user name IF rs_user-name IS INITIAL. rs_user-name = iv_changed_by. ENDIF. ENDMETHOD. METHOD push_auto. TYPES: BEGIN OF ty_changed, filename TYPE string, path TYPE string, changed_by TYPE syuname, END OF ty_changed. DATA: ls_comment TYPE zif_abapgit_git_definitions=>ty_comment, ls_files TYPE zif_abapgit_definitions=>ty_stage_files, lt_changed TYPE STANDARD TABLE OF ty_changed WITH DEFAULT KEY, lt_users TYPE STANDARD TABLE OF syuname WITH DEFAULT KEY, ls_user_files LIKE ls_files, lv_changed_by LIKE LINE OF lt_users, lo_stage TYPE REF TO zcl_abapgit_stage. FIELD-SYMBOLS: LIKE LINE OF lt_changed, LIKE LINE OF ls_files-remote, LIKE LINE OF ls_files-local. ls_files = zcl_abapgit_factory=>get_stage_logic( )->get( io_repo ). LOOP AT ls_files-local ASSIGNING . lv_changed_by = zcl_abapgit_objects=>changed_by( is_item = -item iv_filename = -file-filename ). APPEND lv_changed_by TO lt_users. APPEND INITIAL LINE TO lt_changed ASSIGNING . -changed_by = lv_changed_by. -filename = -file-filename. -path = -file-path. ENDLOOP. SORT lt_users ASCENDING. DELETE ADJACENT DUPLICATES FROM lt_users. LOOP AT lt_users INTO lv_changed_by. CLEAR: ls_comment. * Fill user details ls_comment-committer = determine_user_details( lv_changed_by ). CREATE OBJECT lo_stage. CLEAR ls_user_files. LOOP AT ls_files-local ASSIGNING . READ TABLE lt_changed WITH KEY path = -file-path filename = -file-filename changed_by = lv_changed_by TRANSPORTING NO FIELDS. IF sy-subrc = 0. mi_log->add_info( |stage: { ls_comment-committer-name } { -file-path } { -file-filename }| ). lo_stage->add( iv_path = -file-path iv_filename = -file-filename iv_data = -file-data ). APPEND TO ls_user_files-local. LOOP AT ls_files-remote ASSIGNING USING KEY file WHERE filename = -file-filename AND path <> -file-path AND filename <> 'package.devc.xml'. mi_log->add_info( |rm: { -path } { -filename }| ). * rm old file when object has moved lo_stage->rm( iv_path = -path iv_filename = -filename ). EXIT. " assumption: only one file ENDLOOP. ENDIF. ENDLOOP. ls_comment-comment = build_comment( ls_user_files ). io_repo->push( is_comment = ls_comment io_stage = lo_stage ). ENDLOOP. IF lines( ls_files-remote ) > 0. push_deletions( io_repo = io_repo is_files = ls_files ). ENDIF. ENDMETHOD. METHOD push_deletions. DATA: lo_stage TYPE REF TO zcl_abapgit_stage, ls_comment TYPE zif_abapgit_git_definitions=>ty_comment. FIELD-SYMBOLS: LIKE LINE OF is_files-remote. ASSERT lines( is_files-remote ) > 0. CREATE OBJECT lo_stage. ls_comment-comment = 'BG: Deletion'. LOOP AT is_files-remote ASSIGNING . mi_log->add_info( |removed: { -path } { -filename }| ). lo_stage->rm( iv_path = -path iv_filename = -filename ). CONCATENATE ls_comment-comment cl_abap_char_utilities=>newline -filename INTO ls_comment-comment. ENDLOOP. ls_comment-committer-name = 'Deletion'. ls_comment-committer-email = 'deletion@localhost'. io_repo->push( is_comment = ls_comment io_stage = lo_stage ). ENDMETHOD. METHOD zif_abapgit_background~get_description. rv_description = 'Automatic push, auto author'. ENDMETHOD. METHOD zif_abapgit_background~get_settings. RETURN. ENDMETHOD. METHOD zif_abapgit_background~run. DATA: ls_files TYPE zif_abapgit_definitions=>ty_stage_files. mi_log = ii_log. ls_files = zcl_abapgit_factory=>get_stage_logic( )->get( io_repo ). IF lines( ls_files-local ) = 0 AND lines( ls_files-remote ) = 0. ii_log->add_info( 'Nothing to stage' ). RETURN. ENDIF. push_auto( io_repo ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_background_pull IMPLEMENTATION. METHOD zif_abapgit_background~get_description. rv_description = 'Automatic pull'. ENDMETHOD. METHOD zif_abapgit_background~get_settings. RETURN. ENDMETHOD. METHOD zif_abapgit_background~run. DATA: ls_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks. FIELD-SYMBOLS: LIKE LINE OF ls_checks-overwrite. ls_checks = io_repo->deserialize_checks( ). LOOP AT ls_checks-overwrite ASSIGNING . -decision = zif_abapgit_definitions=>c_yes. ENDLOOP. io_repo->deserialize( is_checks = ls_checks ii_log = ii_log ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_background IMPLEMENTATION. METHOD dequeue. CALL FUNCTION 'DEQUEUE_EZABAPGIT' EXPORTING type = c_enq_type. ENDMETHOD. METHOD enqueue. CALL FUNCTION 'ENQUEUE_EZABAPGIT' EXPORTING mode_zabapgit = 'E' type = c_enq_type _scope = '3' EXCEPTIONS foreign_lock = 1 system_failure = 2 OTHERS = 3. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD list_methods. DATA: ls_method LIKE LINE OF rt_methods, ls_key TYPE seoclskey, lt_implementing TYPE seor_implementing_keys, ls_implementing LIKE LINE OF lt_implementing. FIELD-SYMBOLS: LIKE LINE OF rt_methods. * in order to handle local classes in the compiled report ls_method-class = 'ZCL_ABAPGIT_BACKGROUND_PULL'. INSERT ls_method INTO TABLE rt_methods. ls_method-class = 'ZCL_ABAPGIT_BACKGROUND_PUSH_AU'. INSERT ls_method INTO TABLE rt_methods. ls_method-class = 'ZCL_ABAPGIT_BACKGROUND_PUSH_FI'. INSERT ls_method INTO TABLE rt_methods. ls_key-clsname = 'ZIF_ABAPGIT_BACKGROUND'. CALL FUNCTION 'SEO_INTERFACE_IMPLEM_GET_ALL' EXPORTING intkey = ls_key IMPORTING impkeys = lt_implementing EXCEPTIONS not_existing = 1 OTHERS = 2 ##FM_SUBRC_OK. LOOP AT lt_implementing INTO ls_implementing. ls_method-class = ls_implementing-clsname. INSERT ls_method INTO TABLE rt_methods. ENDLOOP. LOOP AT rt_methods ASSIGNING . CALL METHOD (-class)=>zif_abapgit_background~get_description RECEIVING rv_description = -description. ENDLOOP. ENDMETHOD. METHOD run. DATA: lo_per TYPE REF TO zcl_abapgit_persist_background, lo_repo TYPE REF TO zcl_abapgit_repo_online, lt_list TYPE zcl_abapgit_persist_background=>ty_background_keys, li_background TYPE REF TO zif_abapgit_background, li_log TYPE REF TO zif_abapgit_log, lx_error TYPE REF TO zcx_abapgit_exception, lv_repo_name TYPE string. FIELD-SYMBOLS: LIKE LINE OF lt_list. TRY. enqueue( ). CATCH zcx_abapgit_exception. WRITE: / 'Another instance of the program is already running'. RETURN. ENDTRY. CREATE OBJECT lo_per. lt_list = lo_per->list( ). WRITE: / 'Background mode'. LOOP AT lt_list ASSIGNING . CREATE OBJECT li_log TYPE zcl_abapgit_log. TRY. lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( -key ). lv_repo_name = lo_repo->get_name( ). WRITE: / -method, lv_repo_name. zcl_abapgit_login_manager=>set( iv_uri = lo_repo->get_url( ) iv_username = -username iv_password = -password ). CREATE OBJECT li_background TYPE (-method). li_background->run( io_repo = lo_repo ii_log = li_log it_settings = -settings ). " Decrease memory usage for repository already processed (but keep log) lo_repo->refresh( iv_drop_cache = abap_true iv_drop_log = abap_false ). CATCH zcx_abapgit_exception INTO lx_error. li_log->add_exception( lx_error ). ENDTRY. " Clear auth buffer to allow different user/password per repository in background mode zcl_abapgit_login_manager=>clear( ). zcl_abapgit_log_viewer=>write_log( li_log ). ENDLOOP. IF lines( lt_list ) = 0. WRITE: / 'Nothing configured'. ENDIF. dequeue( ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_apack_writer IMPLEMENTATION. METHOD constructor. ms_manifest_descriptor = is_apack_manifest_descriptor. ENDMETHOD. METHOD create_instance. CREATE OBJECT ro_manifest_writer EXPORTING is_apack_manifest_descriptor = is_apack_manifest_descriptor. ENDMETHOD. METHOD serialize. DATA: ls_manifest_descriptor LIKE ms_manifest_descriptor. FIELD-SYMBOLS: LIKE LINE OF ls_manifest_descriptor-dependencies. " Setting repository type automatically to 'abapGit' as there is no other one right now ms_manifest_descriptor-repository_type = zif_abapgit_apack_definitions=>c_repository_type_abapgit. ls_manifest_descriptor = ms_manifest_descriptor. CLEAR: ls_manifest_descriptor-sem_version. LOOP AT ls_manifest_descriptor-dependencies ASSIGNING . CLEAR: -sem_version. ENDLOOP. CALL TRANSFORMATION id OPTIONS initial_components = 'suppress' SOURCE data = ls_manifest_descriptor RESULT XML rv_xml. rv_xml = zcl_abapgit_xml_pretty=>print( rv_xml ). REPLACE FIRST OCCURRENCE OF REGEX '<\?xml version="1\.0" encoding="[\w-]+"\?>' IN rv_xml WITH ''. ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_apack_reader IMPLEMENTATION. METHOD constructor. ASSERT iv_package_name IS NOT INITIAL. mv_package_name = iv_package_name. ENDMETHOD. METHOD copy_manifest_descriptor. DATA: ls_my_manifest_wo_deps TYPE zif_abapgit_apack_definitions=>ty_descriptor_wo_dependencies, ls_my_dependency TYPE zif_abapgit_apack_definitions=>ty_dependency, ls_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor, lv_descriptor_cust TYPE string, lv_descriptor_sap TYPE string, lv_descriptor_nspc TYPE string, lv_class_name TYPE abap_abstypename, lv_empty TYPE string, ls_namespace TYPE zif_abapgit_definitions=>ty_obj_namespace. FIELD-SYMBOLS: TYPE any, TYPE ANY TABLE, TYPE any. lv_descriptor_cust = zif_abapgit_apack_definitions=>c_apack_interface_cust && '~DESCRIPTOR'. lv_descriptor_sap = zif_abapgit_apack_definitions=>c_apack_interface_sap && '~DESCRIPTOR'. lv_class_name = cl_abap_classdescr=>get_class_name( io_manifest_provider ). SPLIT lv_class_name AT '\CLASS=' INTO lv_empty lv_class_name. ls_namespace = zcl_abapgit_factory=>get_sap_namespace( )->split_by_name( lv_class_name ). IF ls_namespace-namespace IS NOT INITIAL. lv_descriptor_nspc = |{ ls_namespace-namespace }{ lv_descriptor_sap }|. ENDIF. ASSIGN io_manifest_provider->(lv_descriptor_cust) TO . IF IS NOT ASSIGNED. ASSIGN io_manifest_provider->(lv_descriptor_sap) TO . IF IS NOT ASSIGNED AND lv_descriptor_nspc IS NOT INITIAL. ASSIGN io_manifest_provider->(lv_descriptor_nspc) TO . ENDIF. ENDIF. IF IS ASSIGNED. " A little more complex than a normal MOVE-CORRSPONDING " to avoid dumps in case of future updates to the dependencies table structure ASSIGN COMPONENT 'DEPENDENCIES' OF STRUCTURE TO . IF IS ASSIGNED. LOOP AT ASSIGNING . MOVE-CORRESPONDING TO ls_my_dependency. INSERT ls_my_dependency INTO TABLE ls_descriptor-dependencies. ENDLOOP. MOVE-CORRESPONDING TO ls_my_manifest_wo_deps. MOVE-CORRESPONDING ls_my_manifest_wo_deps TO ls_descriptor. ENDIF. ENDIF. set_manifest_descriptor( ls_descriptor ). ENDMETHOD. METHOD create_instance. DATA ls_instance TYPE ty_instance. " One instance per package READ TABLE gt_instances INTO ls_instance WITH TABLE KEY package = iv_package_name. IF sy-subrc <> 0. ls_instance-package = iv_package_name. CREATE OBJECT ls_instance-instance EXPORTING iv_package_name = iv_package_name. INSERT ls_instance INTO TABLE gt_instances. ENDIF. ro_manifest_reader = ls_instance-instance. ENDMETHOD. METHOD deserialize. DATA: lv_xml TYPE string, ls_data TYPE zif_abapgit_apack_definitions=>ty_descriptor. lv_xml = zcl_abapgit_convert=>xstring_to_string_utf8( iv_xstr ). ls_data = from_xml( lv_xml ). ro_manifest_reader = create_instance( iv_package_name ). ro_manifest_reader->set_manifest_descriptor( ls_data ). ENDMETHOD. METHOD format_version. FIELD-SYMBOLS: TYPE zif_abapgit_apack_definitions=>ty_dependency. TRANSLATE ms_cached_descriptor-version TO LOWER CASE. ms_cached_descriptor-sem_version = zcl_abapgit_version=>conv_str_to_version( ms_cached_descriptor-version ). LOOP AT ms_cached_descriptor-dependencies ASSIGNING . TRANSLATE -version TO LOWER CASE. -sem_version = zcl_abapgit_version=>conv_str_to_version( -version ). ENDLOOP. ENDMETHOD. METHOD from_xml. DATA: lv_xml TYPE string. lv_xml = iv_xml. CALL TRANSFORMATION id OPTIONS value_handling = 'accept_data_loss' SOURCE XML lv_xml RESULT data = rs_data. ENDMETHOD. METHOD get_manifest_descriptor. DATA: lo_manifest_provider TYPE REF TO object, lv_package TYPE devclass, lt_packages TYPE zif_abapgit_sap_package=>ty_devclass_tt, ls_manifest_implementation TYPE zif_abapgit_apack_definitions=>ty_manifest_declaration, lt_manifest_implementation TYPE zif_abapgit_apack_definitions=>ty_manifest_declarations. IF mv_is_cached IS INITIAL. lt_packages = zcl_abapgit_factory=>get_sap_package( mv_package_name )->list_subpackages( ). INSERT mv_package_name INTO TABLE lt_packages. lt_manifest_implementation = zcl_abapgit_apack_helper=>get_manifest_implementations( ). LOOP AT lt_packages INTO lv_package. READ TABLE lt_manifest_implementation INTO ls_manifest_implementation WITH KEY devclass = lv_package. IF sy-subrc = 0. EXIT. ENDIF. ENDLOOP. IF ls_manifest_implementation IS NOT INITIAL. TRY. CREATE OBJECT lo_manifest_provider TYPE (ls_manifest_implementation-clsname). CATCH cx_sy_create_object_error. CLEAR: rs_manifest_descriptor. ENDTRY. IF lo_manifest_provider IS BOUND. copy_manifest_descriptor( lo_manifest_provider ). ENDIF. ENDIF. mv_is_cached = abap_true. ENDIF. rs_manifest_descriptor = ms_cached_descriptor. ENDMETHOD. METHOD has_manifest. DATA: ls_returned_manifest TYPE zif_abapgit_apack_definitions=>ty_descriptor. ls_returned_manifest = get_manifest_descriptor( ). rv_has_manifest = boolc( ls_returned_manifest IS NOT INITIAL ). ENDMETHOD. METHOD refresh. CLEAR: mv_is_cached, ms_cached_descriptor. ENDMETHOD. METHOD set_manifest_descriptor. mv_is_cached = abap_true. ms_cached_descriptor = is_manifest_descriptor. format_version( ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_apack_migration IMPLEMENTATION. METHOD add_interface_source. DATA: lo_factory TYPE REF TO object, lo_source TYPE REF TO object, lt_source_code TYPE zif_abapgit_definitions=>ty_string_tt. "Buffer needs to be refreshed, "otherwise standard SAP CLIF_SOURCE reorder methods alphabetically CALL FUNCTION 'SEO_BUFFER_INIT'. CALL FUNCTION 'SEO_BUFFER_REFRESH' EXPORTING cifkey = is_clskey version = seoc_version_inactive. TRY. CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') RECEIVING result = lo_factory. CALL METHOD lo_factory->('CREATE_CLIF_SOURCE') EXPORTING clif_name = is_clskey-clsname RECEIVING result = lo_source. TRY. CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~LOCK'). CATCH cx_oo_access_permission. zcx_abapgit_exception=>raise( 'source_new, access permission exception' ). ENDTRY. lt_source_code = get_interface_source( ). CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~SET_SOURCE') EXPORTING source = lt_source_code. CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~SAVE'). CALL METHOD lo_source->('IF_OO_CLIF_SOURCE~UNLOCK'). CATCH cx_sy_dyn_call_error. add_interface_source_classic( is_clskey ). ENDTRY. ENDMETHOD. METHOD add_interface_source_classic. DATA: lo_source TYPE REF TO object, lt_source_code TYPE zif_abapgit_definitions=>ty_string_tt. CREATE OBJECT lo_source TYPE ('CL_OO_SOURCE') EXPORTING clskey = is_clskey EXCEPTIONS class_not_existing = 1 OTHERS = 2. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from CL_OO_SOURCE' ). ENDIF. TRY. CALL METHOD lo_source->('ACCESS_PERMISSION') EXPORTING access_mode = seok_access_modify. lt_source_code = get_interface_source( ). CALL METHOD lo_source->('SET_SOURCE') EXPORTING i_source = lt_source_code. CALL METHOD lo_source->('SAVE'). CALL METHOD lo_source->('ACCESS_PERMISSION') EXPORTING access_mode = seok_access_free. CATCH cx_oo_access_permission. zcx_abapgit_exception=>raise( 'permission error' ). CATCH cx_oo_source_save_failure. zcx_abapgit_exception=>raise( 'save failure' ). ENDTRY. ENDMETHOD. METHOD add_intf_source_and_activate. DATA: ls_clskey TYPE seoclskey, ls_inactive_object TYPE dwinactiv, lt_inactive_objects TYPE TABLE OF dwinactiv. ls_clskey-clsname = zif_abapgit_apack_definitions=>c_apack_interface_cust. add_interface_source( ls_clskey ). ls_inactive_object-object = 'INTF'. ls_inactive_object-obj_name = zif_abapgit_apack_definitions=>c_apack_interface_cust. INSERT ls_inactive_object INTO TABLE lt_inactive_objects. CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE' TABLES objects = lt_inactive_objects EXCEPTIONS excecution_error = 1 cancelled = 2 insert_into_corr_error = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD create_interface. DATA: ls_interface_properties TYPE vseointerf. ls_interface_properties-clsname = zif_abapgit_apack_definitions=>c_apack_interface_cust. ls_interface_properties-version = '1'. ls_interface_properties-langu = 'E'. ls_interface_properties-descript = 'APACK: Manifest interface'. ls_interface_properties-exposure = '2'. ls_interface_properties-state = '1'. ls_interface_properties-unicode = abap_true. TRY. CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' EXPORTING devclass = '$TMP' suppress_dialog = abap_true " Parameter missing in 702 CHANGING interface = ls_interface_properties EXCEPTIONS existing = 1 is_class = 2 db_error = 3 component_error = 4 no_access = 5 other = 6 OTHERS = 7. CATCH cx_sy_dyn_call_param_not_found. CALL FUNCTION 'SEO_INTERFACE_CREATE_COMPLETE' EXPORTING devclass = '$TMP' CHANGING interface = ls_interface_properties EXCEPTIONS existing = 1 is_class = 2 db_error = 3 component_error = 4 no_access = 5 other = 6 OTHERS = 7. ENDTRY. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. add_intf_source_and_activate( ). ENDMETHOD. METHOD get_interface_source. INSERT `INTERFACE zif_apack_manifest PUBLIC.` INTO TABLE rt_source. INSERT `` INTO TABLE rt_source. INSERT ` TYPES: BEGIN OF ty_dependency,` INTO TABLE rt_source. INSERT ` group_id TYPE string,` INTO TABLE rt_source. INSERT ` artifact_id TYPE string,` INTO TABLE rt_source. INSERT ` version TYPE string,` INTO TABLE rt_source. INSERT ` git_url TYPE string,` INTO TABLE rt_source. INSERT ` target_package TYPE devclass,` INTO TABLE rt_source. INSERT ` END OF ty_dependency,` INTO TABLE rt_source. INSERT ` ty_dependencies TYPE STANDARD TABLE OF ty_dependency` INTO TABLE rt_source. INSERT ` WITH NON-UNIQUE DEFAULT KEY,` INTO TABLE rt_source. INSERT ` ty_repository_type TYPE string,` INTO TABLE rt_source. INSERT ` BEGIN OF ty_descriptor,` INTO TABLE rt_source. INSERT ` group_id TYPE string,` INTO TABLE rt_source. INSERT ` artifact_id TYPE string,` INTO TABLE rt_source. INSERT ` version TYPE string,` INTO TABLE rt_source. INSERT ` repository_type TYPE ty_repository_type,` INTO TABLE rt_source. INSERT ` git_url TYPE string,` INTO TABLE rt_source. INSERT ` dependencies TYPE ty_dependencies,` INTO TABLE rt_source. INSERT ` END OF ty_descriptor.` INTO TABLE rt_source. INSERT `` INTO TABLE rt_source. INSERT ` CONSTANTS: co_file_name TYPE string VALUE '.apack-manifest.xml',` INTO TABLE rt_source. INSERT ` co_abap_git TYPE ty_repository_type VALUE 'abapGit',` INTO TABLE rt_source. INSERT ` co_interface_version TYPE i VALUE 1.` INTO TABLE rt_source. INSERT `` INTO TABLE rt_source. INSERT ` DATA: descriptor TYPE ty_descriptor READ-ONLY.` INTO TABLE rt_source. INSERT `` INTO TABLE rt_source. INSERT `ENDINTERFACE.` INTO TABLE rt_source. ENDMETHOD. METHOD interface_exists. DATA: lv_interface_name TYPE seoclsname. SELECT SINGLE clsname FROM seoclass INTO lv_interface_name WHERE clsname = zif_abapgit_apack_definitions=>c_apack_interface_cust. rv_interface_exists = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD interface_valid. FIELD-SYMBOLS: TYPE i. ASSIGN (zif_abapgit_apack_definitions=>c_apack_interface_cust)=>('CO_INTERFACE_VERSION') TO . rv_interface_valid = boolc( IS ASSIGNED AND >= c_apack_interface_version ). ENDMETHOD. METHOD perform_migration. IF interface_exists( ) = abap_false. create_interface( ). ELSEIF interface_valid( ) = abap_false. add_intf_source_and_activate( ). ENDIF. ENDMETHOD. METHOD run. DATA: lo_apack_migration TYPE REF TO zcl_abapgit_apack_migration. CREATE OBJECT lo_apack_migration. lo_apack_migration->perform_migration( ). ENDMETHOD. ENDCLASS. CLASS zcl_abapgit_apack_helper IMPLEMENTATION. METHOD are_dependencies_met. DATA: lt_dependencies_status TYPE ty_dependency_statuses. IF it_dependencies IS INITIAL. rv_status = zif_abapgit_definitions=>c_yes. RETURN. ENDIF. lt_dependencies_status = get_dependencies_met_status( it_dependencies ). LOOP AT lt_dependencies_status TRANSPORTING NO FIELDS WHERE met <> zif_abapgit_definitions=>c_yes. EXIT. ENDLOOP. IF sy-subrc = 0. rv_status = zif_abapgit_definitions=>c_no. ELSE. rv_status = zif_abapgit_definitions=>c_yes. ENDIF. ENDMETHOD. METHOD dependencies_popup. DATA: lt_met_status TYPE ty_dependency_statuses, lv_answer TYPE c LENGTH 1. lt_met_status = get_dependencies_met_status( it_dependencies ). show_dependencies_popup( lt_met_status ). lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = 'Warning' iv_text_question = 'The project has unmet dependencies. Do you want to continue?' ). IF lv_answer <> '1'. zcx_abapgit_exception=>raise( 'Cancelling because of unmet dependencies.' ). ENDIF. ENDMETHOD. METHOD get_color_table. DATA: lo_functional_settings TYPE REF TO cl_salv_functional_settings, lo_hyperlinks TYPE REF TO cl_salv_hyperlinks, lt_color_negative TYPE lvc_t_scol, lt_color_normal TYPE lvc_t_scol, lt_color_positive TYPE lvc_t_scol, ls_color TYPE lvc_s_scol, lv_handle TYPE i, ls_hyperlink TYPE salv_s_int4_column, lv_hyperlink TYPE service_rl. FIELD-SYMBOLS: TYPE ty_color_line, LIKE LINE OF it_dependencies. CLEAR: ls_color. ls_color-color-col = col_negative. APPEND ls_color TO lt_color_negative. CLEAR: ls_color. ls_color-color-col = col_normal. APPEND ls_color TO lt_color_normal. CLEAR: ls_color. ls_color-color-col = col_positive. APPEND ls_color TO lt_color_positive. lo_functional_settings = io_alv->get_functional_settings( ). lo_hyperlinks = lo_functional_settings->get_hyperlinks( ). CLEAR: lv_handle, ls_color. LOOP AT it_dependencies ASSIGNING . lv_handle = lv_handle + 1. APPEND INITIAL LINE TO ct_color_table ASSIGNING . MOVE-CORRESPONDING TO . CASE -met. WHEN zif_abapgit_definitions=>c_yes. -color = lt_color_positive. -exception = '3'. WHEN zif_abapgit_definitions=>c_partial. -color = lt_color_normal. -exception = '2'. WHEN zif_abapgit_definitions=>c_no. -color = lt_color_negative. -exception = '1'. ENDCASE. CLEAR: ls_hyperlink. ls_hyperlink-columnname = 'GIT_URL'. ls_hyperlink-value = lv_handle. APPEND ls_hyperlink TO -t_hyperlink. lv_hyperlink = -git_url. lo_hyperlinks->add_hyperlink( handle = lv_handle hyperlink = lv_hyperlink ). ENDLOOP. ENDMETHOD. METHOD get_dependencies_met_status. DATA: lt_installed_packages TYPE zif_abapgit_apack_definitions=>ty_descriptors, ls_installed_package TYPE zif_abapgit_apack_definitions=>ty_descriptor, ls_dependecy TYPE zif_abapgit_apack_definitions=>ty_dependency, ls_dependecy_popup TYPE ty_dependency_status. IF it_dependencies IS INITIAL. RETURN. ENDIF. lt_installed_packages = get_installed_packages( ). LOOP AT it_dependencies INTO ls_dependecy. CLEAR: ls_dependecy_popup. MOVE-CORRESPONDING ls_dependecy TO ls_dependecy_popup. READ TABLE lt_installed_packages INTO ls_installed_package WITH KEY group_id = ls_dependecy-group_id artifact_id = ls_dependecy-artifact_id. IF sy-subrc <> 0. ls_dependecy_popup-met = zif_abapgit_definitions=>c_no. ELSE. TRY. zcl_abapgit_version=>check_dependant_version( is_current = ls_installed_package-sem_version is_dependant = ls_dependecy-sem_version ). ls_dependecy_popup-met = zif_abapgit_definitions=>c_yes. CATCH zcx_abapgit_exception. ls_dependecy_popup-met = zif_abapgit_definitions=>c_partial. ENDTRY. ENDIF. INSERT ls_dependecy_popup INTO TABLE rt_status. ENDLOOP. ENDMETHOD. METHOD get_installed_packages. DATA: lo_apack_reader TYPE REF TO zcl_abapgit_apack_reader, lt_manifest_implementation TYPE zif_abapgit_apack_definitions=>ty_manifest_declarations, ls_manifest_implementation TYPE zif_abapgit_apack_definitions=>ty_manifest_declaration, lo_manifest_provider TYPE REF TO object, ls_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor. lt_manifest_implementation = get_manifest_implementations( ). LOOP AT lt_manifest_implementation INTO ls_manifest_implementation. CLEAR: lo_manifest_provider, lo_apack_reader. TRY. CREATE OBJECT lo_manifest_provider TYPE (ls_manifest_implementation-clsname). CATCH cx_sy_create_object_error. CLEAR: lo_manifest_provider. ENDTRY. IF lo_manifest_provider IS NOT BOUND. CONTINUE. ENDIF. lo_apack_reader = zcl_abapgit_apack_reader=>create_instance( ls_manifest_implementation-devclass ). lo_apack_reader->copy_manifest_descriptor( lo_manifest_provider ). ls_descriptor = lo_apack_reader->get_manifest_descriptor( ). IF ls_descriptor IS NOT INITIAL. INSERT ls_descriptor INTO TABLE rt_packages. ENDIF. ENDLOOP. ENDMETHOD. METHOD get_manifest_implementations. DATA lt_refclsname TYPE RANGE OF abap_classname. DATA ls_refclsname LIKE LINE OF lt_refclsname. ls_refclsname-sign = 'I'. ls_refclsname-option = 'EQ'. ls_refclsname-low = zif_abapgit_apack_definitions=>c_apack_interface_cust. INSERT ls_refclsname INTO TABLE lt_refclsname. ls_refclsname-sign = 'I'. ls_refclsname-option = 'EQ'. ls_refclsname-low = zif_abapgit_apack_definitions=>c_apack_interface_sap. INSERT ls_refclsname INTO TABLE lt_refclsname. ls_refclsname-sign = 'I'. ls_refclsname-option = 'CP'. ls_refclsname-low = zif_abapgit_apack_definitions=>c_apack_interface_nspc. INSERT ls_refclsname INTO TABLE lt_refclsname. " Find all classes that implement customer or SAP version of APACK interface SELECT seometarel~clsname tadir~devclass FROM seometarel "#EC CI_NOORDER INNER JOIN tadir ON seometarel~clsname = tadir~obj_name "#EC CI_BUFFJOIN INTO TABLE rt_manifest_implementations WHERE tadir~pgmid = 'R3TR' AND tadir~object = 'CLAS' AND seometarel~version = '1' AND seometarel~refclsname IN lt_refclsname ORDER BY clsname devclass ##SUBRC_OK. ENDMETHOD. METHOD show_dependencies_popup. DATA: lo_alv TYPE REF TO cl_salv_table, lo_column TYPE REF TO cl_salv_column, lo_column_table TYPE REF TO cl_salv_column_table, lo_columns TYPE REF TO cl_salv_columns_table, lt_columns TYPE salv_t_column_ref, ls_column LIKE LINE OF lt_columns, lt_color_table TYPE ty_color_tab, ls_position TYPE zif_abapgit_popups=>ty_popup_position, lx_ex TYPE REF TO cx_root. IF it_dependencies IS INITIAL. RETURN. ENDIF. TRY. cl_salv_table=>factory( IMPORTING r_salv_table = lo_alv CHANGING t_table = lt_color_table ). lo_columns = lo_alv->get_columns( ). lt_columns = lo_columns->get( ). LOOP AT lt_columns INTO ls_column WHERE columnname CP 'SEM_VERSION-*'. ls_column-r_column->set_technical( ). ENDLOOP. lo_column = lo_columns->get_column( 'MET' ). lo_column->set_technical( ). lo_column = lo_columns->get_column( 'GROUP_ID' ). lo_column->set_short_text( 'Org/ProjId' ). lo_columns->set_color_column( 'COLOR' ). lo_columns->set_exception_column( 'EXCEPTION' ). lo_columns->set_hyperlink_entry_column( 'T_HYPERLINK' ). lo_columns->set_optimize( ). lo_column = lo_columns->get_column( 'GROUP_ID' ). lo_column->set_short_text( 'Org/ProjId' ). lo_column = lo_columns->get_column( 'ARTIFACT_ID' ). lo_column->set_short_text( 'Proj. Name' ). lo_column = lo_columns->get_column( 'GIT_URL' ). lo_column->set_short_text( 'Git URL' ). lo_column_table ?= lo_column. lo_column_table->set_cell_type( if_salv_c_cell_type=>link ). lo_column = lo_columns->get_column( 'VERSION' ). lo_column->set_short_text( 'Version' ). lo_column = lo_columns->get_column( 'TARGET_PACKAGE' ). lo_column->set_technical( ). get_color_table( EXPORTING io_alv = lo_alv it_dependencies = it_dependencies CHANGING ct_color_table = lt_color_table ). ls_position = zcl_abapgit_popups=>center( iv_width = 90 iv_height = 10 ). lo_alv->set_screen_popup( start_column = ls_position-start_column end_column = ls_position-end_column start_line = ls_position-start_row end_line = ls_position-end_row ). lo_alv->get_display_settings( )->set_list_header( 'APACK dependencies' ). lo_alv->display( ). CATCH cx_salv_msg cx_salv_not_found cx_salv_data_error cx_salv_existing INTO lx_ex. zcx_abapgit_exception=>raise( lx_ex->get_text( ) ). ENDTRY. ENDMETHOD. METHOD to_file. DATA: lo_manifest_reader TYPE REF TO zcl_abapgit_apack_reader, ls_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor, lo_manifest_writer TYPE REF TO zcl_abapgit_apack_writer. lo_manifest_reader = zcl_abapgit_apack_reader=>create_instance( iv_package ). IF lo_manifest_reader->has_manifest( ) = abap_true. ls_descriptor = lo_manifest_reader->get_manifest_descriptor( ). lo_manifest_writer = zcl_abapgit_apack_writer=>create_instance( ls_descriptor ). rs_file-path = zif_abapgit_definitions=>c_root_dir. rs_file-filename = zif_abapgit_apack_definitions=>c_dot_apack_manifest. rs_file-data = zcl_abapgit_convert=>string_to_xstring_utf8( lo_manifest_writer->serialize( ) ). rs_file-sha1 = zcl_abapgit_hash=>sha1_blob( rs_file-data ). ENDIF. ENDMETHOD. ENDCLASS. SELECTION-SCREEN BEGIN OF SCREEN 1001. * dummy for triggering screen on Java SAP GUI SELECTION-SCREEN END OF SCREEN 1001. TABLES sscrfields. **************************************************** * abapmerge - ZABAPGIT_PASSWORD_DIALOG **************************************************** *&---------------------------------------------------------------------* *& Include ZABAPGIT_PASSWORD_DIALOG *&---------------------------------------------------------------------* SELECTION-SCREEN BEGIN OF SCREEN 1002 TITLE sc_title. SELECTION-SCREEN SKIP. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(18) sc_url FOR FIELD p_url. PARAMETERS: p_url TYPE string LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN SKIP. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(18) sc_user FOR FIELD p_user. PARAMETERS: p_user TYPE string LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(18) sc_pass FOR FIELD p_pass. PARAMETERS: p_pass TYPE c LENGTH 255 LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN SKIP. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(18) sc_cmnt FOR FIELD p_cmnt. PARAMETERS: p_cmnt TYPE c LENGTH 255 LOWER CASE VISIBLE LENGTH 60 ##SEL_WRONG. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN END OF SCREEN 1002. *----------------------------------------------------------------------- * LCL_PASSWORD_DIALOG *----------------------------------------------------------------------- CLASS lcl_password_dialog DEFINITION FINAL. ************** * This class will remain local in the report ************** PUBLIC SECTION. CONSTANTS c_dynnr TYPE c LENGTH 4 VALUE '1002'. CLASS-METHODS popup IMPORTING iv_repo_url TYPE string CHANGING cv_user TYPE string cv_pass TYPE string. CLASS-METHODS on_screen_init. CLASS-METHODS on_screen_output. CLASS-METHODS on_screen_event IMPORTING iv_ucomm TYPE sy-ucomm. PRIVATE SECTION. CLASS-DATA gv_confirm TYPE abap_bool. CLASS-METHODS enrich_title_by_hostname IMPORTING iv_repo_url TYPE string. ENDCLASS. CLASS lcl_password_dialog IMPLEMENTATION. METHOD popup. DATA ls_position TYPE zif_abapgit_popups=>ty_popup_position. CLEAR p_pass. p_url = iv_repo_url. p_user = cv_user. gv_confirm = abap_false. p_cmnt = 'Press F1 for Help'. enrich_title_by_hostname( iv_repo_url ). ls_position = zcl_abapgit_popups=>center( iv_width = 65 iv_height = 7 ). CALL SELECTION-SCREEN c_dynnr STARTING AT ls_position-start_column ls_position-start_row ENDING AT ls_position-end_column ls_position-end_row. IF gv_confirm = abap_true. cv_user = p_user. cv_pass = p_pass. ELSE. CLEAR: cv_user, cv_pass. ENDIF. CLEAR: p_url, p_user, p_pass. ENDMETHOD. METHOD on_screen_init. sc_title = 'Login'. sc_url = 'Repo URL'. sc_user = 'User'. sc_pass = 'Password or Token'. sc_cmnt = 'Note'. ENDMETHOD. METHOD on_screen_output. DATA lt_ucomm TYPE TABLE OF sy-ucomm. ASSERT sy-dynnr = c_dynnr. LOOP AT SCREEN. IF screen-name = 'P_URL' OR screen-name = 'P_CMNT'. screen-input = '0'. screen-intensified = '1'. screen-display_3d = '0'. MODIFY SCREEN. ENDIF. IF screen-name = 'P_CMNT' OR screen-name = 'SC_CMNT'. screen-active = '1'. screen-invisible = '0'. MODIFY SCREEN. ENDIF. IF screen-name = 'P_PASS'. screen-invisible = '1'. MODIFY SCREEN. ENDIF. ENDLOOP. APPEND 'PICK' TO lt_ucomm. CALL FUNCTION 'RS_SET_SELSCREEN_STATUS' EXPORTING p_status = 'DETL' p_program = 'RSPFPAR' TABLES p_exclude = lt_ucomm. IF p_user IS NOT INITIAL. SET CURSOR FIELD 'P_PASS'. ENDIF. ENDMETHOD. METHOD on_screen_event. ASSERT sy-dynnr = c_dynnr. CASE iv_ucomm. WHEN 'OK'. " Enter gv_confirm = abap_true. LEAVE TO SCREEN 0. WHEN 'HELP'. " F1 TRY. zcl_abapgit_services_abapgit=>open_abapgit_wikipage( 'guide-authentication.html' ). CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. WHEN OTHERS. " Escape gv_confirm = abap_false. LEAVE TO SCREEN 0. ENDCASE. ENDMETHOD. METHOD enrich_title_by_hostname. DATA lv_host TYPE string. FIND REGEX 'https?://([^/^:]*)' IN iv_repo_url SUBMATCHES lv_host. IF lv_host IS NOT INITIAL AND lv_host <> space. CLEAR sc_title. CONCATENATE 'Login:' lv_host INTO sc_title IN CHARACTER MODE SEPARATED BY space. ENDIF. ENDMETHOD. ENDCLASS. FORM password_popup USING pv_repo_url TYPE string CHANGING cv_user TYPE string cv_pass TYPE string. lcl_password_dialog=>popup( EXPORTING iv_repo_url = pv_repo_url CHANGING cv_user = cv_user cv_pass = cv_pass ). ENDFORM. * create class ZCL_ABAPGIT_AUTH_EXIT implementing ZIF_ABAPGIT_AUTH in following include, * if using the development version of abapGit create a global class instead * place the object in a different package than ZABAPGIT INCLUDE zabapgit_authorizations_exit IF FOUND. * create class ZCL_ABAPGIT_USER_EXIT implementing ZIF_ABAPGIT_EXIT in following include, * if using the development version of abapGit create a global class instead * place the object in a different package than ZABAPGIT INCLUDE zabapgit_user_exit IF FOUND. INCLUDE zabapgit_gui_pages_userexit IF FOUND. **************************************************** * abapmerge - ZABAPGIT_FORMS **************************************************** *&---------------------------------------------------------------------* *& Include ZABAPGIT_FORMS *&---------------------------------------------------------------------* CLASS lcl_startup DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS prepare_gui_startup RAISING zcx_abapgit_exception. PRIVATE SECTION. CLASS-METHODS set_start_repo_from_package IMPORTING !iv_package TYPE devclass RAISING zcx_abapgit_exception. CLASS-METHODS get_package_from_adt RETURNING VALUE(rv_package) TYPE devclass. CLASS-METHODS check_sapgui RAISING zcx_abapgit_exception. ENDCLASS. CLASS lcl_startup IMPLEMENTATION. METHOD check_sapgui. CONSTANTS: lc_hide_sapgui_hint TYPE string VALUE '2'. DATA: lv_answer TYPE char1, ls_settings TYPE zif_abapgit_definitions=>ty_s_user_settings, li_user_persistence TYPE REF TO zif_abapgit_persist_user. li_user_persistence = zcl_abapgit_persistence_user=>get_instance( ). ls_settings = li_user_persistence->get_settings( ). IF ls_settings-hide_sapgui_hint = abap_true. RETURN. ENDIF. IF zcl_abapgit_ui_factory=>get_frontend_services( )->is_sapgui_for_java( ) = abap_false. RETURN. ENDIF. lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = 'Not supported SAPGUI' iv_text_question = 'SAPGUI for Java is not supported! There might be some issues.' iv_text_button_1 = 'Got it' iv_icon_button_1 = |{ icon_okay }| iv_text_button_2 = 'Hide' iv_icon_button_2 = |{ icon_set_state }| iv_display_cancel_button = abap_false ). IF lv_answer = lc_hide_sapgui_hint. ls_settings-hide_sapgui_hint = abap_true. li_user_persistence->set_settings( ls_settings ). ENDIF. ENDMETHOD. METHOD prepare_gui_startup. DATA: lv_repo_key TYPE zif_abapgit_persistence=>ty_value, lv_package TYPE devclass, lv_package_adt TYPE devclass. check_sapgui( ). IF zcl_abapgit_persist_factory=>get_settings( )->read( )->get_show_default_repo( ) = abap_false. " Don't show the last seen repo at startup zcl_abapgit_persistence_user=>get_instance( )->set_repo_show( || ). ENDIF. " We have three special cases for gui startup " - open a specific repo by repo key " - open a specific repo by package name " - open a specific repo by package name provided by ADT " These overrule the last shown repo GET PARAMETER ID zif_abapgit_definitions=>c_spagpa_param_repo_key FIELD lv_repo_key. GET PARAMETER ID zif_abapgit_definitions=>c_spagpa_param_package FIELD lv_package. lv_package_adt = get_package_from_adt( ). IF lv_repo_key IS NOT INITIAL. SET PARAMETER ID zif_abapgit_definitions=>c_spagpa_param_repo_key FIELD ''. zcl_abapgit_persistence_user=>get_instance( )->set_repo_show( lv_repo_key ). ELSEIF lv_package IS NOT INITIAL. SET PARAMETER ID zif_abapgit_definitions=>c_spagpa_param_package FIELD ''. set_start_repo_from_package( lv_package ). ELSEIF lv_package_adt IS NOT INITIAL. set_start_repo_from_package( lv_package_adt ). ENDIF. ENDMETHOD. METHOD set_start_repo_from_package. DATA: lo_repo TYPE REF TO zcl_abapgit_repo, lt_r_package TYPE RANGE OF devclass, ls_r_package LIKE LINE OF lt_r_package, lt_superpackages TYPE zif_abapgit_sap_package=>ty_devclass_tt, li_package TYPE REF TO zif_abapgit_sap_package, lt_repo_list TYPE zif_abapgit_repo_srv=>ty_repo_list. FIELD-SYMBOLS: TYPE LINE OF zif_abapgit_repo_srv=>ty_repo_list, LIKE LINE OF lt_superpackages. li_package = zcl_abapgit_factory=>get_sap_package( iv_package ). IF li_package->exists( ) = abap_false. RETURN. ENDIF. ls_r_package-sign = 'I'. ls_r_package-option = 'EQ'. ls_r_package-low = iv_package. INSERT ls_r_package INTO TABLE lt_r_package. " Also consider superpackages. E.g. when some open $abapgit_ui, abapGit repo " should be found via package $abapgit lt_superpackages = li_package->list_superpackages( ). LOOP AT lt_superpackages ASSIGNING . ls_r_package-low = . INSERT ls_r_package INTO TABLE lt_r_package. ENDLOOP. lt_repo_list = zcl_abapgit_repo_srv=>get_instance( )->list( ). LOOP AT lt_repo_list ASSIGNING . IF ->get_package( ) IN lt_r_package. lo_repo ?= . EXIT. ENDIF. ENDLOOP. IF lo_repo IS BOUND. zcl_abapgit_persistence_user=>get_instance( )->set_repo_show( lo_repo->get_key( ) ). ENDIF. ENDMETHOD. METHOD get_package_from_adt. DATA: ls_item TYPE zif_abapgit_definitions=>ty_item, lr_context TYPE REF TO data, lt_fields TYPE tihttpnvp. FIELD-SYMBOLS: TYPE any, TYPE string, LIKE LINE OF lt_fields. ls_item-obj_type = 'CLAS'. ls_item-obj_name = 'CL_ADT_GUI_INTEGRATION_CONTEXT'. IF zcl_abapgit_objects=>exists( ls_item ) = abap_false. " ADT is not supported in this NW release RETURN. ENDIF. TRY. CREATE DATA lr_context TYPE ('CL_ADT_GUI_INTEGRATION_CONTEXT=>TY_CONTEXT_INFO'). ASSIGN lr_context->* TO . ASSERT sy-subrc = 0. CALL METHOD (ls_item-obj_name)=>read_context RECEIVING result = . ASSIGN COMPONENT 'PARAMETERS' OF STRUCTURE TO . ASSERT sy-subrc = 0. lt_fields = cl_http_utility=>string_to_fields( cl_http_utility=>unescape_url( ) ). READ TABLE lt_fields ASSIGNING WITH KEY name = 'p_package_name'. IF sy-subrc = 0. rv_package = -value. " We want to open the repo just once. Therefore we delete the parameters " and initialize the ADT context. CLEAR . CALL METHOD (ls_item-obj_name)=>initialize_instance EXPORTING context_info = . ENDIF. CATCH cx_root. " Some problems with dynamic ADT access. " Let's ignore it for now and fail silently ENDTRY. ENDMETHOD. ENDCLASS. ******************************************************* FORM run. DATA lx_exception TYPE REF TO zcx_abapgit_exception. DATA lx_not_found TYPE REF TO zcx_abapgit_not_found. TRY. IF zcl_abapgit_auth=>is_allowed( zif_abapgit_auth=>c_authorization-startup ) = abap_false. zcx_abapgit_exception=>raise( 'No authorization to start abapGit' ). ENDIF. zcl_abapgit_migrations=>run( ). PERFORM open_gui. CATCH zcx_abapgit_exception INTO lx_exception. MESSAGE lx_exception TYPE 'E'. CATCH zcx_abapgit_not_found INTO lx_not_found. MESSAGE lx_not_found TYPE 'E'. ENDTRY. ENDFORM. "run FORM open_gui RAISING zcx_abapgit_exception. DATA lv_action TYPE string. DATA lv_mode TYPE tabname. IF sy-batch = abap_true. zcl_abapgit_background=>run( ). ELSE. * https://docs.abapgit.org/user-guide/reference/database-util.html#emergency-mode GET PARAMETER ID 'DBT' FIELD lv_mode. CASE lv_mode. WHEN 'ZABAPGIT'. lv_action = zif_abapgit_definitions=>c_action-go_db. WHEN OTHERS. lv_action = zif_abapgit_definitions=>c_action-go_home. ENDCASE. lcl_startup=>prepare_gui_startup( ). zcl_abapgit_ui_factory=>get_gui( )->go_home( lv_action ). CALL SELECTION-SCREEN 1001. " trigger screen ENDIF. ENDFORM. FORM output. DATA: lx_error TYPE REF TO zcx_abapgit_exception, lt_ucomm TYPE TABLE OF sy-ucomm. PERFORM set_pf_status IN PROGRAM rsdbrunt IF FOUND. APPEND 'CRET' TO lt_ucomm. "Button Execute APPEND 'SPOS' TO lt_ucomm. "Button Save CALL FUNCTION 'RS_SET_SELSCREEN_STATUS' EXPORTING p_status = sy-pfkey TABLES p_exclude = lt_ucomm. " For variant maintenance we have to omit this because " it instantiates controls and hides maintenance screens. IF zcl_abapgit_factory=>get_environment( )->is_variant_maintenance( ) = abap_false. TRY. zcl_abapgit_ui_factory=>get_gui( )->set_focus( ). CATCH zcx_abapgit_exception INTO lx_error. MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. ENDIF. ENDFORM. FORM exit. DATA lx_error TYPE REF TO zcx_abapgit_exception. " The exit logic should only be applied for our 'main' selection screen 1001. " All other selection-screens are called as popups and shouldn't influence " the gui navigation as it would lead to unpredictable behaviour like dumps. IF sy-dynnr <> 1001. RETURN. ENDIF. TRY. CASE sy-ucomm. WHEN 'CBAC' OR 'CCAN'. "Back & Escape IF zcl_abapgit_ui_factory=>get_gui( )->back( iv_graceful = abap_true ) = abap_true. " end of stack zcl_abapgit_ui_factory=>get_gui( )->free( ). " Graceful shutdown ELSE. LEAVE TO SCREEN 1001. ENDIF. ENDCASE. CATCH zcx_abapgit_exception INTO lx_error. MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. ENDFORM. FORM adjust_toolbar USING pv_dynnr TYPE sy-dynnr. DATA: ls_header TYPE rpy_dyhead, lt_containers TYPE dycatt_tab, lt_fields_to_containers TYPE dyfatc_tab, lt_flow_logic TYPE swydyflow, lv_no_toolbar LIKE ls_header-no_toolbar. CALL FUNCTION 'RPY_DYNPRO_READ' EXPORTING progname = sy-cprog dynnr = pv_dynnr IMPORTING header = ls_header TABLES containers = lt_containers fields_to_containers = lt_fields_to_containers flow_logic = lt_flow_logic EXCEPTIONS cancelled = 1 not_found = 2 permission_error = 3 OTHERS = 4. IF sy-subrc IS NOT INITIAL. RETURN. " Ignore errors, just exit ENDIF. " Remove toolbar on html screen but re-insert toolbar for variant maintenance. " Because otherwise important buttons are missing and variant maintenance is not possible. lv_no_toolbar = boolc( zcl_abapgit_factory=>get_environment( )->is_variant_maintenance( ) = abap_false ). IF ls_header-no_toolbar = lv_no_toolbar. RETURN. " No change required ENDIF. ls_header-no_toolbar = lv_no_toolbar. CALL FUNCTION 'RPY_DYNPRO_INSERT' EXPORTING header = ls_header suppress_exist_checks = abap_true TABLES containers = lt_containers fields_to_containers = lt_fields_to_containers flow_logic = lt_flow_logic EXCEPTIONS cancelled = 1 already_exists = 2 program_not_exists = 3 not_executed = 4 missing_required_field = 5 illegal_field_value = 6 field_not_allowed = 7 not_generated = 8 illegal_field_position = 9 OTHERS = 10. IF sy-subrc <> 2 AND sy-subrc <> 0. RETURN. " Ignore errors, just exit ENDIF. ENDFORM. ********************************************************************** INITIALIZATION. PERFORM adjust_toolbar USING '1001'. lcl_password_dialog=>on_screen_init( ). START-OF-SELECTION. PERFORM run. * Hide Execute button from screen AT SELECTION-SCREEN OUTPUT. IF sy-dynnr = lcl_password_dialog=>c_dynnr. lcl_password_dialog=>on_screen_output( ). ELSE. PERFORM output. ENDIF. * SAP back command re-direction AT SELECTION-SCREEN ON EXIT-COMMAND. PERFORM exit. AT SELECTION-SCREEN. IF sy-dynnr = lcl_password_dialog=>c_dynnr. lcl_password_dialog=>on_screen_event( sscrfields-ucomm ). ENDIF. **************************************************** INTERFACE lif_abapmerge_marker. * abapmerge 0.16.0 - 2024-04-24T14:41:46.792Z CONSTANTS c_merge_timestamp TYPE string VALUE `2024-04-24T14:41:46.792Z`. CONSTANTS c_abapmerge_version TYPE string VALUE `0.16.0`. ENDINTERFACE. ****************************************************