CLASS zcl_abapgit_object_iext DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.
    METHODS:
      constructor
        IMPORTING
          is_item     TYPE zif_abapgit_definitions=>ty_item
          iv_language TYPE spras.

  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.

    DATA:
      mv_extension TYPE edi_cimtyp.

ENDCLASS.

CLASS zcl_abapgit_object_iext IMPLEMENTATION.

  METHOD constructor.

    super->constructor( is_item = is_item
                        iv_language = iv_language ).

    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
        object_not_found = 1
        db_error         = 2
        no_authority     = 3
        OTHERS           = 4.

    rv_user = ls_attributes-plast.

  ENDMETHOD.

  METHOD zif_abapgit_object~compare_to_remote_version.
    CREATE OBJECT ro_comparison_result TYPE zcl_abapgit_comparison_null.
  ENDMETHOD.

  METHOD zif_abapgit_object~delete.

    CALL FUNCTION 'EXTTYPE_DELETE'
      EXPORTING
        pi_cimtyp           = mv_extension
      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_extension  TYPE ty_extention,
          ls_attributes TYPE edi_iapi05.

    io_xml->read(
      EXPORTING
        iv_name = 'IEXT'
      CHANGING
        cg_data = ls_extension ).

    MOVE-CORRESPONDING ls_extension-attributes TO ls_attributes.

    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
        object_not_found    = 1
        object_exists       = 2
        action_not_possible = 3
        syntax_error        = 4
        segment_error       = 5
        transport_error     = 6
        db_error            = 7
        no_authority        = 8
        OTHERS              = 9.

    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
        object_not_found = 1
        db_error         = 2
        no_authority     = 3
        OTHERS           = 4.

    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.

  METHOD zif_abapgit_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.

  METHOD zif_abapgit_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    DATA: lt_bdcdata TYPE TABLE OF bdcdata.

    FIELD-SYMBOLS: <ls_bdcdata> LIKE LINE OF lt_bdcdata.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-program  = 'SAPMSED5'.
    <ls_bdcdata>-dynpro   = '0010'.
    <ls_bdcdata>-dynbegin = abap_true.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'SED5STRUC-OBJECT'.
    <ls_bdcdata>-fval = ms_item-obj_name.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'SED5STRUC-SELECT_EXT'.
    <ls_bdcdata>-fval = abap_true.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'BDC_OKCODE'.
    <ls_bdcdata>-fval = '=DISP'.

    CALL FUNCTION 'ABAP4_CALL_TRANSACTION'
      STARTING NEW TASK 'GIT'
      EXPORTING
        tcode                 = 'WE30'
        mode_val              = 'E'
      TABLES
        using_tab             = lt_bdcdata
      EXCEPTIONS
        system_failure        = 1
        communication_failure = 2
        resource_failure      = 3
        OTHERS                = 4.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

  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
        object_not_found = 1
        db_error         = 2
        no_authority     = 3
        OTHERS           = 4.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

    CLEAR: ls_extension-attributes-devc,
           ls_extension-attributes-plast,
           ls_extension-attributes-credate,
           ls_extension-attributes-cretime,
           ls_extension-attributes-ldate,
           ls_extension-attributes-ltime.

    io_xml->add( iv_name = 'IEXT'
                 ig_data = ls_extension ).

  ENDMETHOD.

  METHOD zif_abapgit_object~is_locked.

    rv_is_locked = abap_false.

  ENDMETHOD.

ENDCLASS.

CLASS zcl_abapgit_object_iext DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.
    METHODS:
      constructor
        IMPORTING
          is_item     TYPE zif_abapgit_definitions=>ty_item
          iv_language TYPE spras.

  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.

    DATA:
      mv_extension TYPE edi_cimtyp.

ENDCLASS.

CLASS zcl_abapgit_object_iext IMPLEMENTATION.

  METHOD constructor.

    super->constructor( is_item = is_item
                        iv_language = iv_language ).

    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~compare_to_remote_version.
    CREATE OBJECT ro_comparison_result TYPE zcl_abapgit_comparison_null.
  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 = 'IEXT'
      CHANGING
        cg_data = ls_extension ).

    MOVE-CORRESPONDING ls_extension-attributes TO ls_attributes.
    ls_attributes-presp = cl_abap_syst=>get_user_name( ).
    ls_attributes-pwork = ls_attributes-presp.

    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.

    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_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.

  METHOD zif_abapgit_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    DATA: lt_bdcdata TYPE TABLE OF bdcdata.

    FIELD-SYMBOLS: <ls_bdcdata> LIKE LINE OF lt_bdcdata.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-program  = 'SAPMSED5'.
    <ls_bdcdata>-dynpro   = '0010'.
    <ls_bdcdata>-dynbegin = abap_true.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'SED5STRUC-OBJECT'.
    <ls_bdcdata>-fval = ms_item-obj_name.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'SED5STRUC-SELECT_EXT'.
    <ls_bdcdata>-fval = abap_true.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'BDC_OKCODE'.
    <ls_bdcdata>-fval = '=DISP'.

    CALL FUNCTION 'ABAP4_CALL_TRANSACTION'
      STARTING NEW TASK 'GIT'
      EXPORTING
        tcode     = 'WE30'
        mode_val  = 'E'
      TABLES
        using_tab = lt_bdcdata
      EXCEPTIONS
        OTHERS    = 1.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

  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.

    CLEAR: ls_extension-attributes-devc,
           ls_extension-attributes-plast,
           ls_extension-attributes-credate,
           ls_extension-attributes-cretime,
           ls_extension-attributes-ldate,
           ls_extension-attributes-ltime,
           ls_extension-attributes-pwork,
           ls_extension-attributes-presp.

    io_xml->add( iv_name = 'IEXT'
                 ig_data = ls_extension ).

  ENDMETHOD.

  METHOD zif_abapgit_object~is_locked.

    rv_is_locked = abap_false.

  ENDMETHOD.

