CLASS zcl_abapgit_object_sprx DEFINITION
INHERITING FROM zcl_abapgit_objects_super
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES:
      zif_abapgit_object.

    METHODS:
      constructor
        IMPORTING
          is_item     TYPE zif_abapgit_definitions=>ty_item
          iv_language TYPE spras
        RAISING
          zcx_abapgit_exception.

  PRIVATE SECTION.
    CONSTANTS:
      BEGIN OF c_proxy,
        data   TYPE string VALUE 'PROXY_DATA' ##NO_TEXT,
        header TYPE string VALUE 'PROXY_HEADER' ##NO_TEXT,
      END OF c_proxy.

    METHODS:
      get_object_and_name
        EXPORTING
          ev_object   TYPE sproxhdr-object
          ev_obj_name TYPE sproxhdr-obj_name,

      activate_classes
        IMPORTING
          it_sproxdat_new TYPE sprx_dat_t
        RAISING
          zcx_abapgit_exception,

      generate_service_definition
        IMPORTING
          it_sproxdat_new TYPE sprx_dat_t
        RAISING
          zcx_abapgit_exception,

      delta_handling
        IMPORTING
          io_xml          TYPE REF TO zcl_abapgit_xml_input
        EXPORTING
          et_sproxhdr_new TYPE sprx_hdr_t
          et_sproxdat_new TYPE sprx_dat_t
        RAISING
          zcx_abapgit_exception,

      check_sprx_tadir
        RAISING
          zcx_abapgit_exception,

      dequeue_proxy
        RAISING
          zcx_abapgit_exception,

      save
        IMPORTING
          it_sproxhdr_new TYPE sprx_hdr_t
          it_sproxdat_new TYPE sprx_dat_t.

    DATA:
      mv_object   TYPE sproxhdr-object,
      mv_obj_name TYPE sproxhdr-obj_name.

ENDCLASS.

