CLASS zcl_abapgit_services_repo DEFINITION PUBLIC 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 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 !iv_reset_all TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . PROTECTED SECTION. PRIVATE SECTION. 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 !iv_reset_all TYPE abap_bool CHANGING !cs_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks RAISING zcx_abapgit_cancel zcx_abapgit_exception . CLASS-METHODS popup_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 . ENDCLASS. CLASS ZCL_ABAPGIT_SERVICES_REPO IMPLEMENTATION. METHOD check_package. DATA: lo_repo TYPE REF TO zcl_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 eo_repo = lo_repo ev_reason = lv_reason ). IF lo_repo IS BOUND. zcx_abapgit_exception=>raise( lv_reason ). 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. 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( ). ENDIF. ENDMETHOD. METHOD gui_deserialize. DATA: ls_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks, li_log TYPE REF TO zif_abapgit_log. " 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 iv_reset_all = iv_reset_all CHANGING cs_checks = ls_checks ). CATCH zcx_abapgit_cancel. RETURN. ENDTRY. li_log = io_repo->create_new_log( 'Pull Log' ). " pass decisions to delete delete_unnecessary_objects( io_repo = io_repo is_checks = ls_checks ii_log = li_log ). " pass decisions to deserialize io_repo->deserialize( is_checks = ls_checks ii_log = li_log ). ENDMETHOD. METHOD new_offline. check_package( is_repo_params ). " create new repo and add to favorites ro_repo = zcl_abapgit_repo_srv=>get_instance( )->new_offline( iv_url = is_repo_params-url iv_package = is_repo_params-package iv_folder_logic = is_repo_params-folder_logic iv_main_lang_only = is_repo_params-main_lang_only ). " Make sure there're no leftovers from previous repos ro_repo->rebuild_local_checksums( ). 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. 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_package = is_repo_params-package iv_display_name = is_repo_params-display_name iv_folder_logic = is_repo_params-folder_logic iv_ign_subpkg = is_repo_params-ignore_subpackages iv_main_lang_only = is_repo_params-main_lang_only ). " Make sure there're no leftovers from previous repos ro_repo->rebuild_local_checksums( ). 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. " For regular pull, some objects are automatically handled (see below) IF iv_reset_all IS INITIAL. DELETE lt_decision WHERE action = zif_abapgit_objects=>c_deserialize_action-add OR action = zif_abapgit_objects=>c_deserialize_action-update. ENDIF. " Ask user what to do popup_overwrite( CHANGING ct_overwrite = lt_decision ). popup_package_overwrite( CHANGING ct_overwrite = cs_checks-warning_package ). IF cs_checks-requirements-met = zif_abapgit_definitions=>c_no. lt_requirements = io_repo->get_dot_abapgit( )->get_data( )-requirements. zcl_abapgit_requirement_helper=>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 ). ENDIF. IF cs_checks-transport-required = abap_true. cs_checks-transport-transport = zcl_abapgit_ui_factory=>get_popups( )->popup_transport_request( is_transport_type = 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. IF sy-subrc = 0. -decision = -decision. ELSE. " If user was not asked (regular pull), deny deletions and confirm other changes (add and update) CASE -action. WHEN zif_abapgit_objects=>c_deserialize_action-delete OR zif_abapgit_objects=>c_deserialize_action-delete_add. -decision = zif_abapgit_definitions=>c_no. WHEN zif_abapgit_objects=>c_deserialize_action-add OR zif_abapgit_objects=>c_deserialize_action-update. -decision = zif_abapgit_definitions=>c_yes. WHEN OTHERS. ASSERT 0 = 1. ENDCASE. ENDIF. ENDLOOP. ENDMETHOD. METHOD popup_overwrite. DATA: lt_columns TYPE zif_abapgit_definitions=>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_definitions=>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 = '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 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 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_definitions=>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_definitions=>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'. 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_question TYPE c LENGTH 100, 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 = zcl_abapgit_factory=>get_tadir( )->read( lv_package ). 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|. lv_answer = zcl_abapgit_ui_factory=>get_popups( )->popup_to_confirm( iv_titlebar = 'Uninstall' 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_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( io_repo = lo_repo is_checks = ls_checks ). COMMIT WORK. IF ri_log IS BOUND AND ri_log->count( ) > 0. 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 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->rebuild_local_checksums( ). COMMIT WORK AND WAIT. ENDMETHOD. METHOD remove. DATA: lv_answer TYPE c LENGTH 1, lo_repo TYPE REF TO zcl_abapgit_repo, lv_package TYPE devclass, lv_question TYPE c LENGTH 200, 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( ). 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' 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( lo_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_headers TYPE trwbo_request_headers, lt_transport_objects TYPE zif_abapgit_definitions=>ty_tadir_tt, 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 ). lt_transport_headers = zcl_abapgit_ui_factory=>get_popups( )->popup_to_select_transports( ). lt_transport_objects = zcl_abapgit_transport=>to_tadir( lt_transport_headers ). 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( lt_transport_headers ). 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.