ENDCLASS.

clear PRESP and PWORK in IEXT serialization + cleanup (#1987)

* clear PRESP and PWORK

clear username fields PRESP and PWORK

* remove unused FM exceptions

if sy-subrc is analysed (only <> 0) no detailed FM exceptions are needed, only OTHERS

* set PRESP and PWORK on deserialization

PRESP and PWORK is not set to SY-UNAME by default so set it explicitly


CLASS zcl_abapgit_object_srvb DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.
    METHODS:
      constructor
        IMPORTING
          is_item     TYPE zif_abapgit_definitions=>ty_item
          iv_language TYPE spras
        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_srvb IMPLEMENTATION.

  METHOD clear_field.

    FIELD-SYMBOLS: <lv_value> TYPE data.

    ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_service_binding
           TO <lv_value>.
    ASSERT sy-subrc = 0.

    CLEAR: <lv_value>.

  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 ).

  ENDMETHOD.

  METHOD constructor.

    super->constructor(
        is_item     = is_item
        iv_language = iv_language ).

    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:
      <ls_service_binding> TYPE any,
      <lv_language>        TYPE data.

    ASSIGN mr_service_binding->* TO <ls_service_binding>.
    ASSERT sy-subrc = 0.

    io_xml->read(
      EXPORTING
        iv_name = 'SRVB'
      CHANGING
        cg_data = <ls_service_binding> ).

    " We have to set the language explicitly,
    " because otherwise the description isn't stored
    ASSIGN COMPONENT 'METADATA-LANGUAGE' OF STRUCTURE <ls_service_binding>
           TO <lv_language>.
    ASSERT sy-subrc = 0.
    <lv_language> = mv_language.

    CREATE OBJECT ro_object_data TYPE ('CL_SRVB_OBJECT_DATA').
    ro_object_data->set_data( p_data = <ls_service_binding>  ).

  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:
      <ls_new>       TYPE any,
      <ls_old>       TYPE any,
      <lv_field_old> TYPE any,
      <lv_field_new> 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 <ls_new>.
    ASSERT sy-subrc = 0.

    CREATE DATA lr_old TYPE ('CL_SRVB_OBJECT_DATA=>TY_OBJECT_DATA').
    ASSIGN lr_old->* TO <ls_old>.
    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           = <ls_new>.

    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           = <ls_old>.

    ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE <ls_old> TO <lv_field_old>.
    ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE <ls_new> TO <lv_field_new>.
    <lv_field_old> = <lv_field_new>.

    CREATE OBJECT ro_object_data_merged TYPE ('CL_SRVB_OBJECT_DATA').

    CALL METHOD ro_object_data_merged->('SET_DATA')
      EXPORTING
        p_data = <ls_old>.

  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_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.

    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.

    lo_wb_object_operator = get_wb_object_operator( ).
    TRY.
        IF mv_is_inactive_supported = abap_true.
          TRY.
              CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ')
                EXPORTING
                  data_selection = 'ST'
                  version        = 'I'
                IMPORTING
                  eo_object_data = lo_object_data.

            CATCH cx_root.
              CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ')
                EXPORTING
                  data_selection = 'ST'
                  version        = 'A'
                IMPORTING
                  eo_object_data = lo_object_data.

          ENDTRY.
        ELSE.

          CALL METHOD lo_wb_object_operator->('IF_WB_OBJECT_OPERATOR~READ')
            EXPORTING
              data_selection = 'ST'
              version        = 'A'
            IMPORTING
              eo_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_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-delete_tadir = abap_true.
  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~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_swb_exception.

    FIELD-SYMBOLS:
      <ls_service_binding> TYPE any.

    ASSIGN mr_service_binding->* TO <ls_service_binding>.
    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 = <ls_service_binding> ).

        clear_fields( CHANGING cs_service_binding = <ls_service_binding> ).

      CATCH cx_swb_exception INTO lx_error.
        zcx_abapgit_exception=>raise_with_text( lx_error ).
    ENDTRY.

    io_xml->add(
        iv_name = 'SRVB'
        ig_data = <ls_service_binding> ).

  ENDMETHOD.
ENDCLASS.