CLASS zcl_abapgit_object_sprx IMPLEMENTATION.

  METHOD activate_classes.

    DATA: lt_objects TYPE STANDARD TABLE OF dwinactiv,
          ls_object  LIKE LINE OF lt_objects.

    FIELD-SYMBOLS: <ls_sproxdat_new> TYPE sprx_dat.

    " Somehow the classes aren't activated by the proxy framework.
    " This seems weird and it's almost certain a result of wrong API calls.
    " So as a quick fix we activate them ourselves. This surely has to
    " be improved in the future. ZCL_ABAPGIT_OBJECTS_ACTIVATION cannot
    " be used as it doesn't activate classes.

    LOOP AT it_sproxdat_new ASSIGNING <ls_sproxdat_new>
                            WHERE object1 = 'CLAS'.

      ls_object-object   = <ls_sproxdat_new>-object1.
      ls_object-obj_name = <ls_sproxdat_new>-obj_name1.
      INSERT ls_object INTO TABLE lt_objects.

    ENDLOOP.

    CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE'
      EXPORTING
        activate_ddic_objects  = abap_false
        with_popup             = abap_false
      TABLES
        objects                = lt_objects
      EXCEPTIONS
        excecution_error       = 1
        cancelled              = 2
        insert_into_corr_error = 3
        OTHERS                 = 4.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Error from RS_WORKING_OBJECTS_ACTIVATE. Subrc={ sy-subrc }| ).
    ENDIF.

  ENDMETHOD.

  METHOD constructor.

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

    get_object_and_name(
      IMPORTING
        ev_object   = mv_object
        ev_obj_name = mv_obj_name ).

  ENDMETHOD.

  METHOD delta_handling.

    DATA: lo_proxy   TYPE REF TO cl_proxy,
          lt_delta   TYPE sprx_t_delta,
          ls_db_data TYPE sprx_db_data.

    "add Delta-Handling to avoid that single objects created without the dependent objects.
    "Thereby the dependent objects will be deleted
    TRY.
        lo_proxy = cl_proxy_fact=>load_by_abap_name(
                       object   = mv_object
                       obj_name = mv_obj_name ).

        lt_delta = lo_proxy->get_delta_all( ).

        ls_db_data = cl_proxy_db=>serialize(
                         proxy    = lo_proxy
                         inactive = abap_false
                         delta    = lt_delta ).

        et_sproxhdr_new = ls_db_data-sproxhdr.
        et_sproxdat_new = ls_db_data-sproxdat.

      CATCH cx_proxy_gen_error.
        "No delta for this object -> create

        io_xml->read(
          EXPORTING
            iv_name = c_proxy-header
          CHANGING
            cg_data = et_sproxhdr_new ).

        IF et_sproxhdr_new IS INITIAL.
          zcx_abapgit_exception=>raise( |SPRX - error deserialize: { ms_item-obj_name }| ).
        ENDIF.

        io_xml->read(
          EXPORTING
            iv_name = c_proxy-data
          CHANGING
            cg_data = et_sproxdat_new ).

    ENDTRY.

  ENDMETHOD.

  METHOD generate_service_definition.

    DATA: lv_transport    TYPE e070use-ordernum,
          lo_proxy_object TYPE REF TO cl_proxy_object,
          lx_proxy_fault  TYPE REF TO cx_proxy_fault.

    lv_transport = zcl_abapgit_default_transport=>get_instance(
                                               )->get( )-ordernum.

    TRY.
        lo_proxy_object = cl_pxn_factory=>create(
                              application  = 'PROXY_UI'
                              display_only = abap_false
                              saveable     = abap_true
                          )->load_by_abap_name_int(
                              object   = mv_object
                              obj_name = mv_obj_name
                          )->proxy.

        lo_proxy_object->activate(
          EXPORTING
            activate_all     = abap_true
          CHANGING
            transport_number = lv_transport ).

        lo_proxy_object->dequeue( ).

      CATCH cx_proxy_fault INTO lx_proxy_fault.
        zcx_abapgit_exception=>raise( iv_text     = |{ lx_proxy_fault->get_text( ) }|
                                      ix_previous = lx_proxy_fault ).
    ENDTRY.

    activate_classes( it_sproxdat_new ).

  ENDMETHOD.

  METHOD get_object_and_name.

    ev_object   = ms_item-obj_name(4).
    ev_obj_name = ms_item-obj_name+4.

  ENDMETHOD.

  METHOD zif_abapgit_object~changed_by.

    DATA lv_changed_by TYPE sproxhdr-changed_by.

    rv_user = c_user_unknown.

    SELECT SINGLE changed_by
           FROM sproxhdr
           INTO lv_changed_by
           WHERE object     = mv_object
           AND   obj_name   = mv_obj_name
           AND   inactive   = abap_false.

    IF  sy-subrc = 0
    AND lv_changed_by IS NOT INITIAL.
      rv_user = lv_changed_by.
    ENDIF.

  ENDMETHOD.

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

  METHOD zif_abapgit_object~delete.

    DATA:
      lv_object      TYPE sproxhdr-object,
      lv_obj_name    TYPE sproxhdr-obj_name,
      lv_return_code TYPE i,
      lt_log         TYPE sprx_log_t.

    get_object_and_name(
      IMPORTING
        ev_object   = lv_object
        ev_obj_name = lv_obj_name ).

    cl_proxy_data=>delete_single_proxy(
       EXPORTING
         object           = lv_object
         obj_name         = lv_obj_name
       CHANGING
         c_return_code    = lv_return_code
         ct_log           = lt_log ).
    IF lv_return_code <> 0.
      zcx_abapgit_exception=>raise( 'SPRX: Error from DELETE_SINGLE_PROXY' ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_object~deserialize.

    DATA: lt_sproxhdr_new TYPE sprx_hdr_t,
          lt_sproxdat_new TYPE sprx_dat_t.

    tadir_insert( iv_package ).

    delta_handling(
      EXPORTING
        io_xml = io_xml
      IMPORTING
        et_sproxhdr_new = lt_sproxhdr_new
        et_sproxdat_new = lt_sproxdat_new ).

    save(
      it_sproxhdr_new = lt_sproxhdr_new
      it_sproxdat_new = lt_sproxdat_new ).

    check_sprx_tadir( ).

    dequeue_proxy( ).

    IF mv_object = 'INTF'.
      generate_service_definition( lt_sproxdat_new ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_object~exists.

    DATA:
      lv_status      TYPE prx_status,
      lv_status_text TYPE prx_status_t.

    cl_proxy_data=>db_get_status(
      EXPORTING
        object      = mv_object
        obj_name    = mv_obj_name
      IMPORTING
        status      = lv_status
        status_text = lv_status_text ).

    IF lv_status = if_proxy=>c_state_active.
      rv_bool = abap_true.
    ELSE.
      rv_bool = abap_false.
    ENDIF.

  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~is_active.
    rv_active = abap_true. "dummy implementation
  ENDMETHOD.

  METHOD zif_abapgit_object~is_locked.
    rv_is_locked = abap_false.
  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    CALL FUNCTION 'RS_TOOL_ACCESS'
      EXPORTING
        operation     = 'SHOW'
        object_name   = ms_item-obj_name
        object_type   = ms_item-obj_type
        in_new_window = abap_true.

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA:
      lo_proxy        TYPE REF TO cl_proxy,
      ls_sprx_db_data TYPE sprx_db_data,
      lt_delta        TYPE sprx_t_delta.

    FIELD-SYMBOLS:
      <ls_sproxheader> LIKE LINE OF ls_sprx_db_data-sproxhdr,
      <ls_sproxdat>    TYPE sprx_dat.

    IF zif_abapgit_object~exists( ) = abap_false.
      RETURN.
    ENDIF.

    TRY.
        lo_proxy = cl_proxy_fact=>load_by_abap_name(
                      object   = mv_object
                      obj_name = mv_obj_name ).

        lt_delta = lo_proxy->get_delta_all( ).

        ls_sprx_db_data = cl_proxy_db=>serialize(
                              proxy     = lo_proxy
                              inactive  = abap_false
                              delta     = lt_delta ).

        LOOP AT ls_sprx_db_data-sproxhdr ASSIGNING <ls_sproxheader>.

          CLEAR:
            <ls_sproxheader>-created_by,
            <ls_sproxheader>-created_on,
            <ls_sproxheader>-changed_by,
            <ls_sproxheader>-changed_on.

        ENDLOOP.

        LOOP AT ls_sprx_db_data-sproxdat ASSIGNING <ls_sproxdat>.

          CLEAR <ls_sproxdat>-warnings.

        ENDLOOP.

        io_xml->add(
            iv_name = c_proxy-header
            ig_data = ls_sprx_db_data-sproxhdr ).

        io_xml->add(
            iv_name = c_proxy-data
            ig_data = ls_sprx_db_data-sproxdat ).

      CATCH cx_proxy_gen_error.
        zcx_abapgit_exception=>raise( |SPRX - error load proxy { mv_obj_name }| ).
    ENDTRY.

  ENDMETHOD.

  METHOD check_sprx_tadir.

    DATA: lt_abap_keys TYPE prx_abapobjects,
          ls_abap_key  LIKE LINE OF lt_abap_keys,
          lx_error     TYPE REF TO cx_proxy_gen_error.

    ls_abap_key-object   = mv_object.
    ls_abap_key-obj_name = mv_obj_name.
    APPEND ls_abap_key TO lt_abap_keys.

    TRY.
        cl_proxy_utils=>check_sprx_tadir(
            objects = lt_abap_keys
            repair  = abap_true ).

      CATCH cx_proxy_gen_error INTO lx_error.
        zcx_abapgit_exception=>raise( iv_text     = |{ lx_error->get_text( ) }|
                                      ix_previous = lx_error ).
    ENDTRY.

  ENDMETHOD.

  METHOD dequeue_proxy.

    DATA: lo_proxy TYPE REF TO cl_proxy,
          lx_error TYPE REF TO cx_proxy_gen_error.

    TRY.
        lo_proxy = cl_proxy_fact=>load_by_abap_name(
                       object   = mv_object
                       obj_name = mv_obj_name ).

        lo_proxy->dequeue( ).

      CATCH cx_proxy_gen_error INTO lx_error.
        zcx_abapgit_exception=>raise( iv_text     = |{ lx_error->get_text( ) }|
                                      ix_previous = lx_error ).
    ENDTRY.

  ENDMETHOD.

  METHOD save.

    DATA:
      lt_sproxhdr_old  TYPE sprx_hdr_t,
      lt_sproxdat_old  TYPE sprx_dat_t,
      lt_sproxsvar_old TYPE sprx_svar_t,
      lt_sproxintf_old TYPE sprx_matchintf_t,
      lt_sproxsvar_new TYPE sprx_svar_t,
      lt_sproxintf_new TYPE sprx_matchintf_t.

    cl_proxy_data=>db_save(
        sproxhdr_old  = lt_sproxhdr_old
        sproxdat_old  = lt_sproxdat_old
        sproxsvar_old = lt_sproxsvar_old
        sproxintf_old = lt_sproxintf_old
        sproxhdr_new  = it_sproxhdr_new
        sproxdat_new  = it_sproxdat_new
        sproxsvar_new = lt_sproxsvar_new
        sproxintf_new = lt_sproxintf_new ).

  ENDMETHOD.

ENDCLASS.

CLASS zcl_abapgit_object_sprx DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES:
      zif_abapgit_object.

    METHODS:
      constructor
        IMPORTING
          is_item     TYPE zif_abapgit_definitions=>ty_item
          iv_language TYPE spras
        RAISING
          zcx_abapgit_exception.

  PRIVATE SECTION.
    CONSTANTS:
      BEGIN OF c_proxy,
        data   TYPE string VALUE 'PROXY_DATA' ##NO_TEXT,
        header TYPE string VALUE 'PROXY_HEADER' ##NO_TEXT,
      END OF c_proxy.

    METHODS:
      get_object_and_name
        EXPORTING
          ev_object   TYPE sproxhdr-object
          ev_obj_name TYPE sproxhdr-obj_name,

      activate_classes
        IMPORTING
          it_sproxdat_new TYPE sprx_dat_t
        RAISING
          zcx_abapgit_exception,

      generate_service_definition
        IMPORTING
          it_sproxdat_new TYPE sprx_dat_t
        RAISING
          zcx_abapgit_exception,

      delta_handling
        IMPORTING
          io_xml          TYPE REF TO zcl_abapgit_xml_input
        EXPORTING
          et_sproxhdr_new TYPE sprx_hdr_t
          et_sproxdat_new TYPE sprx_dat_t
        RAISING
          zcx_abapgit_exception,

      check_sprx_tadir
        RAISING
          zcx_abapgit_exception,

      dequeue_proxy
        RAISING
          zcx_abapgit_exception,

      save
        IMPORTING
          it_sproxhdr_new TYPE sprx_hdr_t
          it_sproxdat_new TYPE sprx_dat_t.

    DATA:
      mv_object   TYPE sproxhdr-object,
      mv_obj_name TYPE sproxhdr-obj_name.

ENDCLASS.

CLASS zcl_abapgit_object_sprx IMPLEMENTATION.

  METHOD activate_classes.

    DATA: lt_objects TYPE STANDARD TABLE OF dwinactiv,
          ls_object  LIKE LINE OF lt_objects.

    FIELD-SYMBOLS: <ls_sproxdat_new> TYPE sprx_dat.

    " Somehow the classes aren't activated by the proxy framework.
    " This seems weird and it's almost certain a result of wrong API calls.
    " So as a quick fix we activate them ourselves. This surely has to
    " be improved in the future. ZCL_ABAPGIT_OBJECTS_ACTIVATION cannot
    " be used as it doesn't activate classes.

    LOOP AT it_sproxdat_new ASSIGNING <ls_sproxdat_new>
                            WHERE object1 = 'CLAS'.

      ls_object-object   = <ls_sproxdat_new>-object1.
      ls_object-obj_name = <ls_sproxdat_new>-obj_name1.
      INSERT ls_object INTO TABLE lt_objects.

    ENDLOOP.

    CALL FUNCTION 'RS_WORKING_OBJECTS_ACTIVATE'
      EXPORTING
        activate_ddic_objects  = abap_false
        with_popup             = abap_false
      TABLES
        objects                = lt_objects
      EXCEPTIONS
        excecution_error       = 1
        cancelled              = 2
        insert_into_corr_error = 3
        OTHERS                 = 4.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Error from RS_WORKING_OBJECTS_ACTIVATE. Subrc={ sy-subrc }| ).
    ENDIF.

  ENDMETHOD.

  METHOD constructor.

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

    get_object_and_name(
      IMPORTING
        ev_object   = mv_object
        ev_obj_name = mv_obj_name ).

  ENDMETHOD.

  METHOD delta_handling.

    DATA: lo_proxy   TYPE REF TO cl_proxy,
          lt_delta   TYPE sprx_t_delta,
          ls_db_data TYPE sprx_db_data.

    "add Delta-Handling to avoid that single objects created without the dependent objects.
    "Thereby the dependent objects will be deleted
    TRY.
        lo_proxy = cl_proxy_fact=>load_by_abap_name(
                       object   = mv_object
                       obj_name = mv_obj_name ).

        lt_delta = lo_proxy->get_delta_all( ).

        ls_db_data = cl_proxy_db=>serialize(
                         proxy    = lo_proxy
                         inactive = abap_false
                         delta    = lt_delta ).

        et_sproxhdr_new = ls_db_data-sproxhdr.
        et_sproxdat_new = ls_db_data-sproxdat.

      CATCH cx_proxy_gen_error.
        "No delta for this object -> create

        io_xml->read(
          EXPORTING
            iv_name = c_proxy-header
          CHANGING
            cg_data = et_sproxhdr_new ).

        IF et_sproxhdr_new IS INITIAL.
          zcx_abapgit_exception=>raise( |SPRX - error deserialize: { ms_item-obj_name }| ).
        ENDIF.

        io_xml->read(
          EXPORTING
            iv_name = c_proxy-data
          CHANGING
            cg_data = et_sproxdat_new ).

    ENDTRY.

  ENDMETHOD.

  METHOD generate_service_definition.

    DATA: lv_transport    TYPE e070use-ordernum,
          lo_proxy_object TYPE REF TO cl_proxy_object,
          lx_proxy_fault  TYPE REF TO cx_proxy_fault.

    lv_transport = zcl_abapgit_default_transport=>get_instance(
                                               )->get( )-ordernum.

    TRY.
        lo_proxy_object = cl_pxn_factory=>create(
                              application  = 'PROXY_UI'
                              display_only = abap_false
                              saveable     = abap_true
                          )->load_by_abap_name_int(
                              object   = mv_object
                              obj_name = mv_obj_name
                          )->proxy.

        lo_proxy_object->activate(
          EXPORTING
            activate_all     = abap_true
          CHANGING
            transport_number = lv_transport ).

        lo_proxy_object->dequeue( ).

      CATCH cx_proxy_fault INTO lx_proxy_fault.
        zcx_abapgit_exception=>raise( iv_text     = |{ lx_proxy_fault->get_text( ) }|
                                      ix_previous = lx_proxy_fault ).
    ENDTRY.

    activate_classes( it_sproxdat_new ).

  ENDMETHOD.

  METHOD get_object_and_name.

    ev_object   = ms_item-obj_name(4).
    ev_obj_name = ms_item-obj_name+4.

  ENDMETHOD.

  METHOD zif_abapgit_object~changed_by.

    DATA lv_changed_by TYPE sproxhdr-changed_by.

    rv_user = c_user_unknown.

    SELECT SINGLE changed_by
           FROM sproxhdr
           INTO lv_changed_by
           WHERE object     = mv_object
           AND   obj_name   = mv_obj_name
           AND   inactive   = abap_false.

    IF  sy-subrc = 0
    AND lv_changed_by IS NOT INITIAL.
      rv_user = lv_changed_by.
    ENDIF.

  ENDMETHOD.

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

  METHOD zif_abapgit_object~delete.

    DATA:
      lv_object      TYPE sproxhdr-object,
      lv_obj_name    TYPE sproxhdr-obj_name,
      lv_return_code TYPE i,
      lt_log         TYPE sprx_log_t.

    get_object_and_name(
      IMPORTING
        ev_object   = lv_object
        ev_obj_name = lv_obj_name ).

    cl_proxy_data=>delete_single_proxy(
       EXPORTING
         object           = lv_object
         obj_name         = lv_obj_name
       CHANGING
         c_return_code    = lv_return_code
         ct_log           = lt_log ).
    IF lv_return_code <> 0.
      zcx_abapgit_exception=>raise( 'SPRX: Error from DELETE_SINGLE_PROXY' ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_object~deserialize.

    DATA: lt_sproxhdr_new TYPE sprx_hdr_t,
          lt_sproxdat_new TYPE sprx_dat_t.

    tadir_insert( iv_package ).

    delta_handling(
      EXPORTING
        io_xml = io_xml
      IMPORTING
        et_sproxhdr_new = lt_sproxhdr_new
        et_sproxdat_new = lt_sproxdat_new ).

    save(
      it_sproxhdr_new = lt_sproxhdr_new
      it_sproxdat_new = lt_sproxdat_new ).

    check_sprx_tadir( ).

    dequeue_proxy( ).

    IF mv_object = 'INTF'.
      generate_service_definition( lt_sproxdat_new ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_object~exists.

    DATA:
      lv_status      TYPE prx_status,
      lv_status_text TYPE prx_status_t.

    cl_proxy_data=>db_get_status(
      EXPORTING
        object      = mv_object
        obj_name    = mv_obj_name
      IMPORTING
        status      = lv_status
        status_text = lv_status_text ).

    IF lv_status = if_proxy=>c_state_active.
      rv_bool = abap_true.
    ELSE.
      rv_bool = abap_false.
    ENDIF.

  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~is_active.
    rv_active = abap_true. "dummy implementation
  ENDMETHOD.

  METHOD zif_abapgit_object~is_locked.
    rv_is_locked = abap_false.
  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    CALL FUNCTION 'RS_TOOL_ACCESS'
      EXPORTING
        operation     = 'SHOW'
        object_name   = ms_item-obj_name
        object_type   = ms_item-obj_type
        in_new_window = abap_true.

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA:
      lo_proxy        TYPE REF TO cl_proxy,
      ls_sprx_db_data TYPE sprx_db_data,
      lt_delta        TYPE sprx_t_delta.

    FIELD-SYMBOLS:
      <ls_sproxheader> LIKE LINE OF ls_sprx_db_data-sproxhdr,
      <ls_sproxdat>    TYPE sprx_dat.

    IF zif_abapgit_object~exists( ) = abap_false.
      RETURN.
    ENDIF.

    TRY.
        lo_proxy = cl_proxy_fact=>load_by_abap_name(
                      object   = mv_object
                      obj_name = mv_obj_name ).

        lt_delta = lo_proxy->get_delta_all( ).

        ls_sprx_db_data = cl_proxy_db=>serialize(
                              proxy     = lo_proxy
                              inactive  = abap_false
                              delta     = lt_delta ).

        LOOP AT ls_sprx_db_data-sproxhdr ASSIGNING <ls_sproxheader>.

          CLEAR:
            <ls_sproxheader>-created_by,
            <ls_sproxheader>-created_on,
            <ls_sproxheader>-changed_by,
            <ls_sproxheader>-changed_on.

        ENDLOOP.

        LOOP AT ls_sprx_db_data-sproxdat ASSIGNING <ls_sproxdat>.

          CLEAR <ls_sproxdat>-warnings.

        ENDLOOP.

        io_xml->add(
            iv_name = c_proxy-header
            ig_data = ls_sprx_db_data-sproxhdr ).

        io_xml->add(
            iv_name = c_proxy-data
            ig_data = ls_sprx_db_data-sproxdat ).

      CATCH cx_proxy_gen_error.
        zcx_abapgit_exception=>raise( |SPRX - error load proxy { mv_obj_name }| ).
    ENDTRY.

  ENDMETHOD.

  METHOD check_sprx_tadir.

    DATA: lt_abap_keys TYPE prx_abapobjects,
          ls_abap_key  LIKE LINE OF lt_abap_keys,
          lx_error     TYPE REF TO cx_proxy_gen_error.

    ls_abap_key-object   = mv_object.
    ls_abap_key-obj_name = mv_obj_name.
    APPEND ls_abap_key TO lt_abap_keys.

    TRY.
        cl_proxy_utils=>check_sprx_tadir(
            objects = lt_abap_keys
            repair  = abap_true ).

      CATCH cx_proxy_gen_error INTO lx_error.
        zcx_abapgit_exception=>raise( iv_text     = |{ lx_error->get_text( ) }|
                                      ix_previous = lx_error ).
    ENDTRY.

  ENDMETHOD.

  METHOD dequeue_proxy.

    DATA: lo_proxy TYPE REF TO cl_proxy,
          lx_error TYPE REF TO cx_proxy_gen_error.

    TRY.
        lo_proxy = cl_proxy_fact=>load_by_abap_name(
                       object   = mv_object
                       obj_name = mv_obj_name ).

        lo_proxy->dequeue( ).

      CATCH cx_proxy_gen_error INTO lx_error.
        zcx_abapgit_exception=>raise( iv_text     = |{ lx_error->get_text( ) }|
                                      ix_previous = lx_error ).
    ENDTRY.

  ENDMETHOD.

  METHOD save.

    DATA:
      lt_sproxhdr_old  TYPE sprx_hdr_t,
      lt_sproxdat_old  TYPE sprx_dat_t,
      lt_sproxsvar_old TYPE sprx_svar_t,
      lt_sproxintf_old TYPE sprx_matchintf_t,
      lt_sproxsvar_new TYPE sprx_svar_t,
      lt_sproxintf_new TYPE sprx_matchintf_t.

    cl_proxy_data=>db_save(
        sproxhdr_old  = lt_sproxhdr_old
        sproxdat_old  = lt_sproxdat_old
        sproxsvar_old = lt_sproxsvar_old
        sproxintf_old = lt_sproxintf_old
        sproxhdr_new  = it_sproxhdr_new
        sproxdat_new  = it_sproxdat_new
        sproxsvar_new = lt_sproxsvar_new
        sproxintf_new = lt_sproxintf_new ).

  ENDMETHOD.

ENDCLASS.

fix class definition

SPRX: fix class definition


CLASS zcl_abapgit_object_susc DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

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

ENDCLASS.

CLASS zcl_abapgit_object_susc IMPLEMENTATION.

  METHOD zif_abapgit_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_object~changed_by.
    rv_user = c_user_unknown. " todo
  ENDMETHOD.

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

  METHOD zif_abapgit_object~exists.

    DATA: lv_oclss TYPE tobc-oclss.

    SELECT SINGLE oclss FROM tobc INTO lv_oclss
      WHERE oclss = ms_item-obj_name.
    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA: ls_tobc  TYPE tobc,
          ls_tobct TYPE tobct.

    SELECT SINGLE * FROM tobc INTO ls_tobc
      WHERE oclss = ms_item-obj_name.
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    SELECT SINGLE * FROM tobct INTO ls_tobct
      WHERE oclss = ms_item-obj_name
      AND langu = mv_language.

    io_xml->add( iv_name = 'TOBC'
                 ig_data = ls_tobc ).
    io_xml->add( iv_name = 'TOBCT'
                 ig_data = ls_tobct ).

  ENDMETHOD.

  METHOD zif_abapgit_object~deserialize.
* see function group SUSA

    DATA: ls_tobc       TYPE tobc,
          lv_objectname TYPE e071-obj_name,
          ls_tobct      TYPE tobct.

    io_xml->read( EXPORTING iv_name = 'TOBC'
                  CHANGING cg_data = ls_tobc ).
    io_xml->read( EXPORTING iv_name = 'TOBCT'
                  CHANGING cg_data = ls_tobct ).

    tadir_insert( iv_package ).

    lv_objectname = ms_item-obj_name.
    CALL FUNCTION 'SUSR_COMMEDITCHECK'
      EXPORTING
        objectname      = lv_objectname
        transobjecttype = 'C'.

    INSERT tobc FROM ls_tobc.                             "#EC CI_SUBRC
* ignore sy-subrc as all fields are key fields

    MODIFY tobct FROM ls_tobct.                           "#EC CI_SUBRC
    ASSERT sy-subrc = 0.

  ENDMETHOD.

  METHOD zif_abapgit_object~delete.

    DATA: lv_objclass TYPE tobc-oclss.

    lv_objclass = ms_item-obj_name.
    CALL FUNCTION 'SUSR_DELETE_OBJECT_CLASS'
      EXPORTING
        objclass = lv_objclass.

  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    DATA: lv_objclass TYPE tobc-oclss.

    lv_objclass = ms_item-obj_name.
    CALL FUNCTION 'SUSR_SHOW_OBJECT_CLASS'
      EXPORTING
        objclass = lv_objclass.

  ENDMETHOD.

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

  METHOD zif_abapgit_object~is_locked.
    rv_is_locked = abap_false.
  ENDMETHOD.

  METHOD zif_abapgit_object~is_active.
    rv_active = is_active( ).
  ENDMETHOD.

ENDCLASS.

CLASS zcl_abapgit_object_susc 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.
    CONSTANTS transobjecttype_class TYPE char1 VALUE 'C' ##NO_TEXT.

    METHODS has_authorization
      IMPORTING iv_object_type TYPE seu_objid
                iv_class       TYPE tobc-oclss
                iv_activity    TYPE activ_auth
      RAISING   zcx_abapgit_exception.
    METHODS is_used
      IMPORTING iv_auth_object_class TYPE tobc-oclss
      RAISING   zcx_abapgit_exception.
  PRIVATE SECTION.
    METHODS delete_class
      IMPORTING iv_auth_object_class TYPE tobc-oclss.
    METHODS put_delete_to_transport
      IMPORTING iv_auth_object_class TYPE tobc-oclss
                iv_object_type       TYPE seu_objid
      RAISING   zcx_abapgit_exception.

ENDCLASS.

CLASS zcl_abapgit_object_susc IMPLEMENTATION.

  METHOD zif_abapgit_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_object~changed_by.
    rv_user = c_user_unknown. " todo
  ENDMETHOD.

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

  METHOD zif_abapgit_object~exists.

    DATA: lv_oclss TYPE tobc-oclss.

    SELECT SINGLE oclss FROM tobc INTO lv_oclss
      WHERE oclss = ms_item-obj_name.
    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA: ls_tobc  TYPE tobc,
          ls_tobct TYPE tobct.

    SELECT SINGLE * FROM tobc INTO ls_tobc
      WHERE oclss = ms_item-obj_name.
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    SELECT SINGLE * FROM tobct INTO ls_tobct
      WHERE oclss = ms_item-obj_name
      AND langu = mv_language.

    io_xml->add( iv_name = 'TOBC'
                 ig_data = ls_tobc ).
    io_xml->add( iv_name = 'TOBCT'
                 ig_data = ls_tobct ).

  ENDMETHOD.

  METHOD zif_abapgit_object~deserialize.
* see function group SUSA

    DATA: ls_tobc       TYPE tobc,
          lv_objectname TYPE e071-obj_name,
          ls_tobct      TYPE tobct.

    io_xml->read( EXPORTING iv_name = 'TOBC'
                  CHANGING cg_data = ls_tobc ).
    io_xml->read( EXPORTING iv_name = 'TOBCT'
                  CHANGING cg_data = ls_tobct ).

    tadir_insert( iv_package ).

    lv_objectname = ms_item-obj_name.
    CALL FUNCTION 'SUSR_COMMEDITCHECK'
      EXPORTING
        objectname      = lv_objectname
        transobjecttype = zcl_abapgit_object_susc=>transobjecttype_class.

    INSERT tobc FROM ls_tobc.                             "#EC CI_SUBRC
* ignore sy-subrc as all fields are key fields

    MODIFY tobct FROM ls_tobct.                           "#EC CI_SUBRC
    ASSERT sy-subrc = 0.

  ENDMETHOD.

  METHOD zif_abapgit_object~delete.
    CONSTANTS activity_delete_06 TYPE activ_auth VALUE '06'.

    DATA: lv_auth_object_class TYPE tobc-oclss.
    DATA: lv_object_type       TYPE seu_objid.
    DATA: lv_tr_object_name    TYPE e071-obj_name.
    DATA: lv_tr_return         TYPE char1.

    lv_auth_object_class = ms_item-obj_name.
    lv_object_type = ms_item-obj_type.

    TRY.
        me->zif_abapgit_object~exists( ).
      CATCH zcx_abapgit_exception.
        RETURN.
    ENDTRY.

    has_authorization( iv_object_type = lv_object_type
                       iv_class       = lv_auth_object_class
                       iv_activity    = activity_delete_06 ).

    is_used( lv_auth_object_class ).

    delete_class( lv_auth_object_class ).

    put_delete_to_transport( iv_auth_object_class = lv_auth_object_class
                             iv_object_type       = lv_object_type ).
  ENDMETHOD.

  METHOD put_delete_to_transport.

    DATA: lv_tr_object_name TYPE e071-obj_name.
    DATA: lv_tr_return      TYPE char1.
    DATA: Ls_package_info   TYPE tdevc.

    lv_tr_object_name = iv_auth_object_class.
    CALL FUNCTION 'SUSR_COMMEDITCHECK'
      EXPORTING
        objectname       = lv_tr_object_name
        transobjecttype  = zcl_abapgit_object_susc=>transobjecttype_class
      IMPORTING
        return_from_korr = lv_tr_return.

    IF lv_tr_return <> 'M'.
      zcx_abapgit_exception=>raise( |error in SUSC delete at SUSR_COMMEDITCHECK| ).
    ENDIF.

    CALL FUNCTION 'TR_DEVCLASS_GET'
      EXPORTING
        iv_devclass = ms_item-devclass
      IMPORTING
        es_tdevc    = ls_package_info
      EXCEPTIONS
        OTHERS      = 1.
    IF sy-subrc = 0 AND ls_package_info-korrflag IS INITIAL.
      CALL FUNCTION 'TR_TADIR_INTERFACE'
        EXPORTING
          wi_delete_tadir_entry = abap_true
          wi_test_modus         = space
          wi_tadir_pgmid        = 'R3TR'
          wi_tadir_object       = iv_object_type
          wi_tadir_obj_name     = lv_tr_object_name
        EXCEPTIONS
          OTHERS                = 0.
    ENDIF.

  ENDMETHOD.

  METHOD delete_class.

    DELETE FROM tobc  WHERE oclss = iv_auth_object_class.
    DELETE FROM tobct WHERE oclss = iv_auth_object_class.

  ENDMETHOD.

  METHOD is_used.

    DATA: lv_used_auth_object_class TYPE tobc-oclss.

    SELECT SINGLE oclss
      FROM tobj
      INTO lv_used_auth_object_class
      WHERE oclss = iv_auth_object_class ##WARN_OK.
    IF sy-subrc = 0.
      zcx_abapgit_exception=>raise_t100( iv_msgid = '01'
                                         iv_msgno = '212'
                                         iv_msgv1 = |{ iv_auth_object_class }| ).
    ENDIF.

  ENDMETHOD.

  METHOD has_authorization.

    AUTHORITY-CHECK OBJECT 'S_DEVELOP'
           ID 'DEVCLASS' DUMMY
           ID 'OBJTYPE' FIELD iv_object_type
           ID 'OBJNAME' FIELD iv_class
           ID 'P_GROUP' DUMMY
           ID 'ACTVT'   FIELD iv_activity.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise_t100( iv_msgid = '01'
                                         iv_msgno = '467' ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    DATA: lv_objclass TYPE tobc-oclss.

    lv_objclass = ms_item-obj_name.
    CALL FUNCTION 'SUSR_SHOW_OBJECT_CLASS'
      EXPORTING
        objclass = lv_objclass.

  ENDMETHOD.

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

  METHOD zif_abapgit_object~is_locked.
    rv_is_locked = abap_false.
  ENDMETHOD.

  METHOD zif_abapgit_object~is_active.
    rv_active = is_active( ).
  ENDMETHOD.

ENDCLASS.

SUSC: delete in more direct way - no confirm popup #2036 (#2079)

* SUSC: delete in more direct way - no confirm popup

delete needs to be done with a code copy of FM SUSR_DELETE_OBJECT_CLASS
I really hate this but there is no other way

* SUSC: delete in more direct way - no confirm popup

* test

* test

* naming conventions

* PP


*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_SERVICES_ABAPGIT
*&---------------------------------------------------------------------*

CLASS lcl_services_abapgit DEFINITION FINAL.
  PUBLIC SECTION.

    CONSTANTS c_abapgit_homepage TYPE string
      VALUE 'http://www.abapgit.org' ##NO_TEXT.
    CONSTANTS c_abapgit_wikipage TYPE string
      VALUE 'http://larshp.github.io/abapGit'.
    CONSTANTS c_package_abapgit  TYPE devclass
      VALUE '$ABAPGIT'.
    CONSTANTS c_package_plugins  TYPE devclass
      VALUE '$ABAPGIT_PLUGINS'.
    CONSTANTS c_abapgit_url      TYPE string
      VALUE 'https://github.com/larshp/abapGit.git'.
    CONSTANTS c_plugins_url      TYPE string
      VALUE 'https://github.com/larshp/abapGit-plugins.git'.

    CLASS-METHODS open_abapgit_homepage
      RAISING zcx_abapgit_exception.

    CLASS-METHODS open_abapgit_wikipage
      RAISING zcx_abapgit_exception.

    CLASS-METHODS install_abapgit
      RAISING zcx_abapgit_exception lcx_cancel.

    CLASS-METHODS install_abapgit_pi
      RAISING zcx_abapgit_exception lcx_cancel.

    CLASS-METHODS is_installed
      RETURNING VALUE(rv_installed) TYPE abap_bool.

    CLASS-METHODS is_installed_pi
      RETURNING VALUE(rv_installed) TYPE abap_bool.

  PRIVATE SECTION.

    CLASS-METHODS do_install
      IMPORTING iv_title   TYPE c
                iv_text    TYPE c
                iv_url     TYPE string
                iv_package TYPE devclass
      RAISING   zcx_abapgit_exception.

ENDCLASS. "lcl_services_abapgit

CLASS lcl_services_abapgit IMPLEMENTATION.

  METHOD open_abapgit_homepage.

    cl_gui_frontend_services=>execute(
      EXPORTING document = c_abapgit_homepage
      EXCEPTIONS OTHERS = 1 ).
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'Opening page in external browser failed.' ).
    ENDIF.

  ENDMETHOD.  "open_abapgit_homepage

  METHOD open_abapgit_wikipage.

    cl_gui_frontend_services=>execute(
      EXPORTING document = c_abapgit_wikipage
      EXCEPTIONS OTHERS = 1 ).
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'Opening page in external browser failed.' ).
    ENDIF.

  ENDMETHOD.  "open_abapgit_wikipage

  METHOD install_abapgit.

    CONSTANTS lc_title TYPE c LENGTH 40 VALUE 'Install abapGit'.
    DATA lv_text       TYPE c LENGTH 100.

    IF is_installed( ) = abap_true.
      lv_text = 'Seems like abapGit package is already installed. No changes to be done'.
      lcl_popups=>popup_to_inform(
        titlebar              = lc_title
        text_message          = lv_text ).
      RETURN.
    ENDIF.

    lv_text = |Confirm to install current version of abapGit to package { c_package_abapgit }|.

    do_install( iv_title   = lc_title
                iv_text    = lv_text
                iv_url     = c_abapgit_url
                iv_package = c_package_abapgit ).

  ENDMETHOD.  "install_abapgit

  METHOD install_abapgit_pi.

    CONSTANTS lc_title TYPE c LENGTH 40 VALUE 'Install abapGit plugins'.
    DATA lv_text       TYPE c LENGTH 100.

    IF is_installed_pi( ) = abap_true.
      lv_text = 'Seems like abapGit plugins package is already installed. No changes to be done'.
      lcl_popups=>popup_to_inform(
        titlebar              = lc_title
        text_message          = lv_text ).
      RETURN.
    ENDIF.

    lv_text = |Confirm to install current version abapGit plugins to package {
               c_package_plugins }|.

    do_install( iv_title   = lc_title
                iv_text    = lv_text
                iv_url     = c_plugins_url
                iv_package = c_package_plugins ).

  ENDMETHOD.  "install_abapgit_pi

  METHOD do_install.

    DATA lo_repo            TYPE REF TO lcl_repo_online.
    DATA lv_answer          TYPE c LENGTH 1.

    lv_answer = lcl_popups=>popup_to_confirm(
      titlebar              = iv_title
      text_question         = iv_text
      text_button_1         = 'Continue'
      text_button_2         = 'Cancel'
      default_button        = '2'
      display_cancel_button = abap_false ).                 "#EC NOTEXT

    IF lv_answer <> '1'.
      RETURN.
    ENDIF.

    IF abap_false = lcl_app=>repo_srv( )->is_repo_installed(
        iv_url              = iv_url
        iv_target_package   = iv_package ).

      lcl_sap_package=>create_local( iv_package ).

      lo_repo = lcl_app=>repo_srv( )->new_online(
        iv_url         = iv_url
        iv_branch_name = 'refs/heads/master'
        iv_package     = iv_package ) ##NO_TEXT.

      lo_repo->initialize( ).
      lo_repo->find_remote_dot_abapgit( ).
      lo_repo->status( ). " check for errors
      lo_repo->deserialize( ).
      lcl_services_repo=>toggle_favorite( lo_repo->get_key( ) ).
    ENDIF.

    COMMIT WORK.

  ENDMETHOD.  " do_install.

  METHOD is_installed.

    TRY.
        rv_installed = lcl_app=>repo_srv( )->is_repo_installed( c_abapgit_url ).
        " TODO, alternative checks for presence in the system
      CATCH zcx_abapgit_exception.
        " cannot be installed anyway in this case, e.g. no connection
        rv_installed = abap_false.
    ENDTRY.

  ENDMETHOD.                    "is_installed

  METHOD is_installed_pi.

    TRY.
        rv_installed = lcl_app=>repo_srv( )->is_repo_installed( c_plugins_url ).
        " TODO, alternative checks for presence in the system
      CATCH zcx_abapgit_exception.
        " cannot be installed anyway in this case, e.g. no connection
        rv_installed = abap_false.
    ENDTRY.

  ENDMETHOD.                    "is_installed_pi

ENDCLASS. "lcl_services_abapgit

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_SERVICES_ABAPGIT
*&---------------------------------------------------------------------*

CLASS lcl_services_abapgit DEFINITION FINAL.
  PUBLIC SECTION.

    CONSTANTS c_abapgit_homepage TYPE string
      VALUE 'http://www.abapgit.org' ##NO_TEXT.
    CONSTANTS c_abapgit_wikipage TYPE string
      VALUE 'http://docs.abapgit.org'.
    CONSTANTS c_package_abapgit  TYPE devclass
      VALUE '$ABAPGIT'.
    CONSTANTS c_package_plugins  TYPE devclass
      VALUE '$ABAPGIT_PLUGINS'.
    CONSTANTS c_abapgit_url      TYPE string
      VALUE 'https://github.com/larshp/abapGit.git'.
    CONSTANTS c_plugins_url      TYPE string
      VALUE 'https://github.com/larshp/abapGit-plugins.git'.

    CLASS-METHODS open_abapgit_homepage
      RAISING zcx_abapgit_exception.

    CLASS-METHODS open_abapgit_wikipage
      RAISING zcx_abapgit_exception.

    CLASS-METHODS install_abapgit
      RAISING zcx_abapgit_exception lcx_cancel.

    CLASS-METHODS install_abapgit_pi
      RAISING zcx_abapgit_exception lcx_cancel.

    CLASS-METHODS is_installed
      RETURNING VALUE(rv_installed) TYPE abap_bool.

    CLASS-METHODS is_installed_pi
      RETURNING VALUE(rv_installed) TYPE abap_bool.

  PRIVATE SECTION.

    CLASS-METHODS do_install
      IMPORTING iv_title   TYPE c
                iv_text    TYPE c
                iv_url     TYPE string
                iv_package TYPE devclass
      RAISING   zcx_abapgit_exception.

ENDCLASS. "lcl_services_abapgit

CLASS lcl_services_abapgit IMPLEMENTATION.

  METHOD open_abapgit_homepage.

    cl_gui_frontend_services=>execute(
      EXPORTING document = c_abapgit_homepage
      EXCEPTIONS OTHERS = 1 ).
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'Opening page in external browser failed.' ).
    ENDIF.

  ENDMETHOD.  "open_abapgit_homepage

  METHOD open_abapgit_wikipage.

    cl_gui_frontend_services=>execute(
      EXPORTING document = c_abapgit_wikipage
      EXCEPTIONS OTHERS = 1 ).
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'Opening page in external browser failed.' ).
    ENDIF.

  ENDMETHOD.  "open_abapgit_wikipage

  METHOD install_abapgit.

    CONSTANTS lc_title TYPE c LENGTH 40 VALUE 'Install abapGit'.
    DATA lv_text       TYPE c LENGTH 100.

    IF is_installed( ) = abap_true.
      lv_text = 'Seems like abapGit package is already installed. No changes to be done'.
      lcl_popups=>popup_to_inform(
        titlebar              = lc_title
        text_message          = lv_text ).
      RETURN.
    ENDIF.

    lv_text = |Confirm to install current version of abapGit to package { c_package_abapgit }|.

    do_install( iv_title   = lc_title
                iv_text    = lv_text
                iv_url     = c_abapgit_url
                iv_package = c_package_abapgit ).

  ENDMETHOD.  "install_abapgit

  METHOD install_abapgit_pi.

    CONSTANTS lc_title TYPE c LENGTH 40 VALUE 'Install abapGit plugins'.
    DATA lv_text       TYPE c LENGTH 100.

    IF is_installed_pi( ) = abap_true.
      lv_text = 'Seems like abapGit plugins package is already installed. No changes to be done'.
      lcl_popups=>popup_to_inform(
        titlebar              = lc_title
        text_message          = lv_text ).
      RETURN.
    ENDIF.

    lv_text = |Confirm to install current version abapGit plugins to package {
               c_package_plugins }|.

    do_install( iv_title   = lc_title
                iv_text    = lv_text
                iv_url     = c_plugins_url
                iv_package = c_package_plugins ).

  ENDMETHOD.  "install_abapgit_pi

  METHOD do_install.

    DATA lo_repo            TYPE REF TO lcl_repo_online.
    DATA lv_answer          TYPE c LENGTH 1.

    lv_answer = lcl_popups=>popup_to_confirm(
      titlebar              = iv_title
      text_question         = iv_text
      text_button_1         = 'Continue'
      text_button_2         = 'Cancel'
      default_button        = '2'
      display_cancel_button = abap_false ).                 "#EC NOTEXT

    IF lv_answer <> '1'.
      RETURN.
    ENDIF.

    IF abap_false = lcl_app=>repo_srv( )->is_repo_installed(
        iv_url              = iv_url
        iv_target_package   = iv_package ).

      lcl_sap_package=>create_local( iv_package ).

      lo_repo = lcl_app=>repo_srv( )->new_online(
        iv_url         = iv_url
        iv_branch_name = 'refs/heads/master'
        iv_package     = iv_package ) ##NO_TEXT.

      lo_repo->initialize( ).
      lo_repo->find_remote_dot_abapgit( ).
      lo_repo->status( ). " check for errors
      lo_repo->deserialize( ).
      lcl_services_repo=>toggle_favorite( lo_repo->get_key( ) ).
    ENDIF.

    COMMIT WORK.

  ENDMETHOD.  " do_install.

  METHOD is_installed.

    TRY.
        rv_installed = lcl_app=>repo_srv( )->is_repo_installed( c_abapgit_url ).
        " TODO, alternative checks for presence in the system
      CATCH zcx_abapgit_exception.
        " cannot be installed anyway in this case, e.g. no connection
        rv_installed = abap_false.
    ENDTRY.

  ENDMETHOD.                    "is_installed

  METHOD is_installed_pi.

    TRY.
        rv_installed = lcl_app=>repo_srv( )->is_repo_installed( c_plugins_url ).
        " TODO, alternative checks for presence in the system
      CATCH zcx_abapgit_exception.
        " cannot be installed anyway in this case, e.g. no connection
        rv_installed = abap_false.
    ENDTRY.

  ENDMETHOD.                    "is_installed_pi

