*&---------------------------------------------------------------------* *& Include ZABAPGIT_REPO_IMPL *&---------------------------------------------------------------------* *----------------------------------------------------------------------* * CLASS lcl_repo_offline IMPLEMENTATION *----------------------------------------------------------------------* CLASS lcl_repo_offline IMPLEMENTATION. METHOD set_files_remote. mt_remote = it_files. ENDMETHOD. ENDCLASS. "lcl_repo_offline IMPLEMENTATION *----------------------------------------------------------------------* * CLASS lcl_repo_online IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_repo_online IMPLEMENTATION. METHOD constructor. super->constructor( is_data ). mv_initialized = abap_false. ENDMETHOD. "constructor METHOD initialize. IF mv_initialized = abap_false. refresh( ). ENDIF. ENDMETHOD. METHOD status. initialize( ). IF lines( mt_status ) = 0. mt_status = lcl_file_status=>status( io_repo = me io_log = io_log ). ENDIF. rt_results = mt_status. ENDMETHOD. "status METHOD deserialize. IF ms_data-write_protect = abap_true. lcx_exception=>raise( 'Cannot deserialize. Local code is write-protected by repo config' ). ENDIF. initialize( ). super->deserialize( ). set( iv_sha1 = mv_branch ). reset_status( ). COMMIT WORK AND WAIT. ENDMETHOD. "deserialize METHOD reset_status. CLEAR mt_status. ENDMETHOD. " reset_status. METHOD refresh. DATA: lx_exception TYPE REF TO lcx_exception. super->refresh( iv_drop_cache ). reset_status( ). lcl_progress=>show( iv_key = 'Fetch' iv_current = 1 iv_total = 1 iv_text = 'Remote files' ) ##NO_TEXT. TRY. lcl_git_porcelain=>pull( EXPORTING io_repo = me IMPORTING et_files = mt_remote et_objects = mt_objects ev_branch = mv_branch ). CATCH lcx_exception INTO lx_exception. delete_initial_online_repo( abap_true ). RAISE EXCEPTION lx_exception. ENDTRY. mo_branches = lcl_git_transport=>branches( get_url( ) ). actualize_head_branch( ). mv_initialized = abap_true. ENDMETHOD. "refresh 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 get_sha1_remote. initialize( ). rv_sha1 = mv_branch. ENDMETHOD. "get_sha1_remote METHOD get_files_remote. initialize( ). rt_files = mt_remote. ENDMETHOD. "get_files METHOD get_objects. initialize( ). rt_objects = mt_objects. ENDMETHOD. "get_objects METHOD get_url. rv_url = ms_data-url. ENDMETHOD. "get_url METHOD get_branch_name. rv_name = ms_data-branch_name. ENDMETHOD. "get_branch_name METHOD get_head_branch_name. rv_name = ms_data-head_branch. ENDMETHOD. "get_head_branch_name METHOD get_branches. IF mo_branches IS NOT BOUND. mo_branches = lcl_git_transport=>branches( get_url( ) ). ENDIF. ro_branches = mo_branches. ENDMETHOD. "get_branches METHOD set_url. IF ms_data-write_protect = abap_true. lcx_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 set_branch_name. IF ms_data-write_protect = abap_true. lcx_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-write_protect = abap_true. lcx_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 get_sha1_local. rv_sha1 = ms_data-sha1. ENDMETHOD. "get_sha1_local METHOD push. DATA: lv_branch TYPE lif_defs=>ty_sha1, lt_updated_files TYPE lif_defs=>ty_file_signatures_tt. handle_stage_ignore( io_stage ). lcl_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 set( iv_sha1 = lv_branch ). ENDIF. refresh( ). update_local_checksums( lt_updated_files ). IF lcl_stage_logic=>count( me ) = 0. set( iv_sha1 = lv_branch ). ENDIF. ENDMETHOD. "push METHOD handle_stage_ignore. DATA: lv_add TYPE abap_bool, lo_dot_abapgit TYPE REF TO lcl_dot_abapgit, lt_stage TYPE lcl_stage=>ty_stage_tt. FIELD-SYMBOLS: LIKE LINE OF lt_stage. lo_dot_abapgit = get_dot_abapgit( ). lt_stage = io_stage->get_all( ). LOOP AT lt_stage ASSIGNING WHERE method = lcl_stage=>c_method-ignore. lo_dot_abapgit->add_ignore( iv_path = -file-path iv_filename = -file-filename ). " remove it from the staging object, as the action is handled here io_stage->reset( iv_path = -file-path iv_filename = -file-filename ). lv_add = abap_true. ENDLOOP. IF lv_add = abap_true. io_stage->add( iv_path = lif_defs=>gc_root_dir iv_filename = lif_defs=>gc_dot_abapgit iv_data = lo_dot_abapgit->serialize( ) ). set_dot_abapgit( lo_dot_abapgit ). ENDIF. ENDMETHOD. METHOD rebuild_local_checksums. "REMOTE DATA: lt_remote TYPE lif_defs=>ty_files_tt, lt_local TYPE lif_defs=>ty_files_item_tt, ls_last_item TYPE lif_defs=>ty_item, lv_branch_equal TYPE abap_bool, lt_checksums TYPE lcl_persistence_repo=>ty_local_checksum_tt. FIELD-SYMBOLS: LIKE LINE OF lt_checksums, LIKE LINE OF -files, LIKE LINE OF lt_remote, 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 = lif_defs=>gc_root_dir AND file-filename = lif_defs=>gc_dot_abapgit ). SORT lt_local BY item. SORT lt_remote BY path filename. LOOP AT lt_local ASSIGNING . IF ls_last_item <> -item OR sy-tabix = 1. " First or New item reached ? APPEND INITIAL LINE TO lt_checksums ASSIGNING . -item = -item. ls_last_item = -item. ENDIF. READ TABLE lt_remote ASSIGNING WITH KEY path = -file-path filename = -file-filename BINARY SEARCH. CHECK sy-subrc = 0. " Ignore new ones APPEND INITIAL LINE TO -files ASSIGNING . MOVE-CORRESPONDING -file TO . " 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 -file-sha1 <> -sha1 AND lv_branch_equal = abap_true. -sha1 = -sha1. ENDIF. ENDLOOP. set( it_checksums = lt_checksums ). reset_status( ). ENDMETHOD. " rebuild_local_checksums. METHOD delete_initial_online_repo. IF me->is_offline( ) = abap_false AND me->get_sha1_local( ) IS INITIAL. lcl_app=>repo_srv( )->delete( me ). IF iv_commit = abap_true. COMMIT WORK. ENDIF. ENDIF. ENDMETHOD. " delete_initial_online_repo METHOD delete_unnecessary_local_objs. DATA: lt_tadir TYPE lif_defs=>ty_tadir_tt. lt_tadir = get_unnecessary_local_objs( ). IF lines( lt_tadir ) > 0. lcl_objects=>delete( lt_tadir ). ENDIF. ENDMETHOD. " delete_unneccessary_local_objs. METHOD get_unnecessary_local_objs. DATA: lt_tadir TYPE lif_defs=>ty_tadir_tt, lt_tadir_unique TYPE HASHED TABLE OF lif_defs=>ty_tadir WITH UNIQUE KEY pgmid object obj_name, lt_local TYPE lif_defs=>ty_files_item_tt, lt_remote TYPE lif_defs=>ty_files_tt, lt_status TYPE lif_defs=>ty_results_tt, lv_package TYPE lcl_persistence_repo=>ty_repo-package. FIELD-SYMBOLS: TYPE lif_defs=>ty_result, TYPE lif_defs=>ty_tadir. " delete objects which are added locally but are not in remote repo lt_local = me->get_files_local( ). lt_remote = me->get_files_remote( ). lt_status = me->status( ). lv_package = me->get_package( ). lt_tadir = lcl_tadir=>read( lv_package ). SORT lt_tadir BY pgmid ASCENDING object ASCENDING obj_name ASCENDING devclass ASCENDING. LOOP AT lt_status ASSIGNING WHERE lstate = lif_defs=>gc_state-added. READ TABLE lt_tadir ASSIGNING WITH KEY pgmid = 'R3TR' object = -obj_type obj_name = -obj_name devclass = -package BINARY SEARCH. IF sy-subrc <> 0. * skip objects that does not exist locally CONTINUE. ENDIF. INSERT INTO TABLE lt_tadir_unique. ENDLOOP. rt_unnecessary_local_objects = lt_tadir_unique. ENDMETHOD. ENDCLASS. "lcl_repo_online IMPLEMENTATION *----------------------------------------------------------------------* * CLASS lcl_repo IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_repo IMPLEMENTATION. METHOD constructor. ASSERT NOT is_data-key IS INITIAL. ms_data = is_data. ENDMETHOD. "constructor METHOD find_remote_dot_abapgit. FIELD-SYMBOLS: LIKE LINE OF mt_remote. READ TABLE mt_remote ASSIGNING WITH KEY path = lif_defs=>gc_root_dir filename = lif_defs=>gc_dot_abapgit. IF sy-subrc = 0. ro_dot = lcl_dot_abapgit=>deserialize( -data ). ENDIF. ENDMETHOD. METHOD get_files_remote. rt_files = mt_remote. ENDMETHOD. METHOD set. DATA: lo_persistence TYPE REF TO lcl_persistence_repo. ASSERT iv_sha1 IS SUPPLIED OR it_checksums IS SUPPLIED OR iv_url IS SUPPLIED OR iv_branch_name IS SUPPLIED OR iv_head_branch IS SUPPLIED OR iv_offline IS SUPPLIED OR is_dot_abapgit IS SUPPLIED. CREATE OBJECT lo_persistence. IF iv_sha1 IS SUPPLIED. lo_persistence->update_sha1( iv_key = ms_data-key iv_branch_sha1 = iv_sha1 ). ms_data-sha1 = iv_sha1. ENDIF. IF it_checksums IS SUPPLIED. lo_persistence->update_local_checksums( iv_key = ms_data-key it_checksums = it_checksums ). ms_data-local_checksums = it_checksums. ENDIF. IF iv_url IS SUPPLIED. lo_persistence->update_url( iv_key = ms_data-key iv_url = iv_url ). ms_data-url = iv_url. ENDIF. IF iv_branch_name IS SUPPLIED. lo_persistence->update_branch_name( iv_key = ms_data-key iv_branch_name = iv_branch_name ). ms_data-branch_name = iv_branch_name. ENDIF. IF iv_head_branch IS SUPPLIED. lo_persistence->update_head_branch( iv_key = ms_data-key iv_head_branch = iv_head_branch ). ms_data-head_branch = iv_head_branch. ENDIF. IF iv_offline IS SUPPLIED. lo_persistence->update_offline( iv_key = ms_data-key iv_offline = iv_offline ). ms_data-offline = iv_offline. ENDIF. IF is_dot_abapgit IS SUPPLIED. lo_persistence->update_dot_abapgit( iv_key = ms_data-key is_dot_abapgit = is_dot_abapgit ). ms_data-dot_abapgit = is_dot_abapgit. ENDIF. ENDMETHOD. METHOD update_local_checksums. " ASSUMTION: SHA1 in param is actual and correct. " Push fills it from local files before pushing, deserialize from remote " If this is not true that there is an error somewhere but not here DATA: lt_checksums TYPE lcl_persistence_repo=>ty_local_checksum_tt, lt_files_idx TYPE lif_defs=>ty_file_signatures_tt, lt_local TYPE lif_defs=>ty_files_item_tt, lv_chks_row TYPE i, lv_file_row TYPE i. FIELD-SYMBOLS: LIKE LINE OF lt_checksums, LIKE LINE OF -files, LIKE LINE OF lt_local, LIKE LINE OF it_files. lt_checksums = get_local_checksums( ). lt_files_idx = it_files. SORT lt_files_idx BY path filename. " Sort for binary search " Loop through current chacksum state, update sha1 for common files LOOP AT lt_checksums ASSIGNING . lv_chks_row = sy-tabix. LOOP AT -files ASSIGNING . lv_file_row = sy-tabix. READ TABLE lt_files_idx ASSIGNING WITH KEY path = -path filename = -filename BINARY SEARCH. CHECK sy-subrc = 0. " Missing in param table, skip IF -sha1 IS INITIAL. " Empty input sha1 is a deletion marker DELETE -files INDEX lv_file_row. ELSE. -sha1 = -sha1. " Update sha1 CLEAR -sha1. " Mark as processed ENDIF. ENDLOOP. IF lines( -files ) = 0. " Remove empty objects DELETE lt_checksums INDEX lv_chks_row. ENDIF. ENDLOOP. DELETE lt_files_idx WHERE sha1 IS INITIAL. " Remove processed IF lines( lt_files_idx ) > 0. lt_local = get_files_local( ). SORT lt_local BY file-path file-filename. " Sort for binary search ENDIF. " Add new files - not deleted and not marked as processed above LOOP AT lt_files_idx ASSIGNING . READ TABLE lt_local ASSIGNING WITH KEY file-path = -path file-filename = -filename BINARY SEARCH. IF sy-subrc <> 0. * if the deserialization fails, the local file might not be there CONTINUE. ENDIF. READ TABLE lt_checksums ASSIGNING " TODO Optimize WITH KEY item = -item. IF sy-subrc > 0. APPEND INITIAL LINE TO lt_checksums ASSIGNING . -item = -item. ENDIF. APPEND TO -files. ENDLOOP. SORT lt_checksums BY item. set( it_checksums = lt_checksums ). ENDMETHOD. " update_local_checksums METHOD deserialize. DATA: lt_updated_files TYPE lif_defs=>ty_file_signatures_tt, lo_dot_abapgit TYPE REF TO lcl_dot_abapgit, lt_requirements TYPE STANDARD TABLE OF lcl_dot_abapgit=>ty_requirement. IF get_dot_abapgit( )->get_master_language( ) <> sy-langu. lcx_exception=>raise( 'Current login language does not match master language' ). ENDIF. lo_dot_abapgit = find_remote_dot_abapgit( ). IF lo_dot_abapgit IS BOUND. set_dot_abapgit( lo_dot_abapgit ). lt_requirements = lo_dot_abapgit->get_data( )-requirements. IF lt_requirements IS NOT INITIAL. lcl_requirement_helper=>check_requirements( it_requirements = lt_requirements iv_show_popup = abap_true ). ENDIF. ENDIF. lt_updated_files = lcl_objects=>deserialize( me ). APPEND get_dot_abapgit( )->get_signature( ) TO lt_updated_files. CLEAR: mt_local, mv_last_serialization. update_local_checksums( lt_updated_files ). ENDMETHOD. METHOD get_local_checksums. rt_checksums = ms_data-local_checksums. ENDMETHOD. METHOD get_local_checksums_per_file. FIELD-SYMBOLS LIKE LINE OF ms_data-local_checksums. LOOP AT ms_data-local_checksums ASSIGNING . APPEND LINES OF -files TO rt_checksums. ENDLOOP. ENDMETHOD. METHOD get_files_local. DATA: lt_tadir TYPE lif_defs=>ty_tadir_tt, ls_item TYPE lif_defs=>ty_item, lt_files TYPE lif_defs=>ty_files_tt, lt_cache TYPE SORTED TABLE OF lif_defs=>ty_file_item WITH NON-UNIQUE KEY item. DATA: lt_filter TYPE SORTED TABLE OF tadir WITH NON-UNIQUE KEY object obj_name, lv_filter_exist TYPE abap_bool. FIELD-SYMBOLS: LIKE LINE OF lt_files, LIKE LINE OF rt_files, LIKE LINE OF lt_cache, LIKE LINE OF lt_tadir. " Serialization happened before and no refresh request IF mv_last_serialization IS NOT INITIAL AND mv_do_local_refresh = abap_false. rt_files = mt_local. RETURN. ENDIF. APPEND INITIAL LINE TO rt_files ASSIGNING . -file-path = lif_defs=>gc_root_dir. -file-filename = lif_defs=>gc_dot_abapgit. -file-data = get_dot_abapgit( )->serialize( ). -file-sha1 = lcl_hash=>sha1( iv_type = lif_defs=>gc_type-blob iv_data = -file-data ). lt_cache = mt_local. lt_tadir = lcl_tadir=>read( iv_package = get_package( ) iv_ignore_subpackages = ignore_subpackages( ) io_dot = get_dot_abapgit( ) io_log = io_log ). lt_filter = it_filter. lv_filter_exist = boolc( lines( lt_filter ) > 0 ). LOOP AT lt_tadir ASSIGNING . IF lv_filter_exist = abap_true. READ TABLE lt_filter TRANSPORTING NO FIELDS WITH KEY object = -object obj_name = -obj_name BINARY SEARCH. IF sy-subrc <> 0. CONTINUE. ENDIF. ENDIF. lcl_progress=>show( iv_key = 'Serialize' iv_current = sy-tabix iv_total = lines( lt_tadir ) iv_text = -obj_name ) ##NO_TEXT. ls_item-obj_type = -object. ls_item-obj_name = -obj_name. ls_item-devclass = -devclass. IF mv_last_serialization IS NOT INITIAL. " Try to fetch from cache READ TABLE lt_cache TRANSPORTING NO FIELDS WITH KEY item = ls_item. " type+name+package key " There is something in cache and the object is unchanged IF sy-subrc = 0 AND abap_false = lcl_objects=>has_changed_since( is_item = ls_item iv_timestamp = mv_last_serialization ). LOOP AT lt_cache ASSIGNING WHERE item = ls_item. APPEND TO rt_files. ENDLOOP. CONTINUE. ENDIF. ENDIF. lt_files = lcl_objects=>serialize( is_item = ls_item iv_language = get_master_language( ) io_log = io_log ). LOOP AT lt_files ASSIGNING . -path = -path. -sha1 = lcl_hash=>sha1( iv_type = lif_defs=>gc_type-blob iv_data = -data ). APPEND INITIAL LINE TO rt_files ASSIGNING . -file = . -item = ls_item. ENDLOOP. ENDLOOP. GET TIME STAMP FIELD mv_last_serialization. mt_local = rt_files. mv_do_local_refresh = abap_false. " Fulfill refresh ENDMETHOD. METHOD get_dot_abapgit. CREATE OBJECT ro_dot_abapgit EXPORTING is_data = ms_data-dot_abapgit. ENDMETHOD. METHOD set_dot_abapgit. set( is_dot_abapgit = io_dot_abapgit->get_data( ) ). ENDMETHOD. METHOD delete. DATA: lo_persistence TYPE REF TO lcl_persistence_repo. CREATE OBJECT lo_persistence. lo_persistence->delete( ms_data-key ). ENDMETHOD. "delete METHOD is_offline. rv_offline = ms_data-offline. ENDMETHOD. METHOD refresh. mv_do_local_refresh = abap_true. IF iv_drop_cache = abap_true. CLEAR: mv_last_serialization, mt_local. ENDIF. ENDMETHOD. "refresh METHOD refresh_local. " For testing purposes, maybe removed later mv_do_local_refresh = abap_true. ENDMETHOD. "refresh_local METHOD get_package. rv_package = ms_data-package. ENDMETHOD. "get_package METHOD get_master_language. rv_language = ms_data-dot_abapgit-master_language. ENDMETHOD. METHOD get_key. rv_key = ms_data-key. ENDMETHOD. "get_key METHOD get_name. IF ms_data-offline = abap_true. rv_name = ms_data-url. ELSE. rv_name = lcl_url=>name( ms_data-url ). rv_name = cl_http_utility=>if_http_utility~unescape_url( rv_name ). ENDIF. ENDMETHOD. "get_name METHOD is_write_protected. rv_yes = ms_data-write_protect. ENDMETHOD. "is_write_protected METHOD ignore_subpackages. rv_yes = ms_data-ignore_subpackages. ENDMETHOD. METHOD rebuild_local_checksums. "LOCAL (BASE) DATA: lt_local TYPE lif_defs=>ty_files_item_tt, ls_last_item TYPE lif_defs=>ty_item, lt_checksums TYPE lcl_persistence_repo=>ty_local_checksum_tt. FIELD-SYMBOLS: LIKE LINE OF lt_checksums, LIKE LINE OF -files, LIKE LINE OF lt_local. lt_local = get_files_local( ). DELETE lt_local " Remove non-code related files except .abapgit WHERE item IS INITIAL AND NOT ( file-path = lif_defs=>gc_root_dir AND file-filename = lif_defs=>gc_dot_abapgit ). SORT lt_local BY item. LOOP AT lt_local ASSIGNING . IF ls_last_item <> -item OR sy-tabix = 1. " First or New item reached ? APPEND INITIAL LINE TO lt_checksums ASSIGNING . -item = -item. ls_last_item = -item. ENDIF. APPEND INITIAL LINE TO -files ASSIGNING . MOVE-CORRESPONDING -file TO . ENDLOOP. set( it_checksums = lt_checksums ). ENDMETHOD. " rebuild_local_checksums. ENDCLASS. "lcl_repo IMPLEMENTATION *----------------------------------------------------------------------* * CLASS lcl_repo_srv IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_repo_srv IMPLEMENTATION. METHOD constructor. CREATE OBJECT mo_persistence. ENDMETHOD. "class_constructor METHOD list. IF mv_init = abap_false. refresh( ). ENDIF. rt_list = mt_list. ENDMETHOD. "list METHOD get. FIELD-SYMBOLS: LIKE LINE OF mt_list. IF mv_init = abap_false. refresh( ). ENDIF. LOOP AT mt_list ASSIGNING . IF ->get_key( ) = iv_key. ro_repo = . RETURN. ENDIF. ENDLOOP. lcx_exception=>raise( 'repo not found, get' ). ENDMETHOD. "get METHOD refresh. DATA: lt_list TYPE lcl_persistence_repo=>tt_repo, lo_online TYPE REF TO lcl_repo_online, lo_offline TYPE REF TO lcl_repo_offline. FIELD-SYMBOLS: LIKE LINE OF lt_list. CLEAR mt_list. lt_list = mo_persistence->list( ). LOOP AT lt_list ASSIGNING . IF -offline = abap_false. CREATE OBJECT lo_online EXPORTING is_data = . APPEND lo_online TO mt_list. ELSE. CREATE OBJECT lo_offline EXPORTING is_data = . APPEND lo_offline TO mt_list. ENDIF. ENDLOOP. mv_init = abap_true. ENDMETHOD. "refresh METHOD new_online. DATA: ls_repo TYPE lcl_persistence_repo=>ty_repo, lv_key TYPE lcl_persistence_repo=>ty_repo-key. validate_package( iv_package ). lv_key = mo_persistence->add( iv_url = iv_url iv_branch_name = iv_branch_name iv_package = iv_package iv_offline = abap_false is_dot_abapgit = lcl_dot_abapgit=>build_default( )->get_data( ) ). TRY. ls_repo = mo_persistence->read( lv_key ). CATCH lcx_not_found. lcx_exception=>raise( 'new_online not found' ). ENDTRY. CREATE OBJECT ro_repo EXPORTING is_data = ls_repo. add( ro_repo ). ENDMETHOD. "new_online METHOD new_offline. DATA: ls_repo TYPE lcl_persistence_repo=>ty_repo, lv_key TYPE lcl_persistence_repo=>ty_repo-key. validate_package( iv_package ). lv_key = mo_persistence->add( iv_url = iv_url iv_branch_name = '' iv_package = iv_package iv_offline = abap_true is_dot_abapgit = lcl_dot_abapgit=>build_default( )->get_data( ) ). TRY. ls_repo = mo_persistence->read( lv_key ). CATCH lcx_not_found. lcx_exception=>raise( 'new_offline not found' ). ENDTRY. CREATE OBJECT ro_repo EXPORTING is_data = ls_repo. add( ro_repo ). ENDMETHOD. "new_offline METHOD add. DATA: lo_repo LIKE LINE OF mt_list. LOOP AT mt_list INTO lo_repo. IF lo_repo->get_key( ) = io_repo->get_key( ). IF lo_repo = io_repo. RETURN. ENDIF. lcx_exception=>raise( 'identical keys' ). ENDIF. ENDLOOP. APPEND io_repo TO mt_list. ENDMETHOD. "add METHOD validate_package. DATA: lv_devclass TYPE tdevc-devclass, lt_repos TYPE lcl_persistence_repo=>tt_repo. IF iv_package IS INITIAL. lcx_exception=>raise( 'add, package empty' ). ENDIF. IF iv_package = '$TMP'. lcx_exception=>raise( 'not possible to use $TMP, create new (local) package' ). ENDIF. IF lcl_exit=>get_instance( )->allow_sap_objects( ) = abap_true. SELECT SINGLE devclass FROM tdevc INTO lv_devclass WHERE devclass = iv_package. "#EC CI_GENBUFF ELSE. SELECT SINGLE devclass FROM tdevc INTO lv_devclass WHERE devclass = iv_package AND as4user <> 'SAP'. "#EC CI_GENBUFF ENDIF. IF sy-subrc <> 0. lcx_exception=>raise( 'package not found or not allowed' ). ENDIF. " make sure its not already in use for a different repository lt_repos = mo_persistence->list( ). READ TABLE lt_repos WITH KEY package = iv_package TRANSPORTING NO FIELDS. IF sy-subrc = 0. lcx_exception=>raise( 'Package already in use' ). ENDIF. ENDMETHOD. "validate_package METHOD delete. io_repo->delete( ). DELETE TABLE mt_list FROM io_repo. ASSERT sy-subrc = 0. ENDMETHOD. "delete METHOD is_repo_installed. DATA: lt_repo TYPE lcl_repo_srv=>ty_repo_tt, lo_repo TYPE REF TO lcl_repo, lv_url TYPE string, lv_package TYPE devclass, lo_repo_online TYPE REF TO lcl_repo_online, lv_err TYPE string. lt_repo = list( ). LOOP AT lt_repo INTO lo_repo. CHECK lo_repo->is_offline( ) = abap_false. lo_repo_online ?= lo_repo. lv_url = lo_repo_online->get_url( ). lv_package = lo_repo_online->get_package( ). CHECK to_upper( lv_url ) = to_upper( iv_url ). " Validate bindings "TODO refactor: move this message out of this method IF iv_target_package IS NOT INITIAL AND iv_target_package <> lv_package. lv_err = |Installation to package { lv_package } detected. | && |Cancelling installation|. lcx_exception=>raise( lv_err ). ENDIF. rv_installed = abap_true. EXIT. ENDLOOP. ENDMETHOD. "is_repo_installed METHOD switch_repo_type. DATA lo_repo TYPE REF TO lcl_repo. FIELD-SYMBOLS LIKE LINE OF mt_list. lo_repo = get( iv_key ). READ TABLE mt_list ASSIGNING FROM lo_repo. ASSERT sy-subrc IS INITIAL. ASSERT iv_offline <> lo_repo->ms_data-offline. IF iv_offline = abap_true. " On-line -> OFFline lo_repo->set( iv_url = lcl_url=>name( lo_repo->ms_data-url ) iv_branch_name = '' iv_sha1 = '' iv_head_branch = '' iv_offline = abap_true ). CREATE OBJECT TYPE lcl_repo_offline EXPORTING is_data = lo_repo->ms_data. ELSE. " OFFline -> On-line lo_repo->set( iv_offline = abap_false ). CREATE OBJECT TYPE lcl_repo_online EXPORTING is_data = lo_repo->ms_data. ENDIF. ENDMETHOD. "switch_repo_type ENDCLASS. "lcl_repo_srv IMPLEMENTATION