CLASS zcl_abapgit_object_srvb DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.
    METHODS:
      constructor
        IMPORTING
          is_item     TYPE zif_abapgit_definitions=>ty_item
          iv_language TYPE spras
        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_srvb IMPLEMENTATION.

  METHOD clear_field.

    FIELD-SYMBOLS: <lv_value> TYPE data.

    ASSIGN COMPONENT iv_fieldname OF STRUCTURE cs_service_binding
           TO <lv_value>.
    ASSERT sy-subrc = 0.

    CLEAR: <lv_value>.

  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 ).

  ENDMETHOD.

  METHOD constructor.

    super->constructor(
        is_item     = is_item
        iv_language = iv_language ).

    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:
      <ls_service_binding> TYPE any,
      <lv_language>        TYPE data.

    ASSIGN mr_service_binding->* TO <ls_service_binding>.
    ASSERT sy-subrc = 0.

    io_xml->read(
      EXPORTING
        iv_name = 'SRVB'
      CHANGING
        cg_data = <ls_service_binding> ).

    " We have to set the language explicitly,
    " because otherwise the description isn't stored
    ASSIGN COMPONENT 'METADATA-LANGUAGE' OF STRUCTURE <ls_service_binding>
           TO <lv_language>.
    ASSERT sy-subrc = 0.
    <lv_language> = mv_language.

    CREATE OBJECT ro_object_data TYPE ('CL_SRVB_OBJECT_DATA').
    ro_object_data->set_data( p_data = <ls_service_binding>  ).

  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:
      <ls_new>       TYPE any,
      <ls_old>       TYPE any,
      <lv_field_old> TYPE any,
      <lv_field_new> 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 <ls_new>.
    ASSERT sy-subrc = 0.

    CREATE DATA lr_old TYPE ('CL_SRVB_OBJECT_DATA=>TY_OBJECT_DATA').
    ASSIGN lr_old->* TO <ls_old>.
    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           = <ls_new>.

    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           = <ls_old>.

    ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE <ls_old> TO <lv_field_old>.
    ASSIGN COMPONENT 'METADATA-DESCRIPTION' OF STRUCTURE <ls_new> TO <lv_field_new>.
    <lv_field_old> = <lv_field_new>.

    CREATE OBJECT ro_object_data_merged TYPE ('CL_SRVB_OBJECT_DATA').

    CALL METHOD ro_object_data_merged->('SET_DATA')
      EXPORTING
        p_data = <ls_old>.

  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_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.

    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_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-delete_tadir = abap_true.
  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~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_swb_exception.

    FIELD-SYMBOLS:
      <ls_service_binding> TYPE any.

    ASSIGN mr_service_binding->* TO <ls_service_binding>.
    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 = <ls_service_binding> ).

        clear_fields( CHANGING cs_service_binding = <ls_service_binding> ).

      CATCH cx_swb_exception INTO lx_error.
        zcx_abapgit_exception=>raise_with_text( lx_error ).
    ENDTRY.

    io_xml->add(
        iv_name = 'SRVB'
        ig_data = <ls_service_binding> ).

  ENDMETHOD.
ENDCLASS.

Fix for Service Binding issue #5212 (#5344)

Fix for SRVB (Service Binding) is lost in version 1.113.0 #5212

Co-authored-by: Marc Bernard <b87df29b98274de0b03db8f81c149b8b52bd050e@users.noreply.github.com>


##TODO.

