Merge pull request #438 from sbcgua/master

Fixes: separate repo_browser, lcl_sap_package=>check(), repotext cache fix
This commit is contained in:
Lars Hvam 2016-11-18 12:18:37 +01:00 committed by GitHub
commit 2be06d0657
9 changed files with 548 additions and 335 deletions

View File

@ -4,8 +4,17 @@
* All UI pages
INCLUDE zabapgit_html_action_utils.
* Super class
INCLUDE zabapgit_page.
* Utils and helpers
INCLUDE zabapgit_html_action_utils.
INCLUDE zabapgit_repo_browser_util.
* Components and templates
INCLUDE zabapgit_view_repo.
* Pages
INCLUDE zabapgit_page_commit.
INCLUDE zabapgit_page_merge.
INCLUDE zabapgit_page_background.

View File

@ -1427,7 +1427,9 @@ CLASS lcl_objects_program IMPLEMENTATION.
WHERE progname = iv_program
AND r3state = 'A'.
_object_check_timestamp lv_date lv_time.
IF sy-subrc = 0. " Text not found ? Assuming no changes, see #404
_object_check_timestamp lv_date lv_time.
ENDIF.
IF iv_skip_gui = abap_true.
RETURN.

View File

@ -2,8 +2,6 @@
*& Include ZABAPGIT_PAGE_MAIN
*&---------------------------------------------------------------------*
INCLUDE zabapgit_view_repo.
CLASS lcl_gui_page_main DEFINITION FINAL INHERITING FROM lcl_gui_page_super.
PUBLIC SECTION.

View File

