CLASS zcl_abapgit_persistence_repo DEFINITION PUBLIC CREATE PROTECTED GLOBAL FRIENDS zcl_abapgit_persist_factory . PUBLIC SECTION. INTERFACES zif_abapgit_persist_repo . METHODS constructor . 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 . 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. CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT' EXPORTING input = rv_next_repo_id IMPORTING output = rv_next_repo_id. 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~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~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. MOVE-CORRESPONDING from_xml( ls_content-data_str ) TO ls_repo. IF ls_repo-local_settings-write_protected = abap_false AND zcl_abapgit_factory=>get_environment( )->is_repo_object_changes_allowed( ) = abap_false. ls_repo-local_settings-write_protected = abap_true. ENDIF. ls_repo-key = ls_content-value. 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.