*CLASS ltcl_test DEFINITION DEFERRED.
*
*CLASS ltcl_logger DEFINITION
*  FOR TESTING
*  INHERITING FROM zcl_alog_dbtab_logger
*  FINAL
*  CREATE PUBLIC.
*
*  PUBLIC SECTION.
*    METHODS:
*      constructor.
*  PROTECTED SECTION.
*    METHODS:
*      get_next_key REDEFINITION.
*  PRIVATE SECTION.
*    CLASS-DATA:
*     gv_last_key TYPE i VALUE 0.
*ENDCLASS.
*
*CLASS ltcl_test DEFINITION
*  FOR TESTING
*  RISK LEVEL CRITICAL
*  DURATION SHORT
*  FINAL.
*
*  PUBLIC SECTION.
*    CONSTANTS:
*      gc_tabname TYPE tabname VALUE 'TEST',
*      BEGIN OF gc_column_names,
*        text      TYPE fieldname VALUE 'TEXT',
*        type      TYPE fieldname VALUE 'TYPE',
*        username  TYPE fieldname VALUE 'USER',
*        timestamp TYPE fieldname VALUE 'TIMESTAMP',
*        index     TYPE fieldname VALUE 'COUNTER',
*      END OF gc_column_names.
*    METHODS:
*      test_entry FOR TESTING.
*  PROTECTED SECTION.
*  PRIVATE SECTION.
*    CLASS-METHODS:
*      class_setup,
*      class_teardown.
*    METHODS:
*      setup,
*      teardown.
*    CLASS-DATA:
*      go_tab_descr TYPE REF TO cl_abap_tabledescr.
*    DATA:
*      mo_logger TYPE REF TO zcl_alog_dbtab_logger.
*ENDCLASS.
*
*CLASS ltcl_logger IMPLEMENTATION.
*  METHOD constructor.
*    super->constructor(
*      iv_tabname = ltcl_test=>gc_tabname
*      is_mapping = VALUE #( text_target = 'TEXT' )
*      it_key_components = VALUE #( ( ltcl_test=>gc_column_names-index ) )
*    ).
*  ENDMETHOD.
*
*  METHOD get_next_key.
*    ADD 1 TO gv_last_key.
*    rv_key = gv_last_key.
*  ENDMETHOD.
*ENDCLASS.
*
*CLASS ltcl_test IMPLEMENTATION.
*  METHOD setup.
*    mo_logger = NEW ltcl_logger( ).
*  ENDMETHOD.
*
*  METHOD teardown.
*    DATA: lr_tab TYPE REF TO data.
*    FIELD-SYMBOLS: <lt_pointer> TYPE STANDARD TABLE.
*
*    FREE mo_logger.
*
*    CREATE DATA lr_tab TYPE HANDLE go_tab_descr.
*    ASSERT lr_tab IS BOUND.
*    ASSIGN lr_tab->* TO <lt_pointer>.
*    ASSERT <lt_pointer> IS ASSIGNED.
*
*    " Delete table content
*    SELECT * INTO TABLE <lt_pointer> FROM (gc_tabname).
*    IF sy-subrc = 0.
*      DELETE (gc_tabname) FROM TABLE <lt_pointer>.
*    ENDIF.
*  ENDMETHOD.
*
*  METHOD class_setup.
*    DATA: lt_definition TYPE STANDARD TABLE OF dd03p.
*
*    DATA(lo_descr) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_name( gc_tabname ) ).
*    go_tab_descr = cl_abap_tabledescr=>get( lo_descr ).
*
*    lt_definition = VALUE #(
*      ( tabname = gc_tabname fieldname = gc_column_names-text )
*      ( tabname = gc_tabname fieldname = gc_column_names-type )
*      ( tabname = gc_tabname fieldname = gc_column_names-username )
*      ( tabname = gc_tabname fieldname = gc_column_names-timestamp )
*    ).
*
**    CALL FUNCTION 'DDIF_TABL_PUT'
**      EXPORTING
**        name      = gc_tabname
***       dd02v_wa  = ' '    " Table Header
***       dd09l_wa  = ' '    " Technical Settings of the Table
**      TABLES
**        dd03p_tab =     " Table Fields
***       dd05m_tab =     " Foreign Key Fields of the Table
***       dd08v_tab =     " Foreign Keys of the Table
***       dd35v_tab =     " Header of the Search Help Assignments of the Table
***       dd36m_tab =     " Allocations of the Search Help Assignments of the Table
***      EXCEPTIONS
***       tabl_not_found    = 1
***       name_inconsistent = 2
***       tabl_inconsistent = 3
***       put_failure       = 4
***       put_refused       = 5
***       others    = 6
**      .
**    ASSERT sy-subrc = 0.
*  ENDMETHOD.
*
*  METHOD class_teardown.
*    CALL FUNCTION 'RS_DD_DELETE_OBJ'
*      EXPORTING
*        no_ask               = abap_true
*        objname              = gc_tabname
*        objtype              = 'T'
*      EXCEPTIONS
*        not_executed         = 1
*        object_not_found     = 2
*        object_not_specified = 3
*        permission_failure   = 4
*        dialog_needed        = 5
*        OTHERS               = 6.
*    ASSERT sy-subrc = 0.
*  ENDMETHOD.
*
*  METHOD test_entry.
*    TYPES: BEGIN OF lty_test,
*             text        TYPE zalog_s_logentry-text,
*             type        TYPE REF TO zcl_alog_entry_type,
*             description TYPE zalog_s_logentry-type_descr,
*           END OF lty_test,
*           lty_test_tab TYPE STANDARD TABLE OF lty_test WITH DEFAULT KEY.
*    DATA: lt_test TYPE lty_test_tab,
*          lr_tab  TYPE REF TO data,
*          lt_cond TYPE stringtab.
*    FIELD-SYMBOLS: <lt_tab>     TYPE STANDARD TABLE,
*                   <lg_row>     TYPE data,
*                   <lg_column>  TYPE data,
*                   <lg_column2> TYPE data.
*
*    DO 400 TIMES.
*      APPEND VALUE #( LET type = ztcl_alog_test_utl=>get_random_log_type( ) IN
*                      text = ztcl_alog_test_utl=>get_random_log_text( )
*                      type = type
*                      description = type->mv_description
*                    ) TO lt_test.
*    ENDDO.
*
*    LOOP AT lt_test ASSIGNING FIELD-SYMBOL(<ls_test>).
*      mo_logger->entry( iv_text = <ls_test>-text io_type = <ls_test>-type ).
*      FREE <ls_test>-type.
*    ENDLOOP.
*
*    COMMIT WORK.
*
*    CREATE DATA lr_tab TYPE HANDLE go_tab_descr.
*    ASSERT lr_tab IS BOUND.
*    ASSIGN lr_tab->* TO <lt_tab>.
*    ASSERT <lt_tab> IS ASSIGNED.
*
*    APPEND LINES OF VALUE stringtab(
**      ( |{ gc_column_names-counter } = @sy-index| )
*    ) TO lt_cond.
*
*    LOOP AT lt_test ASSIGNING FIELD-SYMBOL(<ls_test2>).
*      SELECT * INTO TABLE @<lt_tab>
*        FROM (gc_tabname)
*        WHERE (lt_cond).
*
*      cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( <lt_tab> ) ).
*
*      LOOP AT <lt_tab> ASSIGNING <lg_row>.
*        EXIT.
*      ENDLOOP.
*      ASSERT <lg_row> IS ASSIGNED.
*
*      DO 4 TIMES.
*        DATA(lv_column_name) = SWITCH #( sy-index WHEN 1 THEN gc_column_names-text
*                                                  WHEN 2 THEN gc_column_names-timestamp
*                                                  WHEN 3 THEN gc_column_names-type
*                                                  WHEN 4 THEN gc_column_names-username ).
*
*        ASSIGN COMPONENT lv_column_name OF STRUCTURE <lg_row> TO <lg_column>.
*        ASSERT <lg_column> IS ASSIGNED.
*
*        ASSIGN COMPONENT lv_column_name OF STRUCTURE <ls_test2> TO <lg_column2>.
*        ASSERT <lg_column> IS ASSIGNED.
*
*        cl_abap_unit_assert=>assert_equals( exp = <lg_column2> act = <lg_column> ).
*
*        UNASSIGN: <lg_column>, <lg_column2>.
*      ENDDO.
*
*      CLEAR: <lt_tab>, <lg_row>.
*    ENDLOOP.
*  ENDMETHOD.
*ENDCLASS.