@ -0,0 +1,243 @@
*&---------------------------------------------------------------------*
*& Include ZABAPGIT_REPO_BROWSER_UTIL
*&---------------------------------------------------------------------*
CLASS lcl_repo_content_browser DEFINITION FINAL.
PUBLIC SECTION.
CONSTANTS: BEGIN OF c_sortkey,
default TYPE i VALUE 9999,
parent_dir TYPE i VALUE 0,
dir TYPE i VALUE 1,
orphan TYPE i VALUE 2,
changed TYPE i VALUE 3,
END OF c_sortkey.
TYPES: BEGIN OF ty_repo_item,
obj_type TYPE tadir-object,
obj_name TYPE tadir-obj_name,
sortkey TYPE i,
path TYPE string,
is_dir TYPE abap_bool,
changes TYPE i,
lstate TYPE char1,
rstate TYPE char1,
files TYPE tt_repo_files,
END OF ty_repo_item.
TYPES tt_repo_items TYPE STANDARD TABLE OF ty_repo_item WITH DEFAULT KEY.
METHODS constructor
IMPORTING io_repo TYPE REF TO lcl_repo.
METHODS list
IMPORTING iv_path TYPE string
iv_by_folders TYPE abap_bool
iv_changes_only TYPE abap_bool
RETURNING VALUE(rt_repo_items) TYPE tt_repo_items
RAISING lcx_exception.
METHODS get_log
RETURNING VALUE(ro_log) TYPE REF TO lcl_log.
PRIVATE SECTION.
DATA: mo_repo TYPE REF TO lcl_repo,
mo_log TYPE REF TO lcl_log.
METHODS build_repo_items_offline
RETURNING VALUE(rt_repo_items) TYPE tt_repo_items
RAISING lcx_exception.
METHODS build_repo_items_online
RETURNING VALUE(rt_repo_items) TYPE tt_repo_items
RAISING lcx_exception.
METHODS build_folders
IMPORTING iv_cur_dir TYPE string
CHANGING ct_repo_items TYPE tt_repo_items
RAISING lcx_exception.
METHODS filter_changes
CHANGING ct_repo_items TYPE tt_repo_items.
ENDCLASS. "lcl_repo_content_browser
DEFINE _reduce_state.
" &1 - prev, &2 - cur
IF &1 = &2 OR &2 IS INITIAL.
ASSERT 1 = 1. " No change
ELSEIF &1 IS INITIAL.
&1 = &2.
ELSE.
&1 = gc_state-mixed.
ENDIF.
END-OF-DEFINITION.
CLASS lcl_repo_content_browser IMPLEMENTATION.
METHOD constructor.
mo_repo = io_repo.
CREATE OBJECT mo_log.
ENDMETHOD. "constructor
METHOD get_log.
ro_log = mo_log.
ENDMETHOD. "get_log
METHOD list.
mo_log->clear( ).
IF mo_repo->is_offline( ) = abap_true.
rt_repo_items = build_repo_items_offline( ).
ELSE.
rt_repo_items = build_repo_items_online( ).
ENDIF.
IF iv_by_folders = abap_true.
build_folders(
EXPORTING iv_cur_dir = iv_path
CHANGING ct_repo_items = rt_repo_items ).
ENDIF.
IF iv_changes_only = abap_true.
filter_changes( CHANGING ct_repo_items = rt_repo_items ).
ENDIF.
SORT rt_repo_items BY
sortkey ASCENDING
obj_type ASCENDING
obj_name ASCENDING.
ENDMETHOD. "list
METHOD build_folders.
DATA: lv_index TYPE i,
lt_subitems LIKE ct_repo_items,
ls_subitem LIKE LINE OF ct_repo_items,
ls_folder LIKE LINE OF ct_repo_items.
FIELD-SYMBOLS <item> LIKE LINE OF ct_repo_items.
LOOP AT ct_repo_items ASSIGNING <item>.
lv_index = sy-tabix.
CHECK <item>-path <> iv_cur_dir. " files in target dir - just leave them be
IF lcl_path=>is_subdir( iv_path = <item>-path iv_parent = iv_cur_dir ) = abap_true.
ls_subitem-changes = <item>-changes.
ls_subitem-path = <item>-path.
ls_subitem-lstate = <item>-lstate.
ls_subitem-rstate = <item>-rstate.
APPEND ls_subitem TO lt_subitems.
ENDIF.
DELETE ct_repo_items INDEX lv_index.
ENDLOOP.
SORT lt_subitems BY path ASCENDING.
LOOP AT lt_subitems ASSIGNING <item>.
AT NEW path.
CLEAR ls_folder.
ls_folder-path = <item>-path.
ls_folder-sortkey = c_sortkey-dir. " Directory
ls_folder-is_dir = abap_true.
ENDAT.
ls_folder-changes = ls_folder-changes + <item>-changes.
_reduce_state ls_folder-lstate <item>-lstate.
_reduce_state ls_folder-rstate <item>-rstate.
AT END OF path.
APPEND ls_folder TO ct_repo_items.
ENDAT.
ENDLOOP.
ENDMETHOD. "build_folders
METHOD filter_changes.
DATA lt_repo_temp LIKE ct_repo_items.
FIELD-SYMBOLS <item> LIKE LINE OF ct_repo_items.
LOOP AT ct_repo_items ASSIGNING <item>.
CHECK <item>-changes > 0.
APPEND <item> TO lt_repo_temp.
ENDLOOP.
IF lines( lt_repo_temp ) > 0. " Prevent showing empty package if no changes, show all
ct_repo_items = lt_repo_temp.
ENDIF.
ENDMETHOD. "filter_changes
METHOD build_repo_items_offline.
DATA: lt_tadir TYPE ty_tadir_tt.
FIELD-SYMBOLS: <ls_repo_item> LIKE LINE OF rt_repo_items,
<ls_tadir> LIKE LINE OF lt_tadir.
lt_tadir = lcl_tadir=>read( mo_repo->get_package( ) ).
LOOP AT lt_tadir ASSIGNING <ls_tadir>.
APPEND INITIAL LINE TO rt_repo_items ASSIGNING <ls_repo_item>.
<ls_repo_item>-obj_type = <ls_tadir>-object.
<ls_repo_item>-obj_name = <ls_tadir>-obj_name.
<ls_repo_item>-path = '/' && <ls_tadir>-path. " Add root anchor
<ls_repo_item>-sortkey = c_sortkey-default. " Default sort key
ENDLOOP.
ENDMETHOD. "build_repo_items_offline
METHOD build_repo_items_online.
DATA: lo_repo_online TYPE REF TO lcl_repo_online,
ls_file TYPE ty_repo_file,
lt_status TYPE ty_results_tt.
FIELD-SYMBOLS: <status> LIKE LINE OF lt_status,
<ls_repo_item> LIKE LINE OF rt_repo_items.
lo_repo_online ?= mo_repo.
lt_status = lo_repo_online->status( mo_log ).
LOOP AT lt_status ASSIGNING <status>.
AT NEW obj_name. "obj_type + obj_name
APPEND INITIAL LINE TO rt_repo_items ASSIGNING <ls_repo_item>.
<ls_repo_item>-obj_type = <status>-obj_type.
<ls_repo_item>-obj_name = <status>-obj_name.
<ls_repo_item>-sortkey = c_sortkey-default. " Default sort key
<ls_repo_item>-changes = 0.
<ls_repo_item>-path = <status>-path.
ENDAT.
IF <status>-filename IS NOT INITIAL.
ls_file-path = <status>-path.
ls_file-filename = <status>-filename.
ls_file-is_changed = boolc( <status>-match = abap_false ). " TODO refactor
ls_file-rstate = <status>-rstate.
ls_file-lstate = <status>-lstate.
APPEND ls_file TO <ls_repo_item>-files.
IF ls_file-is_changed = abap_true.
<ls_repo_item>-sortkey = c_sortkey-changed. " Changed files
<ls_repo_item>-changes = <ls_repo_item>-changes + 1.
_reduce_state <ls_repo_item>-lstate ls_file-lstate.
_reduce_state <ls_repo_item>-rstate ls_file-rstate.
ENDIF.
ENDIF.
AT END OF obj_name. "obj_type + obj_name
IF <ls_repo_item>-obj_type IS INITIAL.
<ls_repo_item>-sortkey = c_sortkey-orphan. "Virtual objects
ENDIF.
ENDAT.
ENDLOOP.
ENDMETHOD. "build_repo_items_online
ENDCLASS. "lcl_repo_content_browser

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_PROG" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<PROGDIR>
<NAME>ZABAPGIT_REPO_BROWSER_UTIL</NAME>
<STATE>A</STATE>
<SQLX/>
<EDTX/>
<VARCL>X</VARCL>
<DBAPL/>
<DBNA/>
<CLAS/>
<TYPE/>
<OCCURS/>
<SUBC>I</SUBC>
<APPL/>
<SECU/>
<CNAM/>
<CDAT>0000-00-00</CDAT>
<UNAM/>
<UDAT>0000-00-00</UDAT>
<VERN/>
<LEVL/>
<RSTAT/>
<RMAND/>
<RLOAD>E</RLOAD>
<FIXPT/>
<SSET/>
<SDATE>0000-00-00</SDATE>
<STIME/>
<IDATE>0000-00-00</IDATE>
<ITIME/>
<LDBNAME/>
<UCCHECK>X</UCCHECK>
</PROGDIR>
<TPOOL>
<item>
<ID>R</ID>
<KEY/>
<ENTRY>Include ZABAPGIT_REPO_BROWSER_UTIL</ENTRY>
<LENGTH>34</LENGTH>
<SPLIT/>
</item>
</TPOOL>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -98,7 +98,11 @@ CLASS lcl_sap_package IMPLEMENTATION.
METHOD check.
DATA: lv_path TYPE string.
DATA: lv_path TYPE string,
ls_item TYPE ty_item,
ls_file TYPE ty_file_signature,
lt_res_sort LIKE it_results,
lt_item_idx LIKE it_results.
FIELD-SYMBOLS: <ls_res1> LIKE LINE OF it_results,
<ls_res2> LIKE LINE OF it_results.
@ -108,22 +112,37 @@ CLASS lcl_sap_package IMPLEMENTATION.
RETURN.
ENDIF.
* check files for one object is in the same folder
LOOP AT it_results ASSIGNING <ls_res1>
WHERE NOT obj_type IS INITIAL.
LOOP AT it_results ASSIGNING <ls_res2>
WHERE obj_type = <ls_res1>-obj_type
AND obj_name = <ls_res1>-obj_name
AND path <> <ls_res1>-path.
" Collect object indexe
lt_res_sort = it_results.
SORT lt_res_sort BY obj_type ASCENDING obj_name ASCENDING.
LOOP AT it_results ASSIGNING <ls_res1> WHERE NOT obj_type IS INITIAL.
IF NOT ( <ls_res1>-obj_type = ls_item-obj_type AND <ls_res1>-obj_name = ls_item-obj_name ).
APPEND INITIAL LINE TO lt_item_idx ASSIGNING <ls_res2>.
<ls_res2>-obj_type = <ls_res1>-obj_type.
<ls_res2>-obj_name = <ls_res1>-obj_name.
<ls_res2>-path = <ls_res1>-path.
MOVE-CORRESPONDING <ls_res1> TO ls_item.
ENDIF.
ENDLOOP.
" Check files for one object is in the same folder
LOOP AT it_results ASSIGNING <ls_res1> WHERE NOT obj_type IS INITIAL.
READ TABLE lt_item_idx ASSIGNING <ls_res2>
WITH KEY obj_type = <ls_res1>-obj_type obj_name = <ls_res1>-obj_name
BINARY SEARCH. " Sorted above
IF sy-subrc <> 0 OR <ls_res1>-path <> <ls_res2>-path. " All paths are same
io_log->add( iv_msgv1 = 'Files for object'
iv_msgv2 = <ls_res1>-obj_type
iv_msgv3 = <ls_res1>-obj_name
iv_msgv4 = 'are not placed in the same folder' ) ##no_text.
EXIT.
ENDLOOP.
iv_msgv4 = 'are not placed in the same folder'
iv_rc = '1' ) ##no_text.
ENDIF.
ENDLOOP.
* check that objects are created in package corresponding to folder
" Check that objects are created in package corresponding to folder
LOOP AT it_results ASSIGNING <ls_res1>
WHERE NOT package IS INITIAL AND NOT path IS INITIAL.
lv_path = class_to_path( iv_top = iv_top
@ -132,20 +151,29 @@ CLASS lcl_sap_package IMPLEMENTATION.
IF lv_path <> <ls_res1>-path.
io_log->add( iv_msgv1 = 'Package and path does not match for object,'
iv_msgv2 = <ls_res1>-obj_type
iv_msgv3 = <ls_res1>-obj_name ) ##no_text.
iv_msgv3 = <ls_res1>-obj_name
iv_rc = '2' ) ##no_text.
ENDIF.
ENDLOOP.
* check for multiple files with same filename
LOOP AT it_results ASSIGNING <ls_res1>
WHERE NOT filename IS INITIAL.
LOOP AT it_results ASSIGNING <ls_res2>
WHERE filename = <ls_res1>-filename
AND path <> <ls_res1>-path.
" Check for multiple files with same filename
SORT lt_res_sort BY filename ASCENDING.
LOOP AT lt_res_sort ASSIGNING <ls_res1>.
IF <ls_res1>-filename IS NOT INITIAL AND <ls_res1>-filename = ls_file-filename.
io_log->add( iv_msgv1 = 'Multiple files with same filename,'
iv_msgv2 = <ls_res1>-filename ) ##no_text.
EXIT.
ENDLOOP.
iv_msgv2 = <ls_res1>-filename
iv_rc = '3' ) ##no_text.
ENDIF.
IF <ls_res1>-filename IS INITIAL.
io_log->add( iv_msgv1 = 'Filename is empty for object'
iv_msgv2 = <ls_res1>-obj_type
iv_msgv3 = <ls_res1>-obj_name
iv_rc = '4' ) ##no_text.
ENDIF.
MOVE-CORRESPONDING <ls_res1> TO ls_file.
ENDLOOP.
ENDMETHOD. "check