ENDCLASS. "lcl_services_abapgit

update link to docs

update link to docs


CLASS ltcl_user DEFINITION
  FOR TESTING
  RISK LEVEL CRITICAL
  DURATION SHORT FINAL.

  PRIVATE SECTION.
    CONSTANTS:
      c_abap_user TYPE sy-uname VALUE 'ABAPGIT_TEST',
      c_git_user  TYPE string VALUE 'abapgit_tester',
      c_repo_key  TYPE zif_abapgit_persistence=>ty_repo-key VALUE '000000000001',
      c_repo_url  TYPE string VALUE 'https://github.com/abapGit/abapGit'.

    DATA:
      mi_user TYPE REF TO zif_abapgit_persist_user.

    METHODS:
      set_get_git_user   FOR TESTING RAISING zcx_abapgit_exception,
      set_get_repo_show  FOR TESTING RAISING zcx_abapgit_exception,
      set_get_settings   FOR TESTING RAISING zcx_abapgit_exception,
      set_get_repo_login FOR TESTING RAISING zcx_abapgit_exception,
      teardown RAISING zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_user IMPLEMENTATION.

  METHOD set_get_git_user.

    DATA: lv_user TYPE string.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    mi_user->set_default_git_user_name( c_git_user ).

    FREE mi_user.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    lv_user = mi_user->get_default_git_user_name( ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_user
      exp = c_git_user ).

  ENDMETHOD.

  METHOD set_get_repo_show.

    DATA: lv_key TYPE zif_abapgit_persistence=>ty_repo-key.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    mi_user->set_repo_show( c_repo_key ).

    FREE mi_user.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    lv_key = mi_user->get_repo_show( ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_key
      exp = c_repo_key ).

  ENDMETHOD.

  METHOD set_get_repo_login.

    DATA: lv_login TYPE string.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    mi_user->set_repo_login( iv_url = c_repo_url
                             iv_login = c_git_user ).

    FREE mi_user.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    lv_login = mi_user->get_repo_login( c_repo_url ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_login
      exp = c_git_user ).

  ENDMETHOD.

  METHOD set_get_settings.

    DATA: ls_settings TYPE zif_abapgit_definitions=>ty_s_user_settings.

    ls_settings-show_default_repo = abap_true.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    mi_user->set_settings( ls_settings ).

    FREE mi_user.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    ls_settings = mi_user->get_settings( ).

    cl_abap_unit_assert=>assert_equals(
      act = ls_settings-show_default_repo
      exp = abap_true ).

  ENDMETHOD.

  METHOD teardown.
    " Delete test user settings
    zcl_abapgit_persistence_db=>get_instance( )->delete(
      iv_type  = zcl_abapgit_persistence_db=>c_type_user
      iv_value = c_abap_user ).
    CALL FUNCTION 'DB_COMMIT'.
  ENDMETHOD.