Fix linter issues

Fix linter issues


CLASS zcl_abapgit_persistence_user DEFINITION
  PUBLIC
  CREATE PRIVATE .

  PUBLIC SECTION.

    TYPES tt_favorites TYPE zif_abapgit_persistence=>tt_repo_keys .

    CLASS-METHODS get_instance
      IMPORTING
        !iv_user       TYPE xubname DEFAULT sy-uname
      RETURNING
        VALUE(ro_user) TYPE REF TO zcl_abapgit_persistence_user .
    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 tt_favorites
      RAISING
        zcx_abapgit_exception .
    METHODS get_hide_files
      RETURNING
        VALUE(rv_hide) 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 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 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.
  PRIVATE SECTION.

    TYPES:
      BEGIN OF ty_repo_config,
        url              TYPE zif_abapgit_persistence=>ty_repo-url,
        login            TYPE string,
        git_user         TYPE zif_abapgit_definitions=>ty_git_user,
        last_change_seen TYPE string,
      END OF ty_repo_config .
    TYPES:
      ty_repo_config_tt TYPE STANDARD TABLE OF ty_repo_config WITH DEFAULT KEY .
    TYPES:
      BEGIN OF ty_user,
        default_git_user TYPE zif_abapgit_definitions=>ty_git_user,
        repo_show        TYPE zif_abapgit_persistence=>ty_repo-key,
        hide_files       TYPE abap_bool,
        changes_only     TYPE abap_bool,
        diff_unified     TYPE abap_bool,
        favorites        TYPE tt_favorites,
        repo_config      TYPE ty_repo_config_tt,
        settings         TYPE zif_abapgit_definitions=>ty_s_user_settings,
      END OF ty_user .

    DATA mv_user TYPE xubname .
    CLASS-DATA go_current_user TYPE REF TO zcl_abapgit_persistence_user .

    METHODS constructor
      IMPORTING
        !iv_user TYPE xubname DEFAULT sy-uname .
    METHODS from_xml
      IMPORTING
        !iv_xml        TYPE string
      RETURNING
        VALUE(rs_user) TYPE ty_user
      RAISING
        zcx_abapgit_exception .
    METHODS read
      RETURNING
        VALUE(rs_user) TYPE ty_user
      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
      IMPORTING
        !is_user TYPE ty_user
      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_persistence_user IMPLEMENTATION.

  METHOD constructor.
    mv_user = iv_user.
  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 '<USER>'.
    REPLACE ALL OCCURRENCES OF '</_--28C_TYPE_USER_--29>' IN lv_xml WITH '</USER>'.

    CALL TRANSFORMATION id
      OPTIONS value_handling = 'accept_data_loss'
      SOURCE XML lv_xml
      RESULT user = rs_user ##NO_TEXT.
  ENDMETHOD.

  METHOD get_changes_only.

    rv_changes_only = read( )-changes_only.

  ENDMETHOD. "get_changes_only

  METHOD get_default_git_user_email.

    rv_email = read( )-default_git_user-email.

  ENDMETHOD.

  METHOD get_default_git_user_name.

    rv_username = read( )-default_git_user-name.

  ENDMETHOD.

  METHOD get_diff_unified.

    rv_diff_unified = read( )-diff_unified.

  ENDMETHOD. "get_diff_unified

  METHOD get_favorites.

    rt_favorites = read( )-favorites.

  ENDMETHOD.  "get_favorites

  METHOD get_hide_files.

    rv_hide = read( )-hide_files.

  ENDMETHOD. "get_hide_files

  METHOD get_instance.

    IF iv_user = sy-uname ##USER_OK.
      IF go_current_user IS NOT BOUND.
        CREATE OBJECT go_current_user.
      ENDIF.
      ro_user = go_current_user.
    ELSE.
      CREATE OBJECT ro_user
        EXPORTING
          iv_user = iv_user.
    ENDIF.

  ENDMETHOD.

  METHOD get_repo_git_user_email.

    rv_email = read_repo_config( iv_url )-git_user-email.

  ENDMETHOD.  "get_repo_email

  METHOD get_repo_git_user_name.

    rv_username = read_repo_config( iv_url )-git_user-name.

  ENDMETHOD.  "get_repo_username

  METHOD get_repo_last_change_seen.

    rv_version = read_repo_config( iv_url )-last_change_seen.

  ENDMETHOD.  "get_last_change_seen

  METHOD get_repo_login.

    rv_login = read_repo_config( iv_url )-login.

  ENDMETHOD.  "get_repo_login

  METHOD get_repo_show.

    rv_key = read( )-repo_show.

  ENDMETHOD.

  METHOD is_favorite_repo.

    DATA: lt_favorites TYPE tt_favorites.

    lt_favorites = get_favorites( ).

    READ TABLE lt_favorites TRANSPORTING NO FIELDS
      WITH KEY table_line = iv_repo_key.

    rv_yes = boolc( sy-subrc = 0 ).

  ENDMETHOD.  " is_favorite_repo.

  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.

    rs_user = from_xml( lv_xml ).

  ENDMETHOD.

  METHOD read_repo_config.
    DATA: lt_repo_config TYPE ty_repo_config_tt,
          lv_key         TYPE string.

    lv_key         = to_lower( iv_url ).
    lt_repo_config = read( )-repo_config.
    READ TABLE lt_repo_config INTO rs_repo_config WITH KEY url = lv_key.

  ENDMETHOD.  "read_repo_config

  METHOD set_default_git_user_email.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-default_git_user-email = iv_email.
    update( ls_user ).

  ENDMETHOD.

  METHOD set_default_git_user_name.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).

    ls_user-default_git_user-name = iv_username.

    update( ls_user ).

  ENDMETHOD.

  METHOD 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.  "set_repo_email

  METHOD 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.  "set_repo_username

  METHOD 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.  "set_last_change_seen

  METHOD 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.  "set_repo_login

  METHOD set_repo_show.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-repo_show = iv_key.
    update( ls_user ).

    COMMIT WORK AND WAIT.

  ENDMETHOD.

  METHOD toggle_changes_only.

    DATA ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-changes_only = boolc( ls_user-changes_only = abap_false ).
    update( ls_user ).

    rv_changes_only = ls_user-changes_only.

  ENDMETHOD. "toggle_changes_only

  METHOD toggle_diff_unified.

    DATA ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-diff_unified = boolc( ls_user-diff_unified = abap_false ).
    update( ls_user ).

    rv_diff_unified = ls_user-diff_unified.

  ENDMETHOD. "toggle_diff_unified

  METHOD toggle_favorite.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).

    READ TABLE ls_user-favorites TRANSPORTING NO FIELDS
      WITH KEY table_line = iv_repo_key.

    IF sy-subrc = 0.
      DELETE ls_user-favorites INDEX sy-tabix.
    ELSE.
      APPEND iv_repo_key TO ls_user-favorites.
    ENDIF.

    update( ls_user ).

  ENDMETHOD.  " toggle_favorite.

  METHOD toggle_hide_files.

    DATA ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-hide_files = boolc( ls_user-hide_files = abap_false ).
    update( ls_user ).

    rv_hide = ls_user-hide_files.

  ENDMETHOD. "toggle_hide_files

  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( is_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 ).

  ENDMETHOD.

  METHOD update_repo_config.

    DATA: ls_user TYPE ty_user,
          lv_key  TYPE string.

    FIELD-SYMBOLS <ls_repo_config> TYPE ty_repo_config.

    ls_user = read( ).
    lv_key  = to_lower( iv_url ).

    READ TABLE ls_user-repo_config ASSIGNING <ls_repo_config> WITH KEY url = lv_key.
    IF sy-subrc IS NOT INITIAL.
      APPEND INITIAL LINE TO ls_user-repo_config ASSIGNING <ls_repo_config>.
    ENDIF.
    <ls_repo_config>     = is_repo_config.
    <ls_repo_config>-url = lv_key.

    update( ls_user ).

    COMMIT WORK AND WAIT.

  ENDMETHOD.  "update_repo_config

  METHOD get_settings.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).

    rs_user_settings = ls_user-settings.

  ENDMETHOD.

  METHOD set_settings.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-settings = is_user_settings.
    update( ls_user ).

  ENDMETHOD.