View File

@ -2,6 +2,42 @@
*& Include ZABAPGIT_UNIT_TEST
*&---------------------------------------------------------------------*
DEFINE _append_local.
APPEND INITIAL LINE TO lt_local ASSIGNING <local>.
<local>-item-obj_type = &1.
<local>-item-obj_name = &2.
<local>-item-devclass = '$Z$'.
<local>-file-path = '/'.
<local>-file-filename = &3.
<local>-file-sha1 = &4.
END-OF-DEFINITION.
DEFINE _append_remote.
APPEND INITIAL LINE TO lt_remote ASSIGNING <remote>.
<remote>-path = '/'.
<remote>-filename = &1.
<remote>-sha1 = &2.
END-OF-DEFINITION.
DEFINE _append_state.
APPEND INITIAL LINE TO lt_state ASSIGNING <state>.
<state>-path = '/'.
<state>-filename = &1.
<state>-sha1 = &2.
END-OF-DEFINITION.
DEFINE _append_result.
APPEND INITIAL LINE TO lt_results ASSIGNING <result>.
<result>-obj_type = &1.
<result>-obj_name = &2.
<result>-match = &3.
<result>-lstate = &4.
<result>-rstate = &5.
<result>-package = &6.
<result>-path = &7.
<result>-filename = &8.
END-OF-DEFINITION.
* todo, should the tests be in the same include as the classes
* they are testing?
@ -1758,42 +1794,6 @@ ENDCLASS. "ltcl_file_status
CLASS ltcl_file_status IMPLEMENTATION.
DEFINE _append_local.
APPEND INITIAL LINE TO lt_local ASSIGNING <local>.
<local>-item-obj_type = &1.
<local>-item-obj_name = &2.
<local>-item-devclass = '$Z$'.
<local>-file-path = '/'.
<local>-file-filename = &3.
<local>-file-sha1 = &4.
END-OF-DEFINITION.
DEFINE _append_remote.
APPEND INITIAL LINE TO lt_remote ASSIGNING <remote>.
<remote>-path = '/'.
<remote>-filename = &1.
<remote>-sha1 = &2.
END-OF-DEFINITION.
DEFINE _append_state.
APPEND INITIAL LINE TO lt_state ASSIGNING <state>.
<state>-path = '/'.
<state>-filename = &1.
<state>-sha1 = &2.
END-OF-DEFINITION.
DEFINE _append_result.
APPEND INITIAL LINE TO lt_results_exp ASSIGNING <result>.
<result>-obj_type = &1.
<result>-obj_name = &2.
<result>-match = &3.
<result>-lstate = &4.
<result>-rstate = &5.
<result>-package = &6.
<result>-filename = &7.
<result>-path = '/'.
END-OF-DEFINITION.
METHOD calculate_status.
DATA: lt_local TYPE ty_files_item_tt,
@ -1853,24 +1853,25 @@ CLASS ltcl_file_status IMPLEMENTATION.
_append_remote 'xfeld.doma.xml' 'XFELD'. " Object from different package
_append_remote 'num01.doma.xml' 'NUM01_CHANGED'. " Changed object from different package
"EXP RESULT TYPE NAME MATCH LST RST PKG FILE
_append_result '' '' ' ' ' ' 'A' '' 'textfile.txt'.
_append_result 'CLAS' 'ZCLASS1' ' ' ' ' 'A' '$Z$' 'zclass1.clas.abap'.
_append_result 'CLAS' 'ZCLASS1' ' ' 'A' ' ' '$Z$' 'zclass1.clas.testclasses.abap'.
_append_result 'CLAS' 'ZCLASS1' 'X' ' ' ' ' '$Z$' 'zclass1.clas.xml'.
_append_result 'CLAS' 'ZCLASS2' ' ' ' ' 'A' '' 'zclass2.clas.abap'.
_append_result 'CLAS' 'ZCLASS2' ' ' ' ' 'A' '' 'zclass2.clas.xml'.
_append_result 'DOMA' 'NUM01' ' ' ' ' 'M' 'SUTI' 'num01.doma.xml'.
_append_result 'DOMA' 'XFELD' 'X' ' ' ' ' 'SUTI' 'xfeld.doma.xml'.
_append_result 'DOMA' 'ZDOMA1' 'X' ' ' ' ' '$Z$' 'zdoma1.doma.xml'.
_append_result 'DOMA' 'ZDOMA2' ' ' 'M' ' ' '$Z$' 'zdoma2.doma.xml'.
_append_result 'DOMA' 'ZDOMA3' ' ' ' ' 'M' '$Z$' 'zdoma3.doma.xml'.
_append_result 'DOMA' 'ZDOMA4' ' ' 'A' ' ' '$Z$' 'zdoma4.doma.xml'.
_append_result 'DOMA' 'ZDOMA5' ' ' ' ' 'A' '' 'zdoma5.doma.xml'.
_append_result 'DOMA' 'ZDOMA6' ' ' 'M' 'M' '$Z$' 'zdoma6.doma.xml'.
_append_result 'DOMA' 'ZDOMA7' 'X' ' ' ' ' '$Z$' 'zdoma7.doma.xml'.
_append_result 'DOMA' 'ZDOMA8' ' ' 'M' 'M' '$Z$' 'zdoma8.doma.xml'.
_append_result 'DOMA' 'ZDOMA9' ' ' 'D' ' ' '' 'zdoma9.doma.xml'.
"EXP RESULT TYPE NAME MATCH LST RST PKG PATH FILE
_append_result '' '' ' ' ' ' 'A' '' '/' 'textfile.txt'.
_append_result 'CLAS' 'ZCLASS1' ' ' ' ' 'A' '$Z$' '/' 'zclass1.clas.abap'.
_append_result 'CLAS' 'ZCLASS1' ' ' 'A' ' ' '$Z$' '/' 'zclass1.clas.testclasses.abap'.
_append_result 'CLAS' 'ZCLASS1' 'X' ' ' ' ' '$Z$' '/' 'zclass1.clas.xml'.
_append_result 'CLAS' 'ZCLASS2' ' ' ' ' 'A' '' '/' 'zclass2.clas.abap'.
_append_result 'CLAS' 'ZCLASS2' ' ' ' ' 'A' '' '/' 'zclass2.clas.xml'.
_append_result 'DOMA' 'NUM01' ' ' ' ' 'M' 'SUTI' '/' 'num01.doma.xml'.
_append_result 'DOMA' 'XFELD' 'X' ' ' ' ' 'SUTI' '/' 'xfeld.doma.xml'.
_append_result 'DOMA' 'ZDOMA1' 'X' ' ' ' ' '$Z$' '/' 'zdoma1.doma.xml'.
_append_result 'DOMA' 'ZDOMA2' ' ' 'M' ' ' '$Z$' '/' 'zdoma2.doma.xml'.
_append_result 'DOMA' 'ZDOMA3' ' ' ' ' 'M' '$Z$' '/' 'zdoma3.doma.xml'.
_append_result 'DOMA' 'ZDOMA4' ' ' 'A' ' ' '$Z$' '/' 'zdoma4.doma.xml'.
_append_result 'DOMA' 'ZDOMA5' ' ' ' ' 'A' '' '/' 'zdoma5.doma.xml'.
_append_result 'DOMA' 'ZDOMA6' ' ' 'M' 'M' '$Z$' '/' 'zdoma6.doma.xml'.
_append_result 'DOMA' 'ZDOMA7' 'X' ' ' ' ' '$Z$' '/' 'zdoma7.doma.xml'.
_append_result 'DOMA' 'ZDOMA8' ' ' 'M' 'M' '$Z$' '/' 'zdoma8.doma.xml'.
_append_result 'DOMA' 'ZDOMA9' ' ' 'D' ' ' '' '/' 'zdoma9.doma.xml'.
lt_results_exp = lt_results.
lt_results = lcl_file_status=>calculate_status(
it_local = lt_local
@ -1881,4 +1882,119 @@ CLASS ltcl_file_status IMPLEMENTATION.
ENDMETHOD. "calculate_status
ENDCLASS. "ltcl_file_status
ENDCLASS. "ltcl_file_status
CLASS ltcl_sap_package DEFINITION
FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL
INHERITING FROM CL_AUNIT_ASSERT.
PUBLIC SECTION.
METHODS check FOR TESTING.
ENDCLASS. "ltcl_sap_package
CLASS ltcl_sap_package IMPLEMENTATION.
METHOD check.
DATA: lt_results TYPE ty_results_tt,
lo_log TYPE REF TO lcl_log.
FIELD-SYMBOLS: <result> LIKE LINE OF lt_results.
*** 0 Positive
CLEAR lt_results.
CREATE OBJECT lo_log.
"EXP RESULT TYPE NAME MATCH LST RST PKG PATH FILE
_append_result 'CLAS' 'ZCLASS1' ' ' ' ' 'A' '$Z$' '/' 'zclass1.clas.abap'.
_append_result 'CLAS' 'ZCLASS1' 'X' ' ' ' ' '$Z$' '/' 'zclass1.clas.xml'.
_append_result 'DOMA' 'ZDOMA1' 'X' ' ' ' ' '$Z$' '/' 'zdoma1.doma.xml'.
_append_result 'DOMA' 'ZDOMA2' ' ' 'M' ' ' '$Z$' '/' 'zdoma2.doma.xml'.
lcl_sap_package=>check( io_log = lo_log
it_results = lt_results
iv_start = '/'
iv_top = '$Z$' ).
assert_equals( act = lo_log->count( ) exp = 0 ).
*** 1 Negative, different path for same object
CLEAR lt_results.
CREATE OBJECT lo_log.
"EXP RESULT TYPE NAME MATCH LST RST PKG PATH FILE
_append_result 'CLAS' 'ZCLASS1' ' ' ' ' 'A' '$Z$' '/' 'zclass1.clas.abap'.
_append_result 'CLAS' 'ZCLASS1' 'X' ' ' ' ' '$Z$' '/sub' 'zclass1.clas.xml'.
_append_result 'DOMA' 'ZDOMA1' 'X' ' ' ' ' '$Z$' '/' 'zdoma1.doma.xml'.
_append_result 'DOMA' 'ZDOMA2' ' ' 'M' ' ' '$Z$' '/' 'zdoma2.doma.xml'.
lcl_sap_package=>check( io_log = lo_log
it_results = lt_results
iv_start = '/'
iv_top = '$Z$' ).
" This one is not pure - incorrect path also triggers path vs package check
assert_equals( act = lo_log->count( ) exp = 2 ).
assert_equals( act = lo_log->has_rc( '1' ) exp = abap_true ).
*** 2 Negative, incorrect path vs package
CLEAR lt_results.
CREATE OBJECT lo_log.
"EXP RESULT TYPE NAME MATCH LST RST PKG PATH FILE
_append_result 'CLAS' 'ZCLASS1' ' ' ' ' 'A' '$Z$' '/' 'zclass1.clas.abap'.
_append_result 'CLAS' 'ZCLASS1' 'X' ' ' ' ' '$Z$' '/' 'zclass1.clas.xml'.
_append_result 'DOMA' 'ZDOMA1' 'X' ' ' ' ' '$Z$' '/sub' 'zdoma1.doma.xml'.
_append_result 'DOMA' 'ZDOMA2' ' ' 'M' ' ' '$Z$' '/' 'zdoma2.doma.xml'.
lcl_sap_package=>check( io_log = lo_log
it_results = lt_results
iv_start = '/'
iv_top = '$Z$' ).
assert_equals( act = lo_log->count( ) exp = 1 ).
assert_equals( act = lo_log->has_rc( '2' ) exp = abap_true ).
*** 3 Negative, similar filenames
CLEAR lt_results.
CREATE OBJECT lo_log.
"EXP RESULT TYPE NAME MATCH LST RST PKG PATH FILE
_append_result 'CLAS' 'ZCLASS1' ' ' ' ' 'A' '$Z$' '/' 'zclass1.clas.abap'.
_append_result 'CLAS' 'ZCLASS1' 'X' ' ' ' ' '$Z$' '/' 'zclass1.clas.xml'.
_append_result 'DOMA' 'ZDOMA1' 'X' ' ' ' ' '$Z$' '/' 'zdoma1.doma.xml'.
_append_result 'DOMA' 'ZDOMA2' ' ' 'M' ' ' '$Z$' '/' 'zdoma1.doma.xml'.
lcl_sap_package=>check( io_log = lo_log
it_results = lt_results
iv_start = '/'
iv_top = '$Z$' ).
assert_equals( act = lo_log->count( ) exp = 1 ).
assert_equals( act = lo_log->has_rc( '3' ) exp = abap_true ).
*** 4 Negative, empty filenames
CLEAR lt_results.
CREATE OBJECT lo_log.
"EXP RESULT TYPE NAME MATCH LST RST PKG PATH FILE
_append_result 'CLAS' 'ZCLASS1' ' ' ' ' 'A' '$Z$' '/' 'zclass1.clas.abap'.
_append_result 'CLAS' 'ZCLASS1' 'X' ' ' ' ' '$Z$' '/' 'zclass1.clas.xml'.
_append_result 'DOMA' 'ZDOMA1' 'X' ' ' ' ' '$Z$' '/' ''.
lcl_sap_package=>check( io_log = lo_log
it_results = lt_results
iv_start = '/'
iv_top = '$Z$' ).
assert_equals( act = lo_log->count( ) exp = 1 ).
assert_equals( act = lo_log->has_rc( '4' ) exp = abap_true ).
ENDMETHOD. " check.
ENDCLASS. "ltcl_sap_package

View File

@ -1012,11 +1012,16 @@ CLASS lcl_log DEFINITION FINAL.
iv_msgv1 TYPE csequence
iv_msgv2 TYPE csequence OPTIONAL
iv_msgv3 TYPE csequence OPTIONAL
iv_msgv4 TYPE csequence OPTIONAL,
iv_msgv4 TYPE csequence OPTIONAL
iv_rc TYPE balsort OPTIONAL,
count
RETURNING VALUE(rv_count) TYPE i,
to_html
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper,
clear,
has_rc "For unit tests mainly
IMPORTING iv_rc TYPE balsort
RETURNING VALUE(rv_yes) TYPE abap_bool,
show.
PRIVATE SECTION.
@ -1056,13 +1061,14 @@ CLASS lcl_log IMPLEMENTATION.
FIELD-SYMBOLS: <ls_log> LIKE LINE OF mt_log.
APPEND INITIAL LINE TO mt_log ASSIGNING <ls_log>.
<ls_log>-msgty = 'W'.
<ls_log>-msgid = '00'.
<ls_log>-msgno = '001'.
<ls_log>-msgv1 = iv_msgv1.
<ls_log>-msgv2 = iv_msgv2.
<ls_log>-msgv3 = iv_msgv3.
<ls_log>-msgv4 = iv_msgv4.
<ls_log>-msgty = 'W'.
<ls_log>-msgid = '00'.
<ls_log>-msgno = '001'.
<ls_log>-msgv1 = iv_msgv1.
<ls_log>-msgv2 = iv_msgv2.
<ls_log>-msgv3 = iv_msgv3.
<ls_log>-msgv4 = iv_msgv4.
<ls_log>-alsort = iv_rc. " Error code for unit test, not sure about better field
ENDMETHOD.
@ -1081,4 +1087,13 @@ CLASS lcl_log IMPLEMENTATION.
rv_count = lines( mt_log ).
ENDMETHOD.
METHOD clear.
CLEAR mt_log.
ENDMETHOD. " clear.
METHOD has_rc.
READ TABLE mt_log WITH KEY alsort = iv_rc TRANSPORTING NO FIELDS.
rv_yes = boolc( sy-subrc = 0 ).
ENDMETHOD. "has_rc
ENDCLASS.

View File

@ -2,252 +2,6 @@
*& Include ZABAPGIT_VIEW_REPO
*&---------------------------------------------------------------------*
CLASS lcl_repo_content_browser DEFINITION FINAL.
PUBLIC SECTION.
CONSTANTS: BEGIN OF c_sortkey,
default TYPE i VALUE 9999,
parent_dir TYPE i VALUE 0,
dir TYPE i VALUE 1,
orphan TYPE i VALUE 2,
changed TYPE i VALUE 3,
END OF c_sortkey.
TYPES: BEGIN OF ty_repo_item,
obj_type TYPE tadir-object,
obj_name TYPE tadir-obj_name,
sortkey TYPE i,
path TYPE string,
is_dir TYPE abap_bool,
changes TYPE i,
lstate TYPE char1,
rstate TYPE char1,
files TYPE tt_repo_files,
END OF ty_repo_item.
TYPES tt_repo_items TYPE STANDARD TABLE OF ty_repo_item WITH DEFAULT KEY.
METHODS constructor
IMPORTING io_repo TYPE REF TO lcl_repo.
METHODS list
IMPORTING iv_path TYPE string
iv_by_folders TYPE abap_bool
iv_changes_only TYPE abap_bool
RETURNING VALUE(rt_repo_items) TYPE tt_repo_items
RAISING lcx_exception.
METHODS get_log
RETURNING VALUE(ro_log) TYPE REF TO lcl_log.
PRIVATE SECTION.
DATA: mo_repo TYPE REF TO lcl_repo,
mo_log TYPE REF TO lcl_log.
METHODS get_local
RETURNING VALUE(rt_repo_items) TYPE tt_repo_items
RAISING lcx_exception.
METHODS get_remote
RETURNING VALUE(rt_repo_items) TYPE tt_repo_items
RAISING lcx_exception.
METHODS build_folders
IMPORTING iv_cur_dir TYPE string
CHANGING ct_repo_items TYPE tt_repo_items
RAISING lcx_exception.
METHODS filter_changes
CHANGING ct_repo_items TYPE tt_repo_items.
ENDCLASS. "lcl_repo_content_browser
DEFINE _reduce_state.
" &1 - prev, &2 - cur
IF &1 = &2 OR &2 IS INITIAL.
ASSERT 1 = 1. " No change
ELSEIF &1 IS INITIAL.
&1 = &2.
ELSE.
&1 = gc_state-mixed.
ENDIF.
END-OF-DEFINITION.
CLASS lcl_repo_content_browser IMPLEMENTATION.
METHOD constructor.
mo_repo = io_repo.
ENDMETHOD. "constructor
METHOD get_log.
ro_log = mo_log.
ENDMETHOD. "get_log
METHOD list.
* todo, create mo_log in constuctor instead?
CREATE OBJECT mo_log.
IF mo_repo->is_offline( ) = abap_true.
rt_repo_items = get_local( ).
ELSE.
rt_repo_items = get_remote( ).
ENDIF.
IF iv_by_folders = abap_true.
build_folders(
EXPORTING iv_cur_dir = iv_path
CHANGING ct_repo_items = rt_repo_items ).
ENDIF.
IF iv_changes_only = abap_true.
filter_changes( CHANGING ct_repo_items = rt_repo_items ).
ENDIF.
SORT rt_repo_items BY
sortkey ASCENDING
obj_type ASCENDING
obj_name ASCENDING.
ENDMETHOD. "list
METHOD build_folders.
DATA: lv_index TYPE i,
lt_subitems LIKE ct_repo_items,
ls_subitem LIKE LINE OF ct_repo_items,
ls_folder LIKE LINE OF ct_repo_items.
FIELD-SYMBOLS <item> LIKE LINE OF ct_repo_items.
LOOP AT ct_repo_items ASSIGNING <item>.
lv_index = sy-tabix.
CHECK <item>-path <> iv_cur_dir. " files in target dir - just leave them be
IF lcl_path=>is_subdir( iv_path = <item>-path iv_parent = iv_cur_dir ) = abap_true.
ls_subitem-changes = <item>-changes.
ls_subitem-path = <item>-path.
ls_subitem-lstate = <item>-lstate.
ls_subitem-rstate = <item>-rstate.
APPEND ls_subitem TO lt_subitems.
ENDIF.
DELETE ct_repo_items INDEX lv_index.
ENDLOOP.
SORT lt_subitems BY path ASCENDING.
LOOP AT lt_subitems ASSIGNING <item>.
AT NEW path.
CLEAR ls_folder.
ls_folder-path = <item>-path.
ls_folder-sortkey = c_sortkey-dir. " Directory
ls_folder-is_dir = abap_true.
ENDAT.
ls_folder-changes = ls_folder-changes + <item>-changes.
_reduce_state ls_folder-lstate <item>-lstate.
_reduce_state ls_folder-rstate <item>-rstate.
AT END OF path.
APPEND ls_folder TO ct_repo_items.
ENDAT.
ENDLOOP.
ENDMETHOD. "build_folders
METHOD filter_changes.
DATA lt_repo_temp LIKE ct_repo_items.
FIELD-SYMBOLS <item> LIKE LINE OF ct_repo_items.
LOOP AT ct_repo_items ASSIGNING <item>.
CHECK <item>-changes > 0.
APPEND <item> TO lt_repo_temp.
ENDLOOP.
IF lines( lt_repo_temp ) > 0. " Prevent showing empty package if no changes, show all
ct_repo_items = lt_repo_temp.
ENDIF.
ENDMETHOD. "filter_changes
METHOD get_local.
* todo, should this method be part of lcl_repo instead?
DATA: lt_tadir TYPE ty_tadir_tt.
FIELD-SYMBOLS: <ls_repo_item> LIKE LINE OF rt_repo_items,
<ls_tadir> LIKE LINE OF lt_tadir.
lt_tadir = lcl_tadir=>read( mo_repo->get_package( ) ).
LOOP AT lt_tadir ASSIGNING <ls_tadir>.
APPEND INITIAL LINE TO rt_repo_items ASSIGNING <ls_repo_item>.
<ls_repo_item>-obj_type = <ls_tadir>-object.
<ls_repo_item>-obj_name = <ls_tadir>-obj_name.
<ls_repo_item>-path = '/' && <ls_tadir>-path. " Add root anchor
<ls_repo_item>-sortkey = c_sortkey-default. " Default sort key
ENDLOOP.
ENDMETHOD. "get_local
METHOD get_remote.
* todo, name "get_remote" is misleading? it does a lot more than just fetching
* remote objects
DATA: lo_repo_online TYPE REF TO lcl_repo_online,
ls_file TYPE ty_repo_file,
lt_status TYPE ty_results_tt.
FIELD-SYMBOLS: <status> LIKE LINE OF lt_status,
<ls_repo_item> LIKE LINE OF rt_repo_items.
lo_repo_online ?= mo_repo.
lt_status = lo_repo_online->status( mo_log ).
LOOP AT lt_status ASSIGNING <status>.
AT NEW obj_name. "obj_type + obj_name
APPEND INITIAL LINE TO rt_repo_items ASSIGNING <ls_repo_item>.
<ls_repo_item>-obj_type = <status>-obj_type.
<ls_repo_item>-obj_name = <status>-obj_name.
<ls_repo_item>-sortkey = c_sortkey-default. " Default sort key
<ls_repo_item>-changes = 0.
<ls_repo_item>-path = <status>-path.
ENDAT.
IF <status>-filename IS NOT INITIAL.
ls_file-path = <status>-path.
ls_file-filename = <status>-filename.
ls_file-is_changed = boolc( <status>-match = abap_false ). " TODO refactor
ls_file-rstate = <status>-rstate.
ls_file-lstate = <status>-lstate.
APPEND ls_file TO <ls_repo_item>-files.
IF ls_file-is_changed = abap_true.
<ls_repo_item>-sortkey = c_sortkey-changed. " Changed files
<ls_repo_item>-changes = <ls_repo_item>-changes + 1.
_reduce_state <ls_repo_item>-lstate ls_file-lstate.
_reduce_state <ls_repo_item>-rstate ls_file-rstate.
ENDIF.
ENDIF.
AT END OF obj_name. "obj_type + obj_name
IF <ls_repo_item>-obj_type IS INITIAL.
<ls_repo_item>-sortkey = c_sortkey-orphan. "Virtual objects
ENDIF.
ENDAT.
ENDLOOP.
ENDMETHOD. "get_remote
ENDCLASS. "lcl_repo_content_browser
**********************************************************************
**********************************************************************
CLASS lcl_gui_view_repo_content DEFINITION FINAL INHERITING FROM lcl_gui_page_super.
PUBLIC SECTION.