ENDCLASS.

CLASS ltcl_user DEFINITION
  FOR TESTING
  RISK LEVEL CRITICAL
  DURATION SHORT FINAL.

  PRIVATE SECTION.
    CONSTANTS:
      c_abap_user TYPE sy-uname VALUE 'ABAPGIT_TEST',
      c_git_user  TYPE string VALUE 'abapgit_tester',
      c_repo_url  TYPE string VALUE 'https://github.com/abapGit/abapGit'.

    DATA:
      mi_user TYPE REF TO zif_abapgit_persist_user.

    METHODS:
      set_get_git_user   FOR TESTING RAISING zcx_abapgit_exception,
      set_get_repo_show  FOR TESTING RAISING zcx_abapgit_exception,
      set_get_settings   FOR TESTING RAISING zcx_abapgit_exception,
      set_get_repo_login FOR TESTING RAISING zcx_abapgit_exception,
      teardown RAISING zcx_abapgit_exception.

ENDCLASS.

CLASS ltcl_user IMPLEMENTATION.

  METHOD set_get_git_user.

    DATA: lv_user TYPE string.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    mi_user->set_default_git_user_name( c_git_user ).

    FREE mi_user.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    lv_user = mi_user->get_default_git_user_name( ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_user
      exp = c_git_user ).

  ENDMETHOD.

  METHOD set_get_repo_show.

    DATA: lv_key      TYPE zif_abapgit_persistence=>ty_repo-key,
          lv_repo_key TYPE zif_abapgit_persistence=>ty_repo-key.

    SELECT MIN( value ) FROM (zcl_abapgit_persistence_db=>c_tabname) INTO lv_repo_key
      WHERE type = zcl_abapgit_persistence_db=>c_type_repo.
    IF sy-subrc <> 0.
      RETURN. " can't test
    ENDIF.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    mi_user->set_repo_show( lv_repo_key ).

    FREE mi_user.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    lv_key = mi_user->get_repo_show( ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_key
      exp = lv_repo_key ).

  ENDMETHOD.

  METHOD set_get_repo_login.

    DATA: lv_login TYPE string.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    mi_user->set_repo_login( iv_url = c_repo_url
                             iv_login = c_git_user ).

    FREE mi_user.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    lv_login = mi_user->get_repo_login( c_repo_url ).

    cl_abap_unit_assert=>assert_equals(
      act = lv_login
      exp = c_git_user ).

  ENDMETHOD.

  METHOD set_get_settings.

    DATA: ls_settings TYPE zif_abapgit_definitions=>ty_s_user_settings.

    ls_settings-show_default_repo = abap_true.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    mi_user->set_settings( ls_settings ).

    FREE mi_user.

    mi_user = zcl_abapgit_persistence_user=>get_instance( c_abap_user ).
    ls_settings = mi_user->get_settings( ).

    cl_abap_unit_assert=>assert_equals(
      act = ls_settings-show_default_repo
      exp = abap_true ).

  ENDMETHOD.

  METHOD teardown.
    " Delete test user settings
    zcl_abapgit_persistence_db=>get_instance( )->delete(
      iv_type  = zcl_abapgit_persistence_db=>c_type_user
      iv_value = c_abap_user ).
    CALL FUNCTION 'DB_COMMIT'.
  ENDMETHOD.