ENDCLASS.

CLASS zcl_abapgit_persistence_user DEFINITION
  PUBLIC
  CREATE PRIVATE .

  PUBLIC SECTION.

    TYPES tt_favorites TYPE zif_abapgit_persistence=>tt_repo_keys .

    CLASS-METHODS get_instance
      IMPORTING
        !iv_user       TYPE xubname DEFAULT sy-uname
      RETURNING
        VALUE(ro_user) TYPE REF TO zcl_abapgit_persistence_user .
    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 tt_favorites
      RAISING
        zcx_abapgit_exception .
    METHODS get_hide_files
      RETURNING
        VALUE(rv_hide) 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 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 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.
  PRIVATE SECTION.

    TYPES:
      BEGIN OF ty_repo_config,
        url              TYPE zif_abapgit_persistence=>ty_repo-url,
        login            TYPE string,
        git_user         TYPE zif_abapgit_definitions=>ty_git_user,
        last_change_seen TYPE string,
      END OF ty_repo_config .
    TYPES:
      ty_repo_config_tt TYPE STANDARD TABLE OF ty_repo_config WITH DEFAULT KEY .
    TYPES:
      BEGIN OF ty_user,
        default_git_user TYPE zif_abapgit_definitions=>ty_git_user,
        repo_show        TYPE zif_abapgit_persistence=>ty_repo-key,
        hide_files       TYPE abap_bool,
        changes_only     TYPE abap_bool,
        diff_unified     TYPE abap_bool,
        favorites        TYPE tt_favorites,
        repo_config      TYPE ty_repo_config_tt,
        settings         TYPE zif_abapgit_definitions=>ty_s_user_settings,
      END OF ty_user .

    DATA mv_user TYPE xubname .
    CLASS-DATA go_current_user TYPE REF TO zcl_abapgit_persistence_user .

    METHODS constructor
      IMPORTING
        !iv_user TYPE xubname DEFAULT sy-uname .
    METHODS from_xml
      IMPORTING
        !iv_xml        TYPE string
      RETURNING
        VALUE(rs_user) TYPE ty_user
      RAISING
        zcx_abapgit_exception .
    METHODS read
      RETURNING
        VALUE(rs_user) TYPE ty_user
      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
      IMPORTING
        !is_user TYPE ty_user
      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_persistence_user IMPLEMENTATION.

  METHOD constructor.
    mv_user = iv_user.
  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 '<USER>'.
    REPLACE ALL OCCURRENCES OF '</_--28C_TYPE_USER_--29>' IN lv_xml WITH '</USER>'.

    CALL TRANSFORMATION id
      OPTIONS value_handling = 'accept_data_loss'
      SOURCE XML lv_xml
      RESULT user = rs_user ##NO_TEXT.
  ENDMETHOD.

  METHOD get_changes_only.

    rv_changes_only = read( )-changes_only.

  ENDMETHOD. "get_changes_only

  METHOD get_default_git_user_email.

    rv_email = read( )-default_git_user-email.

  ENDMETHOD.

  METHOD get_default_git_user_name.

    rv_username = read( )-default_git_user-name.

  ENDMETHOD.

  METHOD get_diff_unified.

    rv_diff_unified = read( )-diff_unified.

  ENDMETHOD. "get_diff_unified

  METHOD get_favorites.

    rt_favorites = read( )-favorites.

  ENDMETHOD.  "get_favorites

  METHOD get_hide_files.

    rv_hide = read( )-hide_files.

  ENDMETHOD. "get_hide_files

  METHOD get_instance.

    IF iv_user = sy-uname ##USER_OK.
      IF go_current_user IS NOT BOUND.
        CREATE OBJECT go_current_user.
      ENDIF.
      ro_user = go_current_user.
    ELSE.
      CREATE OBJECT ro_user
        EXPORTING
          iv_user = iv_user.
    ENDIF.

  ENDMETHOD.

  METHOD get_repo_git_user_email.

    rv_email = read_repo_config( iv_url )-git_user-email.

  ENDMETHOD.  "get_repo_email

  METHOD get_repo_git_user_name.

    rv_username = read_repo_config( iv_url )-git_user-name.

  ENDMETHOD.  "get_repo_username

  METHOD get_repo_last_change_seen.

    rv_version = read_repo_config( iv_url )-last_change_seen.

  ENDMETHOD.  "get_last_change_seen

  METHOD get_repo_login.

    rv_login = read_repo_config( iv_url )-login.

  ENDMETHOD.  "get_repo_login

  METHOD get_repo_show.

    rv_key = read( )-repo_show.

  ENDMETHOD.

  METHOD is_favorite_repo.

    DATA: lt_favorites TYPE tt_favorites.

    lt_favorites = get_favorites( ).

    READ TABLE lt_favorites TRANSPORTING NO FIELDS
      WITH KEY table_line = iv_repo_key.

    rv_yes = boolc( sy-subrc = 0 ).

  ENDMETHOD.  " is_favorite_repo.

  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.

    rs_user = from_xml( lv_xml ).

  ENDMETHOD.

  METHOD read_repo_config.
    DATA: lt_repo_config TYPE ty_repo_config_tt,
          lv_key         TYPE string.

    lv_key         = to_lower( iv_url ).
    lt_repo_config = read( )-repo_config.
    READ TABLE lt_repo_config INTO rs_repo_config WITH KEY url = lv_key.

  ENDMETHOD.  "read_repo_config

  METHOD set_default_git_user_email.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-default_git_user-email = iv_email.
    update( ls_user ).

  ENDMETHOD.

  METHOD set_default_git_user_name.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).

    ls_user-default_git_user-name = iv_username.

    update( ls_user ).

  ENDMETHOD.

  METHOD 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.  "set_repo_email

  METHOD 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.  "set_repo_username

  METHOD 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.  "set_last_change_seen

  METHOD 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.  "set_repo_login

  METHOD set_repo_show.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-repo_show = iv_key.
    update( ls_user ).

    COMMIT WORK AND WAIT.

  ENDMETHOD.

  METHOD toggle_changes_only.

    DATA ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-changes_only = boolc( ls_user-changes_only = abap_false ).
    update( ls_user ).

    rv_changes_only = ls_user-changes_only.

  ENDMETHOD. "toggle_changes_only

  METHOD toggle_diff_unified.

    DATA ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-diff_unified = boolc( ls_user-diff_unified = abap_false ).
    update( ls_user ).

    rv_diff_unified = ls_user-diff_unified.

  ENDMETHOD. "toggle_diff_unified

  METHOD toggle_favorite.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).

    READ TABLE ls_user-favorites TRANSPORTING NO FIELDS
      WITH KEY table_line = iv_repo_key.

    IF sy-subrc = 0.
      DELETE ls_user-favorites INDEX sy-tabix.
    ELSE.
      APPEND iv_repo_key TO ls_user-favorites.
    ENDIF.

    update( ls_user ).

    COMMIT WORK AND WAIT.

  ENDMETHOD.  " toggle_favorite.

  METHOD toggle_hide_files.

    DATA ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-hide_files = boolc( ls_user-hide_files = abap_false ).
    update( ls_user ).

    rv_hide = ls_user-hide_files.

  ENDMETHOD. "toggle_hide_files

  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( is_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 ).

  ENDMETHOD.

  METHOD update_repo_config.

    DATA: ls_user TYPE ty_user,
          lv_key  TYPE string.

    FIELD-SYMBOLS <ls_repo_config> TYPE ty_repo_config.

    ls_user = read( ).
    lv_key  = to_lower( iv_url ).

    READ TABLE ls_user-repo_config ASSIGNING <ls_repo_config> WITH KEY url = lv_key.
    IF sy-subrc IS NOT INITIAL.
      APPEND INITIAL LINE TO ls_user-repo_config ASSIGNING <ls_repo_config>.
    ENDIF.
    <ls_repo_config>     = is_repo_config.
    <ls_repo_config>-url = lv_key.

    update( ls_user ).

    COMMIT WORK AND WAIT.

  ENDMETHOD.  "update_repo_config

  METHOD get_settings.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).

    rs_user_settings = ls_user-settings.

  ENDMETHOD.

  METHOD set_settings.

    DATA: ls_user TYPE ty_user.

    ls_user = read( ).
    ls_user-settings = is_user_settings.
    update( ls_user ).

  ENDMETHOD.

