From 40efc567f65e3b2815abdfa7faa19046727fe8aa Mon Sep 17 00:00:00 2001 From: Marc Bernard <59966492+mbtools@users.noreply.github.com> Date: Sat, 23 Jan 2021 04:11:54 -0500 Subject: [PATCH] Automatic creation of top repository package (#4431) * Automatic creation of top repository package When adding a repository, it is not necessary anymore that the top SAP package assigned to the repository exists. Just enter a package name and clone (works for offline, too). The initial diff will now show that the top package exists remotely only. Therefore, when pulling, you will not get the "confirm overwrite package" popup anymore. Yippie! * Typo Co-authored-by: Lars Hvam --- .../zcl_abapgit_default_transport.clas.abap | 4 +- ...abapgit_dependencies.clas.testclasses.abap | 4 + .../core/zcl_abapgit_folder_logic.clas.abap | 22 ++-- ...abapgit_folder_logic.clas.testclasses.abap | 8 ++ src/objects/zcl_abapgit_objects.clas.abap | 3 +- src/repo/zcl_abapgit_repo_srv.clas.abap | 15 ++- .../zcl_abapgit_gui_page_repo_view.clas.abap | 5 +- ...apgit_services_basis.clas.testclasses.abap | 4 + src/zcl_abapgit_sap_package.clas.abap | 102 ++++++++++++++---- src/zif_abapgit_sap_package.intf.abap | 76 ++++++++----- 10 files changed, 175 insertions(+), 68 deletions(-) diff --git a/src/cts/zcl_abapgit_default_transport.clas.abap b/src/cts/zcl_abapgit_default_transport.clas.abap index a030b1a6e..66b39ce89 100644 --- a/src/cts/zcl_abapgit_default_transport.clas.abap +++ b/src/cts/zcl_abapgit_default_transport.clas.abap @@ -58,7 +58,7 @@ ENDCLASS. -CLASS ZCL_ABAPGIT_DEFAULT_TRANSPORT IMPLEMENTATION. +CLASS zcl_abapgit_default_transport IMPLEMENTATION. METHOD clear. @@ -215,7 +215,7 @@ CLASS ZCL_ABAPGIT_DEFAULT_TRANSPORT IMPLEMENTATION. OTHERS = 7. IF sy-subrc <> 0. - zcx_abapgit_exception=>raise( |Error from TR_TASK_SET. Subrc = { sy-subrc }| ). + zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. diff --git a/src/objects/core/zcl_abapgit_dependencies.clas.testclasses.abap b/src/objects/core/zcl_abapgit_dependencies.clas.testclasses.abap index 42b8cb91c..2fafc0449 100644 --- a/src/objects/core/zcl_abapgit_dependencies.clas.testclasses.abap +++ b/src/objects/core/zcl_abapgit_dependencies.clas.testclasses.abap @@ -71,6 +71,10 @@ CLASS ltcl_sap_package IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_sap_package~get_transport_layer. "##needed + + ENDMETHOD. + METHOD zif_abapgit_sap_package~list_superpackages. "##needed ENDMETHOD. diff --git a/src/objects/core/zcl_abapgit_folder_logic.clas.abap b/src/objects/core/zcl_abapgit_folder_logic.clas.abap index 8292b1fc7..b4c9f560b 100644 --- a/src/objects/core/zcl_abapgit_folder_logic.clas.abap +++ b/src/objects/core/zcl_abapgit_folder_logic.clas.abap @@ -50,7 +50,7 @@ ENDCLASS. -CLASS ZCL_ABAPGIT_FOLDER_LOGIC IMPLEMENTATION. +CLASS zcl_abapgit_folder_logic IMPLEMENTATION. METHOD get_instance. @@ -146,22 +146,32 @@ CLASS ZCL_ABAPGIT_FOLDER_LOGIC IMPLEMENTATION. DATA: lv_length TYPE i, lv_parent TYPE devclass, + ls_package TYPE scompkdtln, lv_new TYPE string, lv_path TYPE string, lv_absolute_name TYPE string, - lv_top TYPE devclass, lt_unique_package_names TYPE HASHED TABLE OF devclass WITH UNIQUE KEY table_line. - lv_top = iv_top. - lv_length = strlen( io_dot->get_starting_folder( ) ). IF lv_length > strlen( iv_path ). * treat as not existing locally RETURN. ENDIF. lv_path = iv_path+lv_length. - lv_parent = lv_top. - rv_package = lv_top. + lv_parent = iv_top. + rv_package = iv_top. + + " Automatically create package using minimal properties + " Details will be updated during deserialization + IF iv_create_if_not_exists = abap_true. + IF iv_top(1) = '$'. + zcl_abapgit_factory=>get_sap_package( iv_top )->create_local( ). + ELSE. + ls_package-devclass = ls_package-ctext = iv_top. + ls_package-as4user = cl_abap_syst=>get_user_name( ). + zcl_abapgit_factory=>get_sap_package( iv_top )->create( ls_package ). + ENDIF. + ENDIF. INSERT iv_top INTO TABLE lt_unique_package_names. diff --git a/src/objects/core/zcl_abapgit_folder_logic.clas.testclasses.abap b/src/objects/core/zcl_abapgit_folder_logic.clas.testclasses.abap index 824937093..63206c903 100644 --- a/src/objects/core/zcl_abapgit_folder_logic.clas.testclasses.abap +++ b/src/objects/core/zcl_abapgit_folder_logic.clas.testclasses.abap @@ -96,6 +96,10 @@ CLASS ltcl_folder_logic IMPLEMENTATION. RETURN. ENDMETHOD. + METHOD zif_abapgit_sap_package~get_transport_layer. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_sap_package~create. RETURN. ENDMETHOD. @@ -217,6 +221,10 @@ CLASS ltcl_folder_logic_namespaces IMPLEMENTATION. RETURN. ENDMETHOD. + METHOD zif_abapgit_sap_package~get_transport_layer. + RETURN. + ENDMETHOD. + METHOD zif_abapgit_sap_package~create. RETURN. ENDMETHOD. diff --git a/src/objects/zcl_abapgit_objects.clas.abap b/src/objects/zcl_abapgit_objects.clas.abap index 4768a582c..d29a57c9b 100644 --- a/src/objects/zcl_abapgit_objects.clas.abap +++ b/src/objects/zcl_abapgit_objects.clas.abap @@ -1415,7 +1415,8 @@ CLASS zcl_abapgit_objects IMPLEMENTATION. lv_package = lo_folder_logic->path_to_package( iv_top = io_repo->get_package( ) io_dot = io_repo->get_dot_abapgit( ) - iv_path = -path ). + iv_path = -path + iv_create_if_not_exists = abap_false ). ls_tadir = zcl_abapgit_factory=>get_tadir( )->read_single( iv_object = -obj_type diff --git a/src/repo/zcl_abapgit_repo_srv.clas.abap b/src/repo/zcl_abapgit_repo_srv.clas.abap index 3baca3cf8..389b053b4 100644 --- a/src/repo/zcl_abapgit_repo_srv.clas.abap +++ b/src/repo/zcl_abapgit_repo_srv.clas.abap @@ -554,25 +554,24 @@ CLASS zcl_abapgit_repo_srv IMPLEMENTATION. zcx_abapgit_exception=>raise( 'not possible to use $TMP, create new (local) package' ). ENDIF. + " Check if package owned by SAP is allowed (new packages are ok, since they are created automatically) SELECT SINGLE as4user FROM tdevc INTO lv_as4user WHERE devclass = iv_package. "#EC CI_GENBUFF - IF sy-subrc <> 0. - zcx_abapgit_exception=>raise( |Package { iv_package } not found| ). - ENDIF. - - IF zcl_abapgit_factory=>get_environment( )->is_sap_object_allowed( ) = abap_false AND lv_as4user = 'SAP'. + IF sy-subrc = 0 AND lv_as4user = 'SAP' AND + zcl_abapgit_factory=>get_environment( )->is_sap_object_allowed( ) = abap_false. zcx_abapgit_exception=>raise( |Package { iv_package } not allowed, responsible user = 'SAP'| ). ENDIF. + " Check if package is already used in another repo IF iv_chk_exists = abap_true. get_repo_from_package( EXPORTING - iv_package = iv_package + iv_package = iv_package iv_ign_subpkg = iv_ign_subpkg IMPORTING - eo_repo = lo_repo - ev_reason = lv_reason ). + eo_repo = lo_repo + ev_reason = lv_reason ). IF lo_repo IS BOUND. zcx_abapgit_exception=>raise( lv_reason ). diff --git a/src/ui/zcl_abapgit_gui_page_repo_view.clas.abap b/src/ui/zcl_abapgit_gui_page_repo_view.clas.abap index e26d33617..9a6a596e2 100644 --- a/src/ui/zcl_abapgit_gui_page_repo_view.clas.abap +++ b/src/ui/zcl_abapgit_gui_page_repo_view.clas.abap @@ -605,8 +605,7 @@ CLASS zcl_abapgit_gui_page_repo_view IMPLEMENTATION. METHOD constructor. DATA: lo_settings TYPE REF TO zcl_abapgit_settings, - lx_error TYPE REF TO zcx_abapgit_exception, - lv_package TYPE devclass. + lx_error TYPE REF TO zcx_abapgit_exception. super->constructor( ). @@ -626,8 +625,6 @@ CLASS zcl_abapgit_gui_page_repo_view IMPLEMENTATION. mv_max_lines = lo_settings->get_max_lines( ). mv_max_setting = mv_max_lines. - lv_package = mo_repo->get_package( ). - CATCH zcx_abapgit_exception INTO lx_error. " Reset 'last shown repo' so next start will go to repo overview " and allow troubleshooting of issue diff --git a/src/ui/zcl_abapgit_services_basis.clas.testclasses.abap b/src/ui/zcl_abapgit_services_basis.clas.testclasses.abap index c0f03b9bc..ca9f55071 100644 --- a/src/ui/zcl_abapgit_services_basis.clas.testclasses.abap +++ b/src/ui/zcl_abapgit_services_basis.clas.testclasses.abap @@ -302,6 +302,10 @@ CLASS ltcl_sap_package_mock IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_sap_package~get_transport_layer. + + ENDMETHOD. + METHOD zif_abapgit_sap_package~list_subpackages. ENDMETHOD. diff --git a/src/zcl_abapgit_sap_package.clas.abap b/src/zcl_abapgit_sap_package.clas.abap index f9b6a2b3a..ae5e8de77 100644 --- a/src/zcl_abapgit_sap_package.clas.abap +++ b/src/zcl_abapgit_sap_package.clas.abap @@ -17,7 +17,7 @@ ENDCLASS. -CLASS ZCL_ABAPGIT_SAP_PACKAGE IMPLEMENTATION. +CLASS zcl_abapgit_sap_package IMPLEMENTATION. METHOD constructor. @@ -42,11 +42,15 @@ CLASS ZCL_ABAPGIT_SAP_PACKAGE IMPLEMENTATION. object_locked_and_modified = 5 OTHERS = 6 ). - IF sy-subrc <> 0. - zcx_abapgit_exception=>raise_t100( ). - ENDIF. - - rv_are_changes_rec_in_tr_req = li_package->wbo_korr_flag. + CASE sy-subrc. + WHEN 0. + rv_are_changes_rec_in_tr_req = li_package->wbo_korr_flag. + WHEN 1. + " For new packages, derive from package name + rv_are_changes_rec_in_tr_req = boolc( mv_package(1) <> '$' ). + WHEN OTHERS. + zcx_abapgit_exception=>raise_t100( ). + ENDCASE. ENDMETHOD. @@ -83,6 +87,11 @@ CLASS ZCL_ABAPGIT_SAP_PACKAGE IMPLEMENTATION. ls_package-dlvunit = 'HOME'. ENDIF. + " For transportable packages, get default transport and layer + IF ls_package-devclass(1) <> '$' AND ls_package-pdevclass IS INITIAL. + ls_package-pdevclass = zif_abapgit_sap_package~get_transport_layer( ). + ENDIF. + cl_package_factory=>create_new_package( EXPORTING i_reuse_deleted_object = abap_true @@ -220,27 +229,80 @@ CLASS ZCL_ABAPGIT_SAP_PACKAGE IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_sap_package~get_transport_layer. + + " Get default transport layer + CALL FUNCTION 'TR_GET_TRANSPORT_TARGET' + EXPORTING + iv_use_default = abap_true + iv_get_layer_only = abap_true + IMPORTING + ev_layer = rv_transport_layer + EXCEPTIONS + wrong_call = 1 + invalid_input = 2 + cts_initialization_failure = 3 + OTHERS = 4. + IF sy-subrc <> 0. + " Return empty layer (i.e. "local workbench request" for the package) + CLEAR rv_transport_layer. + ENDIF. + + ENDMETHOD. + + METHOD zif_abapgit_sap_package~get_transport_type. - DATA lv_pkg_name TYPE e071-obj_name. + DATA: + lv_pkg_name TYPE e071-obj_name, + lv_obj_name TYPE tadir-obj_name, + lv_role TYPE trnrole. - lv_pkg_name = mv_package. + lv_pkg_name = lv_obj_name = mv_package. - CALL FUNCTION 'TRINT_GET_REQUEST_TYPE' + CALL FUNCTION 'TR_GET_REQUEST_TYPE' EXPORTING - iv_pgmid = 'R3TR' - iv_object = 'DEVC' - iv_obj_name = lv_pkg_name + iv_pgmid = 'R3TR' + iv_object = 'DEVC' + iv_obj_name = lv_pkg_name IMPORTING - ev_request_type = rs_transport_type-request - ev_task_type = rs_transport_type-task + ev_request_type = rs_transport_type-request + ev_task_type = rs_transport_type-task EXCEPTIONS - no_request_needed = 1 - internal_error = 2 - cts_initialization_failure = 3. - IF sy-subrc <> 0. - zcx_abapgit_exception=>raise_t100( ). - ENDIF. + no_request_needed = 1 + invalid_object = 2 + system_error = 3 + OTHERS = 4. + + CASE sy-subrc. + WHEN 0 OR 1. + RETURN. + WHEN 2. + " For new packages, set to workbench request + rs_transport_type-request = 'K'. + + CALL FUNCTION 'TR_GET_NAMESPACE_AND_ROLE' + EXPORTING + iv_pgmid = 'R3TR' + iv_object = 'DEVC' + iv_objname = lv_obj_name + IMPORTING + ev_role = lv_role + EXCEPTIONS + namespace_not_existing = 1 + invalid_object = 2 + namespace_not_determinable = 3 + OTHERS = 4. + IF sy-subrc = 0 AND lv_role = 'C'. + " Namespace with repair license requires repair task + rs_transport_type-task = 'R'. + ELSE. + " Otherweise use correction task + rs_transport_type-task = 'S'. + ENDIF. + WHEN OTHERS. + zcx_abapgit_exception=>raise_t100( ). + ENDCASE. ENDMETHOD. diff --git a/src/zif_abapgit_sap_package.intf.abap b/src/zif_abapgit_sap_package.intf.abap index 6c3c185c2..79c7d4ab2 100644 --- a/src/zif_abapgit_sap_package.intf.abap +++ b/src/zif_abapgit_sap_package.intf.abap @@ -1,30 +1,52 @@ -INTERFACE zif_abapgit_sap_package PUBLIC. +INTERFACE zif_abapgit_sap_package + PUBLIC . - TYPES: ty_devclass_tt TYPE STANDARD TABLE OF devclass WITH DEFAULT KEY. - METHODS: - create - IMPORTING is_package TYPE scompkdtln - RAISING zcx_abapgit_exception, - create_local - RAISING zcx_abapgit_exception, - list_subpackages - RETURNING VALUE(rt_list) TYPE ty_devclass_tt, - list_superpackages - RETURNING VALUE(rt_list) TYPE ty_devclass_tt - RAISING zcx_abapgit_exception, - read_parent - RETURNING VALUE(rv_parentcl) TYPE tdevc-parentcl - RAISING zcx_abapgit_exception, - create_child - IMPORTING iv_child TYPE devclass - RAISING zcx_abapgit_exception, - exists - RETURNING VALUE(rv_bool) TYPE abap_bool, - are_changes_recorded_in_tr_req - RETURNING VALUE(rv_are_changes_rec_in_tr_req) TYPE abap_bool - RAISING zcx_abapgit_exception, - get_transport_type - RETURNING VALUE(rs_transport_type) TYPE zif_abapgit_definitions=>ty_transport_type - RAISING zcx_abapgit_exception. + TYPES: + ty_devclass_tt TYPE STANDARD TABLE OF devclass WITH DEFAULT KEY . + + METHODS create + IMPORTING + !is_package TYPE scompkdtln + RAISING + zcx_abapgit_exception . + METHODS create_local + RAISING + zcx_abapgit_exception . + METHODS list_subpackages + RETURNING + VALUE(rt_list) TYPE ty_devclass_tt . + METHODS list_superpackages + RETURNING + VALUE(rt_list) TYPE ty_devclass_tt + RAISING + zcx_abapgit_exception . + METHODS read_parent + RETURNING + VALUE(rv_parentcl) TYPE tdevc-parentcl + RAISING + zcx_abapgit_exception . + METHODS create_child + IMPORTING + !iv_child TYPE devclass + RAISING + zcx_abapgit_exception . + METHODS exists + RETURNING + VALUE(rv_bool) TYPE abap_bool . + METHODS are_changes_recorded_in_tr_req + RETURNING + VALUE(rv_are_changes_rec_in_tr_req) TYPE abap_bool + RAISING + zcx_abapgit_exception . + METHODS get_transport_type + RETURNING + VALUE(rs_transport_type) TYPE zif_abapgit_definitions=>ty_transport_type + RAISING + zcx_abapgit_exception . + METHODS get_transport_layer + RETURNING + VALUE(rv_transport_layer) TYPE devlayer + RAISING + zcx_abapgit_exception . ENDINTERFACE.