ENDCLASS.

Fix unit test for user persistence (#5763)

* Fix unit test for user persistence

Test fails if no repo exists with key `REPO/000000000001`

* Use existing constants

* Update src/persist/zcl_abapgit_persistence_user.clas.testclasses.abap

Co-authored-by: abaplint[bot] <589dee37d0e82f3cabf9dea701e9ec2fd481eb1e@users.noreply.github.com>

Co-authored-by: Lars Hvam <721d1b171982cd84b755f6b25130d2b88cd1f696@hotmail.com>
Co-authored-by: abaplint[bot] <589dee37d0e82f3cabf9dea701e9ec2fd481eb1e@users.noreply.github.com>


CLASS zcl_abapgit_code_inspector DEFINITION
  PUBLIC
  CREATE PROTECTED
  GLOBAL FRIENDS zcl_abapgit_factory .

  PUBLIC SECTION.

    INTERFACES zif_abapgit_code_inspector .

    METHODS constructor
      IMPORTING
        !iv_package TYPE devclass
      RAISING
        zcx_abapgit_exception .
    CLASS-METHODS validate_check_variant
      IMPORTING
        !iv_check_variant_name TYPE sci_chkv
      RAISING
        zcx_abapgit_exception .
  PROTECTED SECTION.
    DATA mv_package TYPE devclass .

    METHODS create_variant
      IMPORTING
        !iv_variant       TYPE sci_chkv
      RETURNING
        VALUE(ro_variant) TYPE REF TO cl_ci_checkvariant
      RAISING
        zcx_abapgit_exception .
    METHODS cleanup
      IMPORTING
        !io_set TYPE REF TO cl_ci_objectset
      RAISING
        zcx_abapgit_exception .
    METHODS skip_object
      IMPORTING
        !is_obj        TYPE scir_objs
      RETURNING
        VALUE(rv_skip) TYPE abap_bool.
  PRIVATE SECTION.

    DATA mv_success TYPE abap_bool .

    TYPES: ty_run_mode TYPE c LENGTH 1.
    CONSTANTS:
      BEGIN OF co_run_mode,
        run_with_popup   TYPE ty_run_mode VALUE 'P',
        run_after_popup  TYPE ty_run_mode VALUE 'A',
        run_via_rfc      TYPE ty_run_mode VALUE 'R',
        run_in_batch     TYPE ty_run_mode VALUE 'B',
        run_loc_parallel TYPE ty_run_mode VALUE 'L',
        run_direct       TYPE ty_run_mode VALUE 'L',
      END OF co_run_mode .
    DATA mo_inspection TYPE REF TO cl_ci_inspection .
    DATA mv_name TYPE sci_objs .
    DATA mv_run_mode TYPE c LENGTH 1 .

    METHODS create_objectset
      RETURNING
        VALUE(ro_set) TYPE REF TO cl_ci_objectset .
    METHODS run_inspection
      IMPORTING
        !io_inspection TYPE REF TO cl_ci_inspection
      RETURNING
        VALUE(rt_list) TYPE scit_alvlist
      RAISING
        zcx_abapgit_exception .
    METHODS create_inspection
      IMPORTING
        io_set               TYPE REF TO cl_ci_objectset
        io_variant           TYPE REF TO cl_ci_checkvariant
      RETURNING
        VALUE(ro_inspection) TYPE REF TO cl_ci_inspection
      RAISING
        zcx_abapgit_exception .

    METHODS decide_run_mode
      RETURNING
        VALUE(rv_run_mode) TYPE ty_run_mode.
ENDCLASS.

CLASS ZCL_ABAPGIT_CODE_INSPECTOR IMPLEMENTATION.

  METHOD cleanup.

    IF mo_inspection IS BOUND.

      mo_inspection->delete(
        EXCEPTIONS
          locked              = 1
          error_in_enqueue    = 2
          not_authorized      = 3
          exceptn_appl_exists = 4
          OTHERS              = 5 ).

      IF sy-subrc <> 0.
        zcx_abapgit_exception=>raise( |Couldn't delete inspection. Subrc = { sy-subrc }| ).
      ENDIF.

    ENDIF.

    io_set->delete(
      EXCEPTIONS
        exists_in_insp   = 1
        locked           = 2
        error_in_enqueue = 3
        not_authorized   = 4
        exists_in_objs   = 5
        OTHERS           = 6 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Couldn't delete objectset. Subrc = { sy-subrc }| ).
    ENDIF.

  ENDMETHOD.

  METHOD constructor.

    IF iv_package IS INITIAL.
      zcx_abapgit_exception=>raise( |Please supply package| ).
    ENDIF.

    mv_package = iv_package.

    " We create the inspection and objectset with dummy names.
    " Because we want to persist them so we can run it in parallel.
    " Both are deleted afterwards.
    mv_name = |{ sy-uname }_{ sy-datum }_{ sy-uzeit }|.
    mv_run_mode = decide_run_mode( ).

  ENDMETHOD.

  METHOD create_inspection.

    cl_ci_inspection=>create(
      EXPORTING
        p_user           = sy-uname
        p_name           = mv_name
      RECEIVING
        p_ref            = ro_inspection
      EXCEPTIONS
        locked           = 1
        error_in_enqueue = 2
        not_authorized   = 3
        OTHERS           = 4 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Failed to create inspection. Subrc = { sy-subrc }| ).
    ENDIF.

    ro_inspection->set(
      p_chkv = io_variant
      p_objs = io_set ).

    ro_inspection->save(
      EXCEPTIONS
        missing_information = 1
        insp_no_name        = 2
        not_enqueued        = 3
        OTHERS              = 4 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Failed to save inspection. Subrc = { sy-subrc }| ).
    ENDIF.

  ENDMETHOD.

  METHOD create_objectset.

    DATA: lt_objs       TYPE scit_objs,
          ls_obj        TYPE scir_objs,
          lt_objs_check TYPE scit_objs,
          ls_item       TYPE zif_abapgit_definitions=>ty_item,
          lt_packages   TYPE zif_abapgit_sap_package=>ty_devclass_tt.

    lt_packages = zcl_abapgit_factory=>get_sap_package( mv_package )->list_subpackages( ).
    INSERT mv_package INTO TABLE lt_packages.

    SELECT object AS objtype obj_name AS objname
      FROM tadir
      INTO CORRESPONDING FIELDS OF TABLE lt_objs
      FOR ALL ENTRIES IN lt_packages
      WHERE devclass = lt_packages-table_line
      AND delflag = abap_false
      AND pgmid = 'R3TR' ##TOO_MANY_ITAB_FIELDS.        "#EC CI_GENBUFF

    LOOP AT lt_objs INTO ls_obj.

      IF skip_object( ls_obj ) = abap_true.
        CONTINUE.
      ENDIF.

      ls_item-obj_type = ls_obj-objtype.
      ls_item-obj_name = ls_obj-objname.

      IF zcl_abapgit_objects=>exists( ls_item ) = abap_false.
        CONTINUE.
      ENDIF.

      INSERT ls_obj INTO TABLE lt_objs_check.

    ENDLOOP.

    ro_set = cl_ci_objectset=>save_from_list(
      p_name    = mv_name
      p_objects = lt_objs_check ).

  ENDMETHOD.

  METHOD create_variant.

    IF iv_variant IS INITIAL.
      zcx_abapgit_exception=>raise( |No check variant supplied.| ).
    ENDIF.

    cl_ci_checkvariant=>get_ref(
      EXPORTING
        p_user                   = ''
        p_name                   = iv_variant
      RECEIVING
        p_ref                    = ro_variant
      EXCEPTIONS
        chkv_not_exists          = 1
        missing_parameter        = 2
        OTHERS                   = 3 ).

    CASE sy-subrc.
      WHEN 1.
        zcx_abapgit_exception=>raise( |Check variant { iv_variant } doesn't exist| ).
      WHEN 2.
        zcx_abapgit_exception=>raise( |Parameter missing for check variant { iv_variant }| ).
    ENDCASE.

  ENDMETHOD.

  METHOD decide_run_mode.

    DATA: lo_settings TYPE REF TO zcl_abapgit_settings.
    lo_settings = zcl_abapgit_persist_settings=>get_instance( )->read( ).

    IF sy-batch = abap_true.
      " We have to disable parallelization in batch because of lock errors.
      rv_run_mode = co_run_mode-run_via_rfc.
    ELSEIF lo_settings->get_parallel_proc_disabled( ) = abap_false.
      rv_run_mode = co_run_mode-run_loc_parallel.
    ELSE.
      rv_run_mode = co_run_mode-run_via_rfc.
    ENDIF.

  ENDMETHOD.

  METHOD run_inspection.

    io_inspection->run(
      EXPORTING
        p_howtorun            = mv_run_mode
      EXCEPTIONS
        invalid_check_version = 1
        OTHERS                = 2 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Code inspector run failed. Subrc = { sy-subrc }| ).
    ENDIF.

    io_inspection->plain_list( IMPORTING p_list = rt_list ).

    SORT rt_list BY objtype objname test code sobjtype sobjname line col.

    DELETE ADJACENT DUPLICATES FROM rt_list.

  ENDMETHOD.

  METHOD skip_object.

    DATA: ls_trdir TYPE trdir.

    CASE is_obj-objtype.
      WHEN 'PROG'.

        SELECT SINGLE *
          INTO ls_trdir
          FROM trdir
          WHERE name = is_obj-objname.

        rv_skip = boolc( ls_trdir-subc = 'I' ). " Include program.

      WHEN OTHERS.
        rv_skip = abap_false.

    ENDCASE.

  ENDMETHOD.

  METHOD validate_check_variant.

    cl_ci_checkvariant=>get_ref(
      EXPORTING
        p_user                   = ''
        p_name                   = iv_check_variant_name
      EXCEPTIONS
        chkv_not_exists          = 1
        missing_parameter        = 2
        OTHERS                   = 3 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |No valid check variant { iv_check_variant_name  }| ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_code_inspector~is_successful.

    rv_success = mv_success.

  ENDMETHOD.

  METHOD zif_abapgit_code_inspector~run.

    DATA: lo_set     TYPE REF TO cl_ci_objectset,
          lo_variant TYPE REF TO cl_ci_checkvariant,
          lx_error   TYPE REF TO zcx_abapgit_exception.

    TRY.
        lo_set = create_objectset( ).

        IF lines( lo_set->iobjlst-objects ) = 0.
          " no objects, nothing to check
          RETURN.
        ENDIF.

        lo_variant = create_variant( iv_variant ).

        mo_inspection = create_inspection(
          io_set     = lo_set
          io_variant = lo_variant ).

        rt_list = run_inspection( mo_inspection ).

        cleanup( lo_set ).

        IF iv_save = abap_true.
          READ TABLE rt_list TRANSPORTING NO FIELDS WITH KEY kind = 'E'.
          mv_success = boolc( sy-subrc <> 0 ).
        ENDIF.

      CATCH zcx_abapgit_exception INTO lx_error.

        " ensure cleanup
        cleanup( lo_set ).
        zcx_abapgit_exception=>raise( iv_text     = lx_error->get_text( )
                                      ix_previous = lx_error ).

    ENDTRY.

  ENDMETHOD.
ENDCLASS.

CLASS zcl_abapgit_code_inspector DEFINITION
  PUBLIC
  CREATE PROTECTED
  GLOBAL FRIENDS zcl_abapgit_factory .

  PUBLIC SECTION.

    INTERFACES zif_abapgit_code_inspector .

    METHODS constructor
      IMPORTING
        !iv_package TYPE devclass
      RAISING
        zcx_abapgit_exception .
    CLASS-METHODS validate_check_variant
      IMPORTING
        !iv_check_variant_name TYPE sci_chkv
      RAISING
        zcx_abapgit_exception .
  PROTECTED SECTION.
    DATA mv_package TYPE devclass .

    METHODS create_variant
      IMPORTING
        !iv_variant       TYPE sci_chkv
      RETURNING
        VALUE(ro_variant) TYPE REF TO cl_ci_checkvariant
      RAISING
        zcx_abapgit_exception .
    METHODS cleanup
      IMPORTING
        !io_set TYPE REF TO cl_ci_objectset
      RAISING
        zcx_abapgit_exception .
    METHODS skip_object
      IMPORTING
        !is_obj        TYPE scir_objs
      RETURNING
        VALUE(rv_skip) TYPE abap_bool.
  PRIVATE SECTION.

    DATA mv_success TYPE abap_bool .

    TYPES: ty_run_mode TYPE c LENGTH 1.
    CONSTANTS:
      BEGIN OF co_run_mode,
        run_with_popup   TYPE ty_run_mode VALUE 'P',
        run_after_popup  TYPE ty_run_mode VALUE 'A',
        run_via_rfc      TYPE ty_run_mode VALUE 'R',
        run_in_batch     TYPE ty_run_mode VALUE 'B',
        run_loc_parallel TYPE ty_run_mode VALUE 'L',
        run_direct       TYPE ty_run_mode VALUE 'L',
      END OF co_run_mode .
    DATA mo_inspection TYPE REF TO cl_ci_inspection .
    DATA mv_name TYPE sci_objs .
    DATA mv_run_mode TYPE c LENGTH 1 .

    METHODS create_objectset
      RETURNING
        VALUE(ro_set) TYPE REF TO cl_ci_objectset .
    METHODS run_inspection
      IMPORTING
        !io_inspection TYPE REF TO cl_ci_inspection
      RETURNING
        VALUE(rt_list) TYPE scit_alvlist
      RAISING
        zcx_abapgit_exception .
    METHODS create_inspection
      IMPORTING
        io_set               TYPE REF TO cl_ci_objectset
        io_variant           TYPE REF TO cl_ci_checkvariant
      RETURNING
        VALUE(ro_inspection) TYPE REF TO cl_ci_inspection
      RAISING
        zcx_abapgit_exception .

    METHODS decide_run_mode
      RETURNING
        VALUE(rv_run_mode) TYPE ty_run_mode.
ENDCLASS.

CLASS ZCL_ABAPGIT_CODE_INSPECTOR IMPLEMENTATION.

  METHOD cleanup.

    IF mo_inspection IS BOUND.

      mo_inspection->delete(
        EXCEPTIONS
          locked              = 1
          error_in_enqueue    = 2
          not_authorized      = 3
          exceptn_appl_exists = 4
          OTHERS              = 5 ).

      IF sy-subrc <> 0.
        zcx_abapgit_exception=>raise( |Couldn't delete inspection. Subrc = { sy-subrc }| ).
      ENDIF.

    ENDIF.

    io_set->delete(
      EXCEPTIONS
        exists_in_insp   = 1
        locked           = 2
        error_in_enqueue = 3
        not_authorized   = 4
        exists_in_objs   = 5
        OTHERS           = 6 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Couldn't delete objectset. Subrc = { sy-subrc }| ).
    ENDIF.

  ENDMETHOD.

  METHOD constructor.

    IF iv_package IS INITIAL.
      zcx_abapgit_exception=>raise( |Please supply package| ).
    ENDIF.

    mv_package = iv_package.

    " We create the inspection and objectset with dummy names.
    " Because we want to persist them so we can run it in parallel.
    " Both are deleted afterwards.
    mv_name = |{ sy-uname }_{ sy-datum }_{ sy-uzeit }|.
    mv_run_mode = decide_run_mode( ).

  ENDMETHOD.

  METHOD create_inspection.

    cl_ci_inspection=>create(
      EXPORTING
        p_user           = sy-uname
        p_name           = mv_name
      RECEIVING
        p_ref            = ro_inspection
      EXCEPTIONS
        locked           = 1
        error_in_enqueue = 2
        not_authorized   = 3
        OTHERS           = 4 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Failed to create inspection. Subrc = { sy-subrc }| ).
    ENDIF.

    ro_inspection->set(
      p_chkv = io_variant
      p_objs = io_set ).

    ro_inspection->save(
      EXCEPTIONS
        missing_information = 1
        insp_no_name        = 2
        not_enqueued        = 3
        OTHERS              = 4 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Failed to save inspection. Subrc = { sy-subrc }| ).
    ENDIF.

  ENDMETHOD.

  METHOD create_objectset.

    DATA: lt_objs       TYPE scit_objs,
          ls_obj        TYPE scir_objs,
          lt_objs_check TYPE scit_objs,
          ls_item       TYPE zif_abapgit_definitions=>ty_item,
          lt_packages   TYPE zif_abapgit_sap_package=>ty_devclass_tt.

    lt_packages = zcl_abapgit_factory=>get_sap_package( mv_package )->list_subpackages( ).
    INSERT mv_package INTO TABLE lt_packages.

    SELECT object AS objtype obj_name AS objname
      FROM tadir
      INTO CORRESPONDING FIELDS OF TABLE lt_objs
      FOR ALL ENTRIES IN lt_packages
      WHERE devclass = lt_packages-table_line
      AND delflag = abap_false
      AND pgmid = 'R3TR' ##TOO_MANY_ITAB_FIELDS.        "#EC CI_GENBUFF

    LOOP AT lt_objs INTO ls_obj.

      IF skip_object( ls_obj ) = abap_true.
        CONTINUE.
      ENDIF.

      ls_item-obj_type = ls_obj-objtype.
      ls_item-obj_name = ls_obj-objname.

      IF zcl_abapgit_objects=>exists( ls_item ) = abap_false.
        CONTINUE.
      ENDIF.

      INSERT ls_obj INTO TABLE lt_objs_check.

    ENDLOOP.

    ro_set = cl_ci_objectset=>save_from_list(
      p_name    = mv_name
      p_objects = lt_objs_check ).

  ENDMETHOD.

  METHOD create_variant.

    IF iv_variant IS INITIAL.
      zcx_abapgit_exception=>raise( |No check variant supplied.| ).
    ENDIF.

    cl_ci_checkvariant=>get_ref(
      EXPORTING
        p_user                   = ''
        p_name                   = iv_variant
      RECEIVING
        p_ref                    = ro_variant
      EXCEPTIONS
        chkv_not_exists          = 1
        missing_parameter        = 2
        OTHERS                   = 3 ).

    CASE sy-subrc.
      WHEN 1.
        zcx_abapgit_exception=>raise( |Check variant { iv_variant } doesn't exist| ).
      WHEN 2.
        zcx_abapgit_exception=>raise( |Parameter missing for check variant { iv_variant }| ).
    ENDCASE.

  ENDMETHOD.

  METHOD decide_run_mode.

    DATA: lo_settings TYPE REF TO zcl_abapgit_settings.
    lo_settings = zcl_abapgit_persist_settings=>get_instance( )->read( ).

    IF sy-batch = abap_true.
      " We have to disable parallelization in batch because of lock errors.
      rv_run_mode = co_run_mode-run_via_rfc.
    ELSEIF lo_settings->get_parallel_proc_disabled( ) = abap_false.
      rv_run_mode = co_run_mode-run_loc_parallel.
    ELSE.
      rv_run_mode = co_run_mode-run_via_rfc.
    ENDIF.

  ENDMETHOD.

  METHOD run_inspection.

    io_inspection->run(
      EXPORTING
        p_howtorun            = mv_run_mode
      EXCEPTIONS
        invalid_check_version = 1
        OTHERS                = 2 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |Code inspector run failed. Subrc = { sy-subrc }| ).
    ENDIF.

    io_inspection->plain_list( IMPORTING p_list = rt_list ).

    SORT rt_list BY objtype objname test code sobjtype sobjname line col.

    DELETE ADJACENT DUPLICATES FROM rt_list.

  ENDMETHOD.

  METHOD skip_object.

    DATA ls_program_type TYPE subc.

    CASE is_obj-objtype.
      WHEN 'PROG'.

        SELECT SINGLE subc
          INTO ls_program_type
          FROM trdir
          WHERE name = is_obj-objname.

        rv_skip = boolc( ls_program_type = 'I' ). " Include program.

      WHEN OTHERS.
        rv_skip = abap_false.

    ENDCASE.

  ENDMETHOD.

  METHOD validate_check_variant.

    cl_ci_checkvariant=>get_ref(
      EXPORTING
        p_user                   = ''
        p_name                   = iv_check_variant_name
      EXCEPTIONS
        chkv_not_exists          = 1
        missing_parameter        = 2
        OTHERS                   = 3 ).

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |No valid check variant { iv_check_variant_name  }| ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_code_inspector~is_successful.

    rv_success = mv_success.

  ENDMETHOD.

  METHOD zif_abapgit_code_inspector~run.

    DATA: lo_set     TYPE REF TO cl_ci_objectset,
          lo_variant TYPE REF TO cl_ci_checkvariant,
          lx_error   TYPE REF TO zcx_abapgit_exception.

    TRY.
        lo_set = create_objectset( ).

        IF lines( lo_set->iobjlst-objects ) = 0.
          " no objects, nothing to check
          RETURN.
        ENDIF.

        lo_variant = create_variant( iv_variant ).

        mo_inspection = create_inspection(
          io_set     = lo_set
          io_variant = lo_variant ).

        rt_list = run_inspection( mo_inspection ).

        cleanup( lo_set ).

        IF iv_save = abap_true.
          READ TABLE rt_list TRANSPORTING NO FIELDS WITH KEY kind = 'E'.
          mv_success = boolc( sy-subrc <> 0 ).
        ENDIF.

      CATCH zcx_abapgit_exception INTO lx_error.

        " ensure cleanup
        cleanup( lo_set ).
        zcx_abapgit_exception=>raise( iv_text     = lx_error->get_text( )
                                      ix_previous = lx_error ).

    ENDTRY.

  ENDMETHOD.
ENDCLASS.

Replace SELECT * with field list (#4675)


CLASS zcl_abapgit_repo_online DEFINITION
  PUBLIC
  INHERITING FROM zcl_abapgit_repo
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    METHODS constructor
      IMPORTING
        !is_data TYPE zif_abapgit_persistence=>ty_repo
      RAISING
        zcx_abapgit_exception .
    METHODS get_url
      RETURNING
        VALUE(rv_url) TYPE zif_abapgit_persistence=>ty_repo-url .
    METHODS get_branch_name
      RETURNING
        VALUE(rv_name) TYPE zif_abapgit_persistence=>ty_repo-branch_name .
    METHODS get_head_branch_name
      RETURNING
        VALUE(rv_name) TYPE zif_abapgit_persistence=>ty_repo-head_branch .
    METHODS set_url
      IMPORTING
        !iv_url TYPE zif_abapgit_persistence=>ty_repo-url
      RAISING
        zcx_abapgit_exception .
    METHODS set_branch_name
      IMPORTING
        !iv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name
      RAISING
        zcx_abapgit_exception .
    METHODS set_new_remote
      IMPORTING
        !iv_url         TYPE zif_abapgit_persistence=>ty_repo-url
        !iv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name
      RAISING
        zcx_abapgit_exception .
    METHODS get_sha1_local
      RETURNING
        VALUE(rv_sha1) TYPE zif_abapgit_persistence=>ty_repo-sha1 .
    METHODS get_sha1_remote
      RETURNING
        VALUE(rv_sha1) TYPE zif_abapgit_persistence=>ty_repo-sha1
      RAISING
        zcx_abapgit_exception .
    METHODS get_objects
      RETURNING
        VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt
      RAISING
        zcx_abapgit_exception .
    METHODS status
      IMPORTING
        !io_log           TYPE REF TO zcl_abapgit_log OPTIONAL
      RETURNING
        VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt
      RAISING
        zcx_abapgit_exception .
    METHODS reset_status .
    METHODS set_objects
      IMPORTING
        !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt
      RAISING
        zcx_abapgit_exception .
    METHODS initialize
      RAISING
        zcx_abapgit_exception .
    METHODS push
      IMPORTING
        !is_comment TYPE zif_abapgit_definitions=>ty_comment
        !io_stage   TYPE REF TO zcl_abapgit_stage
      RAISING
        zcx_abapgit_exception .
    METHODS get_unnecessary_local_objs
      RETURNING
        VALUE(rt_unnecessary_local_objects) TYPE zif_abapgit_definitions=>ty_tadir_tt
      RAISING
        zcx_abapgit_exception .

    METHODS deserialize
        REDEFINITION .
    METHODS get_files_remote
        REDEFINITION .
    METHODS rebuild_local_checksums
        REDEFINITION .
    METHODS refresh
        REDEFINITION .
  PRIVATE SECTION.
    DATA:
      mt_objects     TYPE zif_abapgit_definitions=>ty_objects_tt,
      mv_branch      TYPE zif_abapgit_definitions=>ty_sha1,
      mv_initialized TYPE abap_bool,
      mo_branches    TYPE REF TO zcl_abapgit_git_branch_list,
      mt_status      TYPE zif_abapgit_definitions=>ty_results_tt.

    METHODS:
      handle_stage_ignore
        IMPORTING io_stage TYPE REF TO zcl_abapgit_stage
        RAISING   zcx_abapgit_exception,
      actualize_head_branch
        RAISING zcx_abapgit_exception,
      delete_initial_online_repo
        IMPORTING iv_commit TYPE flag
        RAISING   zcx_abapgit_exception.

ENDCLASS.

CLASS zcl_abapgit_repo_online IMPLEMENTATION.

  METHOD actualize_head_branch.
    DATA lv_branch_name TYPE string.
    lv_branch_name = mo_branches->get_head( )-name.

    IF lv_branch_name <> ms_data-head_branch.
      set( iv_head_branch = lv_branch_name ).
    ENDIF.

  ENDMETHOD.                    "actualize_head_branch

  METHOD constructor.

    super->constructor( is_data ).

    mv_initialized = abap_false.

  ENDMETHOD.                    "constructor

  METHOD delete_initial_online_repo.

    IF me->is_offline( ) = abap_false AND me->get_sha1_local( ) IS INITIAL.

      zcl_abapgit_repo_srv=>get_instance( )->delete( me ).

      IF iv_commit = abap_true.
        COMMIT WORK.
      ENDIF.

    ENDIF.

  ENDMETHOD.  " delete_initial_online_repo

  METHOD deserialize.

    initialize( ).

    super->deserialize( is_checks ).

    set( iv_sha1 = mv_branch ).

    reset_status( ).

    COMMIT WORK AND WAIT.

  ENDMETHOD.                    "deserialize

  METHOD get_branch_name.
    rv_name = ms_data-branch_name.
  ENDMETHOD.                    "get_branch_name

  METHOD get_files_remote.
    initialize( ).

    rt_files = mt_remote.
  ENDMETHOD.                    "get_files

  METHOD get_head_branch_name.
    rv_name = ms_data-head_branch.
  ENDMETHOD.                    "get_head_branch_name

  METHOD get_objects.
    initialize( ).

    rt_objects = mt_objects.
  ENDMETHOD.                    "get_objects

  METHOD get_sha1_local.
    rv_sha1 = ms_data-sha1.
  ENDMETHOD.                    "get_sha1_local

  METHOD get_sha1_remote.
    initialize( ).

    rv_sha1 = mv_branch.
  ENDMETHOD.                    "get_sha1_remote

  METHOD get_unnecessary_local_objs.

    DATA: lt_tadir        TYPE zif_abapgit_definitions=>ty_tadir_tt,
          lt_tadir_unique TYPE HASHED TABLE OF zif_abapgit_definitions=>ty_tadir
                               WITH UNIQUE KEY pgmid object obj_name,
          lt_local        TYPE zif_abapgit_definitions=>ty_files_item_tt,
          lt_remote       TYPE zif_abapgit_definitions=>ty_files_tt,
          lt_status       TYPE zif_abapgit_definitions=>ty_results_tt,
          lv_package      TYPE zif_abapgit_persistence=>ty_repo-package.

    FIELD-SYMBOLS: <ls_status> TYPE zif_abapgit_definitions=>ty_result,
                   <ls_tadir>  TYPE zif_abapgit_definitions=>ty_tadir.

    " delete objects which are added locally but are not in remote repo
    lt_local  = get_files_local( ).
    lt_remote = get_files_remote( ).
    lt_status = status( ).

    lv_package = me->get_package( ).
    lt_tadir = zcl_abapgit_tadir=>read( lv_package ).
    SORT lt_tadir BY pgmid ASCENDING object ASCENDING obj_name ASCENDING devclass ASCENDING.

    LOOP AT lt_status ASSIGNING <ls_status>
                      WHERE lstate = zif_abapgit_definitions=>gc_state-added.

      READ TABLE lt_tadir ASSIGNING <ls_tadir>
                          WITH KEY pgmid    = 'R3TR'
                                   object   = <ls_status>-obj_type
                                   obj_name = <ls_status>-obj_name
                                   devclass = <ls_status>-package
                          BINARY SEARCH.
      IF sy-subrc <> 0.
* skip objects that does not exist locally
        CONTINUE.
      ENDIF.

      INSERT <ls_tadir> INTO TABLE lt_tadir_unique.

    ENDLOOP.

    rt_unnecessary_local_objects = lt_tadir_unique.

  ENDMETHOD.

  METHOD get_url.
    rv_url = ms_data-url.
  ENDMETHOD.                    "get_url

  METHOD handle_stage_ignore.

    DATA: lv_add         TYPE abap_bool,
          lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit,
          lt_stage       TYPE zcl_abapgit_stage=>ty_stage_tt.

    FIELD-SYMBOLS: <ls_stage> LIKE LINE OF lt_stage.

    lo_dot_abapgit = get_dot_abapgit( ).
    lt_stage = io_stage->get_all( ).
    LOOP AT lt_stage ASSIGNING <ls_stage> WHERE method = zcl_abapgit_stage=>c_method-ignore.

      lo_dot_abapgit->add_ignore(
        iv_path     = <ls_stage>-file-path
        iv_filename = <ls_stage>-file-filename ).

      " remove it from the staging object, as the action is handled here
      io_stage->reset( iv_path     = <ls_stage>-file-path
                       iv_filename = <ls_stage>-file-filename ).

      lv_add = abap_true.

    ENDLOOP.

    IF lv_add = abap_true.
      io_stage->add(
        iv_path     = zif_abapgit_definitions=>gc_root_dir
        iv_filename = zif_abapgit_definitions=>gc_dot_abapgit
        iv_data     = lo_dot_abapgit->serialize( ) ).

      set_dot_abapgit( lo_dot_abapgit ).
    ENDIF.

  ENDMETHOD.

  METHOD initialize.
    IF mv_initialized = abap_false.
      refresh( ).
    ENDIF.
  ENDMETHOD.

  METHOD push.

    DATA: lv_branch        TYPE zif_abapgit_definitions=>ty_sha1,
          lt_updated_files TYPE zif_abapgit_definitions=>ty_file_signatures_tt,
          lv_text          TYPE string.

    IF ms_data-branch_name CP 'refs/tags*'.
      lv_text = |You're working on a tag. Currently it's not |
             && |possible to push on tags. Consider creating a branch instead|.
      zcx_abapgit_exception=>raise( lv_text ).
    ENDIF.

    handle_stage_ignore( io_stage ).

    zcl_abapgit_git_porcelain=>push( EXPORTING is_comment       = is_comment
                                       io_repo          = me
                                       io_stage         = io_stage
                             IMPORTING ev_branch        = lv_branch
                                       et_updated_files = lt_updated_files ).

    IF io_stage->get_branch_sha1( ) = get_sha1_local( ).
* pushing to the branch currently represented by this repository object
      mv_branch = lv_branch.
      set( iv_sha1 = lv_branch ).
    ELSE.
      refresh( ).
    ENDIF.

    update_local_checksums( lt_updated_files ).

    IF zcl_abapgit_stage_logic=>count( me ) = 0.
      set( iv_sha1 = lv_branch ).
    ENDIF.

  ENDMETHOD.                    "push

  METHOD rebuild_local_checksums. "REMOTE

    DATA: lt_remote       TYPE zif_abapgit_definitions=>ty_files_tt,
          lt_local        TYPE zif_abapgit_definitions=>ty_files_item_tt,
          ls_last_item    TYPE zif_abapgit_definitions=>ty_item,
          lv_branch_equal TYPE abap_bool,
          lt_checksums    TYPE zif_abapgit_persistence=>ty_local_checksum_tt.

    FIELD-SYMBOLS: <ls_checksum> LIKE LINE OF lt_checksums,
                   <ls_file_sig> LIKE LINE OF <ls_checksum>-files,
                   <ls_remote>   LIKE LINE OF lt_remote,
                   <ls_local>    LIKE LINE OF lt_local.

    lt_remote       = get_files_remote( ).
    lt_local        = get_files_local( ).
    lv_branch_equal = boolc( get_sha1_remote( ) = get_sha1_local( ) ).

    DELETE lt_local " Remove non-code related files except .abapgit
      WHERE item IS INITIAL
      AND NOT ( file-path     = zif_abapgit_definitions=>gc_root_dir
      AND       file-filename = zif_abapgit_definitions=>gc_dot_abapgit ).

    SORT lt_local BY item.
    SORT lt_remote BY path filename.

    LOOP AT lt_local ASSIGNING <ls_local>.
      IF ls_last_item <> <ls_local>-item OR sy-tabix = 1. " First or New item reached ?
        APPEND INITIAL LINE TO lt_checksums ASSIGNING <ls_checksum>.
        <ls_checksum>-item = <ls_local>-item.
        ls_last_item       = <ls_local>-item.
      ENDIF.

      READ TABLE lt_remote ASSIGNING <ls_remote>
        WITH KEY path = <ls_local>-file-path filename = <ls_local>-file-filename
        BINARY SEARCH.
      CHECK sy-subrc = 0.  " Ignore new ones

      APPEND INITIAL LINE TO <ls_checksum>-files ASSIGNING <ls_file_sig>.
      MOVE-CORRESPONDING <ls_local>-file TO <ls_file_sig>.

      " If hashes are equal -> local sha1 is OK
      " Else if R-branch is ahead  -> assume changes were remote, state - local sha1
      "      Else (branches equal) -> assume changes were local, state - remote sha1
      IF <ls_local>-file-sha1 <> <ls_remote>-sha1 AND lv_branch_equal = abap_true.
        <ls_file_sig>-sha1 = <ls_remote>-sha1.
      ENDIF.
    ENDLOOP.

    set( it_checksums = lt_checksums ).
    reset_status( ).

  ENDMETHOD.  " rebuild_local_checksums.

  METHOD refresh.

    DATA: lo_progress  TYPE REF TO zcl_abapgit_progress,
          lx_exception TYPE REF TO zcx_abapgit_exception.

    super->refresh( iv_drop_cache ).
    reset_status( ).

    CREATE OBJECT lo_progress
      EXPORTING
        iv_total = 1.

    lo_progress->show( iv_current = 1
                       iv_text    = 'Fetch remote files' ) ##NO_TEXT.

    TRY.
        zcl_abapgit_git_porcelain=>pull(
          EXPORTING
            io_repo    = me
          IMPORTING
            et_files   = mt_remote
            et_objects = mt_objects
            ev_branch  = mv_branch ).

      CATCH zcx_abapgit_exception INTO lx_exception.

        delete_initial_online_repo( abap_true ).

        RAISE EXCEPTION lx_exception.

    ENDTRY.

    mo_branches = zcl_abapgit_git_transport=>branches( get_url( ) ).
    actualize_head_branch( ).

    mv_initialized = abap_true.

  ENDMETHOD.                    "refresh

  METHOD reset_status.
    CLEAR mt_status.
  ENDMETHOD.  " reset_status.

  METHOD set_branch_name.

    IF ms_data-local_settings-write_protected = abap_true.
      zcx_abapgit_exception=>raise( 'Cannot switch branch. Local code is write-protected by repo config' ).
    ENDIF.

    mv_initialized = abap_false.
    set( iv_branch_name = iv_branch_name ).

  ENDMETHOD.

  METHOD set_new_remote.

    IF ms_data-local_settings-write_protected = abap_true.
      zcx_abapgit_exception=>raise( 'Cannot change remote. Local code is write-protected by repo config' ).
    ENDIF.

    mv_initialized = abap_false.
    set( iv_url         = iv_url
         iv_branch_name = iv_branch_name
         iv_head_branch = ''
         iv_sha1        = '' ).

  ENDMETHOD.  "set_new_remote

  METHOD set_objects.
    mt_objects = it_objects.
  ENDMETHOD.

  METHOD set_url.

    IF ms_data-local_settings-write_protected = abap_true.
      zcx_abapgit_exception=>raise( 'Cannot change URL. Local code is write-protected by repo config' ).
    ENDIF.

    mv_initialized = abap_false.
    set( iv_url = iv_url ).

  ENDMETHOD.

  METHOD status.

    initialize( ).

    IF lines( mt_status ) = 0.
      mt_status = zcl_abapgit_file_status=>status( io_repo = me
                                                   io_log  = io_log ).
    ENDIF.
    rt_results = mt_status.

  ENDMETHOD.                    "status
ENDCLASS.

CLASS zcl_abapgit_repo_online DEFINITION
  PUBLIC
  INHERITING FROM zcl_abapgit_repo
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    METHODS constructor
      IMPORTING
        !is_data TYPE zif_abapgit_persistence=>ty_repo
      RAISING
        zcx_abapgit_exception .
    METHODS get_url
      RETURNING
        VALUE(rv_url) TYPE zif_abapgit_persistence=>ty_repo-url .
    METHODS get_branch_name
      RETURNING
        VALUE(rv_name) TYPE zif_abapgit_persistence=>ty_repo-branch_name .
    METHODS get_head_branch_name
      RETURNING
        VALUE(rv_name) TYPE zif_abapgit_persistence=>ty_repo-head_branch .
    METHODS set_url
      IMPORTING
        !iv_url TYPE zif_abapgit_persistence=>ty_repo-url
      RAISING
        zcx_abapgit_exception .
    METHODS set_branch_name
      IMPORTING
        !iv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name
      RAISING
        zcx_abapgit_exception .
    METHODS set_new_remote
      IMPORTING
        !iv_url         TYPE zif_abapgit_persistence=>ty_repo-url
        !iv_branch_name TYPE zif_abapgit_persistence=>ty_repo-branch_name
      RAISING
        zcx_abapgit_exception .
    METHODS get_sha1_local
      RETURNING
        VALUE(rv_sha1) TYPE zif_abapgit_persistence=>ty_repo-sha1 .
    METHODS get_sha1_remote
      RETURNING
        VALUE(rv_sha1) TYPE zif_abapgit_persistence=>ty_repo-sha1
      RAISING
        zcx_abapgit_exception .
    METHODS get_objects
      RETURNING
        VALUE(rt_objects) TYPE zif_abapgit_definitions=>ty_objects_tt
      RAISING
        zcx_abapgit_exception .
    METHODS status
      IMPORTING
        !io_log           TYPE REF TO zcl_abapgit_log OPTIONAL
      RETURNING
        VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt
      RAISING
        zcx_abapgit_exception .
    METHODS reset_status .
    METHODS set_objects
      IMPORTING
        !it_objects TYPE zif_abapgit_definitions=>ty_objects_tt
      RAISING
        zcx_abapgit_exception .
    METHODS initialize
      RAISING
        zcx_abapgit_exception .
    METHODS push
      IMPORTING
        !is_comment TYPE zif_abapgit_definitions=>ty_comment
        !io_stage   TYPE REF TO zcl_abapgit_stage
      RAISING
        zcx_abapgit_exception .
    METHODS get_unnecessary_local_objs
      RETURNING
        VALUE(rt_unnecessary_local_objects) TYPE zif_abapgit_definitions=>ty_tadir_tt
      RAISING
        zcx_abapgit_exception .

    METHODS deserialize
        REDEFINITION .
    METHODS get_files_remote
        REDEFINITION .
    METHODS rebuild_local_checksums
        REDEFINITION .
    METHODS refresh
        REDEFINITION .
  PRIVATE SECTION.
    DATA:
      mt_objects     TYPE zif_abapgit_definitions=>ty_objects_tt,
      mv_branch      TYPE zif_abapgit_definitions=>ty_sha1,
      mv_initialized TYPE abap_bool,
      mo_branches    TYPE REF TO zcl_abapgit_git_branch_list,
      mt_status      TYPE zif_abapgit_definitions=>ty_results_tt.

    METHODS:
      handle_stage_ignore
        IMPORTING io_stage TYPE REF TO zcl_abapgit_stage
        RAISING   zcx_abapgit_exception,
      actualize_head_branch
        RAISING zcx_abapgit_exception,
      delete_initial_online_repo
        IMPORTING iv_commit TYPE flag
        RAISING   zcx_abapgit_exception.

ENDCLASS.

CLASS zcl_abapgit_repo_online IMPLEMENTATION.

  METHOD actualize_head_branch.
    DATA lv_branch_name TYPE string.
    lv_branch_name = mo_branches->get_head( )-name.

    IF lv_branch_name <> ms_data-head_branch.
      set( iv_head_branch = lv_branch_name ).
    ENDIF.

  ENDMETHOD.                    "actualize_head_branch

  METHOD constructor.

    super->constructor( is_data ).

    mv_initialized = abap_false.

  ENDMETHOD.                    "constructor

  METHOD delete_initial_online_repo.

    IF me->is_offline( ) = abap_false AND me->get_sha1_local( ) IS INITIAL.

      zcl_abapgit_repo_srv=>get_instance( )->delete( me ).

      IF iv_commit = abap_true.
        COMMIT WORK.
      ENDIF.

    ENDIF.

  ENDMETHOD.  " delete_initial_online_repo

  METHOD deserialize.

    initialize( ).

    super->deserialize( is_checks ).

    set( iv_sha1 = mv_branch ).

    reset_status( ).

    COMMIT WORK AND WAIT.

  ENDMETHOD.                    "deserialize

  METHOD get_branch_name.
    rv_name = ms_data-branch_name.
  ENDMETHOD.                    "get_branch_name

  METHOD get_files_remote.
    initialize( ).

    rt_files = mt_remote.
  ENDMETHOD.                    "get_files

  METHOD get_head_branch_name.
    rv_name = ms_data-head_branch.
  ENDMETHOD.                    "get_head_branch_name

  METHOD get_objects.
    initialize( ).

    rt_objects = mt_objects.
  ENDMETHOD.                    "get_objects

  METHOD get_sha1_local.
    rv_sha1 = ms_data-sha1.
  ENDMETHOD.                    "get_sha1_local

  METHOD get_sha1_remote.
    initialize( ).

    rv_sha1 = mv_branch.
  ENDMETHOD.                    "get_sha1_remote

  METHOD get_unnecessary_local_objs.

    DATA: lt_tadir        TYPE zif_abapgit_definitions=>ty_tadir_tt,
          lt_tadir_unique TYPE HASHED TABLE OF zif_abapgit_definitions=>ty_tadir
                               WITH UNIQUE KEY pgmid object obj_name,
          lt_local        TYPE zif_abapgit_definitions=>ty_files_item_tt,
          lt_remote       TYPE zif_abapgit_definitions=>ty_files_tt,
          lt_status       TYPE zif_abapgit_definitions=>ty_results_tt,
          lv_package      TYPE zif_abapgit_persistence=>ty_repo-package.

    FIELD-SYMBOLS: <ls_status> TYPE zif_abapgit_definitions=>ty_result,
                   <ls_tadir>  TYPE zif_abapgit_definitions=>ty_tadir.

    " delete objects which are added locally but are not in remote repo
    lt_local  = get_files_local( ).
    lt_remote = get_files_remote( ).
    lt_status = status( ).

    lv_package = me->get_package( ).
    lt_tadir = zcl_abapgit_tadir=>read( lv_package ).
    SORT lt_tadir BY pgmid ASCENDING object ASCENDING obj_name ASCENDING devclass ASCENDING.

    LOOP AT lt_status ASSIGNING <ls_status>
                      WHERE lstate = zif_abapgit_definitions=>gc_state-added.

      READ TABLE lt_tadir ASSIGNING <ls_tadir>
                          WITH KEY pgmid    = 'R3TR'
                                   object   = <ls_status>-obj_type
                                   obj_name = <ls_status>-obj_name
                                   devclass = <ls_status>-package
                          BINARY SEARCH.
      IF sy-subrc <> 0.
* skip objects that does not exist locally
        CONTINUE.
      ENDIF.

      INSERT <ls_tadir> INTO TABLE lt_tadir_unique.

    ENDLOOP.

    rt_unnecessary_local_objects = lt_tadir_unique.

  ENDMETHOD.

  METHOD get_url.
    rv_url = ms_data-url.
  ENDMETHOD.                    "get_url

  METHOD handle_stage_ignore.

    DATA: lv_add         TYPE abap_bool,
          lo_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit,
          lt_stage       TYPE zcl_abapgit_stage=>ty_stage_tt.

    FIELD-SYMBOLS: <ls_stage> LIKE LINE OF lt_stage.

    lo_dot_abapgit = get_dot_abapgit( ).
    lt_stage = io_stage->get_all( ).
    LOOP AT lt_stage ASSIGNING <ls_stage> WHERE method = zcl_abapgit_stage=>c_method-ignore.

      lo_dot_abapgit->add_ignore(
        iv_path     = <ls_stage>-file-path
        iv_filename = <ls_stage>-file-filename ).

      " remove it from the staging object, as the action is handled here
      io_stage->reset( iv_path     = <ls_stage>-file-path
                       iv_filename = <ls_stage>-file-filename ).

      lv_add = abap_true.

    ENDLOOP.

    IF lv_add = abap_true.
      io_stage->add(
        iv_path     = zif_abapgit_definitions=>gc_root_dir
        iv_filename = zif_abapgit_definitions=>gc_dot_abapgit
        iv_data     = lo_dot_abapgit->serialize( ) ).

      set_dot_abapgit( lo_dot_abapgit ).
    ENDIF.

  ENDMETHOD.

  METHOD initialize.
    IF mv_initialized = abap_false.
      refresh( ).
    ENDIF.
  ENDMETHOD.

  METHOD push.

    DATA: lv_branch        TYPE zif_abapgit_definitions=>ty_sha1,
          lt_updated_files TYPE zif_abapgit_definitions=>ty_file_signatures_tt,
          lv_text          TYPE string.

    IF ms_data-branch_name CP 'refs/tags*'.
      lv_text = |You're working on a tag. Currently it's not |
             && |possible to push on tags. Consider creating a branch instead|.
      zcx_abapgit_exception=>raise( lv_text ).
    ENDIF.

    handle_stage_ignore( io_stage ).

    zcl_abapgit_git_porcelain=>push( EXPORTING is_comment       = is_comment
                                       io_repo          = me
                                       io_stage         = io_stage
                             IMPORTING ev_branch        = lv_branch
                                       et_updated_files = lt_updated_files ).

    IF io_stage->get_branch_sha1( ) = get_sha1_local( ).
* pushing to the branch currently represented by this repository object
      mv_branch = lv_branch.
      set( iv_sha1 = lv_branch ).
    ELSE.
      refresh( ).
    ENDIF.

    update_local_checksums( lt_updated_files ).

    IF zcl_abapgit_stage_logic=>count( me ) = 0.
      set( iv_sha1 = lv_branch ).
    ENDIF.

  ENDMETHOD.                    "push

  METHOD rebuild_local_checksums. "REMOTE

    DATA: lt_remote       TYPE zif_abapgit_definitions=>ty_files_tt,
          lt_local        TYPE zif_abapgit_definitions=>ty_files_item_tt,
          ls_last_item    TYPE zif_abapgit_definitions=>ty_item,
          lv_branch_equal TYPE abap_bool,
          lt_checksums    TYPE zif_abapgit_persistence=>ty_local_checksum_tt.

    FIELD-SYMBOLS: <ls_checksum> LIKE LINE OF lt_checksums,
                   <ls_file_sig> LIKE LINE OF <ls_checksum>-files,
                   <ls_remote>   LIKE LINE OF lt_remote,
                   <ls_local>    LIKE LINE OF lt_local.

    lt_remote       = get_files_remote( ).
    lt_local        = get_files_local( ).
    lv_branch_equal = boolc( get_sha1_remote( ) = get_sha1_local( ) ).

    DELETE lt_local " Remove non-code related files except .abapgit
      WHERE item IS INITIAL
      AND NOT ( file-path     = zif_abapgit_definitions=>gc_root_dir
      AND       file-filename = zif_abapgit_definitions=>gc_dot_abapgit ).

    SORT lt_local BY item.
    SORT lt_remote BY path filename.

    LOOP AT lt_local ASSIGNING <ls_local>.
      IF ls_last_item <> <ls_local>-item OR sy-tabix = 1. " First or New item reached ?
        APPEND INITIAL LINE TO lt_checksums ASSIGNING <ls_checksum>.
        <ls_checksum>-item = <ls_local>-item.
        ls_last_item       = <ls_local>-item.
      ENDIF.

      READ TABLE lt_remote ASSIGNING <ls_remote>
        WITH KEY path = <ls_local>-file-path filename = <ls_local>-file-filename
        BINARY SEARCH.
      CHECK sy-subrc = 0.  " Ignore new ones

      APPEND INITIAL LINE TO <ls_checksum>-files ASSIGNING <ls_file_sig>.
      MOVE-CORRESPONDING <ls_local>-file TO <ls_file_sig>.

      " If hashes are equal -> local sha1 is OK
      " Else if R-branch is ahead  -> assume changes were remote, state - local sha1
      "      Else (branches equal) -> assume changes were local, state - remote sha1
      IF <ls_local>-file-sha1 <> <ls_remote>-sha1 AND lv_branch_equal = abap_true.
        <ls_file_sig>-sha1 = <ls_remote>-sha1.
      ENDIF.
    ENDLOOP.

    set( it_checksums = lt_checksums ).
    reset_status( ).

  ENDMETHOD.  " rebuild_local_checksums.

  METHOD refresh.

    DATA: lo_progress  TYPE REF TO zcl_abapgit_progress,
          lx_exception TYPE REF TO zcx_abapgit_exception.

    super->refresh( iv_drop_cache ).
    reset_status( ).

    CREATE OBJECT lo_progress
      EXPORTING
        iv_total = 1.

    lo_progress->show( iv_current = 1
                       iv_text    = 'Fetch remote files' ) ##NO_TEXT.

    TRY.
        zcl_abapgit_git_porcelain=>pull(
          EXPORTING
            io_repo    = me
          IMPORTING
            et_files   = mt_remote
            et_objects = mt_objects
            ev_branch  = mv_branch ).

      CATCH zcx_abapgit_exception INTO lx_exception.

        delete_initial_online_repo( abap_true ).

        RAISE EXCEPTION lx_exception.

    ENDTRY.

    mo_branches = zcl_abapgit_git_transport=>branches( get_url( ) ).
    actualize_head_branch( ).

    mv_initialized = abap_true.

  ENDMETHOD.                    "refresh

  METHOD reset_status.
    CLEAR mt_status.
  ENDMETHOD.  " reset_status.

  METHOD set_branch_name.

    IF ms_data-local_settings-write_protected = abap_true.
      zcx_abapgit_exception=>raise( 'Cannot switch branch. Local code is write-protected by repo config' ).
    ENDIF.

    mv_initialized = abap_false.
    set( iv_branch_name = iv_branch_name ).

  ENDMETHOD.

  METHOD set_new_remote.

    IF ms_data-local_settings-write_protected = abap_true.
      zcx_abapgit_exception=>raise( 'Cannot change remote. Local code is write-protected by repo config' ).
    ENDIF.

    mv_initialized = abap_false.
    set( iv_url         = iv_url
         iv_branch_name = iv_branch_name
         iv_head_branch = ''
         iv_sha1        = '' ).

    " If the SHA1 is empty, it's not possible to create tags or branches.
    " Therefore we update the local SHA1 with the new remote SHA1
    set( iv_sha1 = get_sha1_remote( ) ).

  ENDMETHOD.  "set_new_remote

  METHOD set_objects.
    mt_objects = it_objects.
  ENDMETHOD.

  METHOD set_url.

    IF ms_data-local_settings-write_protected = abap_true.
      zcx_abapgit_exception=>raise( 'Cannot change URL. Local code is write-protected by repo config' ).
    ENDIF.

    mv_initialized = abap_false.
    set( iv_url = iv_url ).

  ENDMETHOD.

  METHOD status.

    initialize( ).

    IF lines( mt_status ) = 0.
      mt_status = zcl_abapgit_file_status=>status( io_repo = me
                                                   io_log  = io_log ).
    ENDIF.
    rt_results = mt_status.

  ENDMETHOD.                    "status
ENDCLASS.

set new remote: supply remote SHA1

set new remote: supply remote SHA1


interface ZIF_MOCKUP_LOADER_CONSTANTS
  public .

  " codepages
  constants encoding_utf8  type abap_encoding value '4110'. "#EC NOTEXT
  constants encoding_utf16 type abap_encoding value '4103'. "#EC NOTEXT
  constants version        type string value 'v2.1.6'.      "#EC NOTEXT
endinterface.

interface ZIF_MOCKUP_LOADER_CONSTANTS
  public .

  " codepages
  constants encoding_utf8  type abap_encoding value '4110'. "#EC NOTEXT
  constants encoding_utf16 type abap_encoding value '4103'. "#EC NOTEXT
  constants version        type string value 'v2.1.7'.      "#EC NOTEXT
endinterface.

bump version to v2.1.7

bump version to v2.1.7