ENDCLASS.

add commit to toggle_favorites

add commit to toggle_favorites


CLASS zcl_abapgit_http_digest DEFINITION
  PUBLIC
  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.

  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_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,
          lv_hash TYPE xstring.

    lv_xstr = zcl_abapgit_convert=>string_to_xstring_utf8( iv_data ).

    CALL FUNCTION 'CALCULATE_HASH_FOR_RAW'
      EXPORTING
        alg            = 'MD5'
        data           = lv_xstr
      IMPORTING
        hashxstring    = lv_hash
      EXCEPTIONS
        unknown_alg    = 1
        param_error    = 2
        internal_error = 3
        OTHERS         = 4.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error from CALCULATE_HASH_FOR_RAW' ).
    ENDIF.

    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_digest DEFINITION
  PUBLIC
  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_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.

use cl_abap_hmac for calculating md5 (#4355)


CLASS zcl_abapgit_object_tobj DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.

  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_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.

    SELECT * FROM tvimf INTO TABLE rs_tobj-tvimf WHERE tabname = iv_tabname.

  ENDMETHOD.

  METHOD update_extra.
    DATA: lt_current_tvimf TYPE STANDARD TABLE OF tvimf.
    FIELD-SYMBOLS: <ls_tvimf> 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 <ls_tvimf>.
      READ TABLE is_tobj-tvimf WITH KEY tabname = <ls_tvimf>-tabname
                                        event   = <ls_tvimf>-event
                               TRANSPORTING NO FIELDS.
      IF sy-subrc <> 0.
        DELETE FROM tvimf
          WHERE tabname = <ls_tvimf>-tabname
          AND event = <ls_tvimf>-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.

    CALL FUNCTION 'OBJ_GENERATE'
      EXPORTING
        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( 'error from OBJ_GENERATE' ).
    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_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( 'error from OBJ_GENERATE' ).
    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( 'error from OBJ_SET_IMPORTABLE' ).
    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.

    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_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-late_deser = abap_true.
    rs_metadata-delete_tadir = abap_true.
  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.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Jump not possible. Subrc={ sy-subrc } from TR_OBJECT_JUMP_TO_TOOL| ).
    ENDIF.

  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( 'error from CTO_OBJECT_GET' ).
    ENDIF.

    CLEAR: ls_objh-luser,
           ls_objh-ldate.

    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 ).

    io_xml->add( iv_name = 'TOBJ'
                 ig_data = ls_tobj ).

  ENDMETHOD.
ENDCLASS.

CLASS zcl_abapgit_object_tobj DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.

  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_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.

  ENDMETHOD.

  METHOD update_extra.
    DATA: lt_current_tvimf TYPE STANDARD TABLE OF tvimf.
    FIELD-SYMBOLS: <ls_tvimf> 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 <ls_tvimf>.
      READ TABLE is_tobj-tvimf WITH KEY tabname = <ls_tvimf>-tabname
                                        event   = <ls_tvimf>-event
                               TRANSPORTING NO FIELDS.
      IF sy-subrc <> 0.
        DELETE FROM tvimf
          WHERE tabname = <ls_tvimf>-tabname
          AND event = <ls_tvimf>-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.

    CALL FUNCTION 'OBJ_GENERATE'
      EXPORTING
        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( 'error from OBJ_GENERATE' ).
    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_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( 'error from OBJ_GENERATE' ).
    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( 'error from OBJ_SET_IMPORTABLE' ).
    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_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-late_deser = abap_true.
    rs_metadata-delete_tadir = abap_true.
  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.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Jump not possible. Subrc={ sy-subrc } from TR_OBJECT_JUMP_TO_TOOL| ).
    ENDIF.

  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( 'error from CTO_OBJECT_GET' ).
    ENDIF.

    CLEAR: ls_objh-luser,
           ls_objh-ldate.

    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 ).

    io_xml->add( iv_name = 'TOBJ'
                 ig_data = ls_tobj ).

  ENDMETHOD.
ENDCLASS.

Clear package (#3632)

TOBJ: Clear package (#3632)

Closes https://github.com/larshp/abapGit/issues/3627

Co-authored-by: Lars Hvam <721d1b171982cd84b755f6b25130d2b88cd1f696@hotmail.com>