CLASS zcl_abapgit_git_branch_list DEFINITION PUBLIC CREATE PUBLIC . PUBLIC SECTION. METHODS constructor IMPORTING !iv_data TYPE string RAISING zcx_abapgit_exception . METHODS find_by_name IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rs_branch) TYPE zif_abapgit_definitions=>ty_git_branch RAISING zcx_abapgit_exception . METHODS get_head_symref RETURNING VALUE(rv_head_symref) TYPE string . METHODS get_branches_only RETURNING VALUE(rt_branches) TYPE zif_abapgit_definitions=>ty_git_branch_list_tt RAISING zcx_abapgit_exception . METHODS get_tags_only " For potential future use RETURNING VALUE(rt_tags) TYPE zif_abapgit_definitions=>ty_git_branch_list_tt RAISING zcx_abapgit_exception . CLASS-METHODS get_display_name IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rv_display_name) TYPE string . CLASS-METHODS get_type IMPORTING !iv_branch_name TYPE clike !it_result TYPE stringtab OPTIONAL !iv_current_row_index TYPE sytabix OPTIONAL RETURNING VALUE(rv_type) TYPE zif_abapgit_definitions=>ty_git_branch_type . CLASS-METHODS complete_heads_branch_name IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rv_name) TYPE string . CLASS-METHODS normalize_branch_name IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rv_name) TYPE string . PROTECTED SECTION. PRIVATE SECTION. DATA mt_branches TYPE zif_abapgit_definitions=>ty_git_branch_list_tt . DATA mv_head_symref TYPE string . CLASS-METHODS skip_first_pkt IMPORTING !iv_data TYPE string RETURNING VALUE(rv_data) TYPE string . METHODS find_tag_by_name IMPORTING !iv_branch_name TYPE string RETURNING VALUE(rs_branch) TYPE zif_abapgit_definitions=>ty_git_branch RAISING zcx_abapgit_exception . CLASS-METHODS parse_branch_list IMPORTING !iv_data TYPE string EXPORTING !et_list TYPE zif_abapgit_definitions=>ty_git_branch_list_tt !ev_head_symref TYPE string RAISING zcx_abapgit_exception . CLASS-METHODS parse_head_params IMPORTING !iv_data TYPE string RETURNING VALUE(rv_head_symref) TYPE string . CLASS-METHODS is_ignored IMPORTING !iv_branch_name TYPE clike RETURNING VALUE(rv_ignore) TYPE abap_bool . ENDCLASS. CLASS ZCL_ABAPGIT_GIT_BRANCH_LIST IMPLEMENTATION. METHOD complete_heads_branch_name. IF iv_branch_name CP 'refs/heads/*'. rv_name = iv_branch_name. ELSE. rv_name = 'refs/heads/' && iv_branch_name. ENDIF. ENDMETHOD. METHOD constructor. parse_branch_list( EXPORTING iv_data = iv_data IMPORTING et_list = me->mt_branches ev_head_symref = me->mv_head_symref ). ENDMETHOD. METHOD find_by_name. IF iv_branch_name IS INITIAL. zcx_abapgit_exception=>raise( 'Branch name empty' ) ##NO_TEXT. ENDIF. IF iv_branch_name CP |refs/tags/*|. rs_branch = find_tag_by_name( iv_branch_name ). ELSE. READ TABLE mt_branches INTO rs_branch WITH KEY name = iv_branch_name. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( |Branch not found: { iv_branch_name }| ). ENDIF. ENDIF. ENDMETHOD. METHOD find_tag_by_name. DATA: lv_branch_name TYPE string. lv_branch_name = iv_branch_name && '^{}'. READ TABLE mt_branches INTO rs_branch WITH KEY name = lv_branch_name. IF sy-subrc <> 0. READ TABLE mt_branches INTO rs_branch WITH KEY name = iv_branch_name. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'Branch not found' ) ##NO_TEXT. ENDIF. ENDIF. ENDMETHOD. METHOD get_branches_only. FIELD-SYMBOLS LIKE LINE OF mt_branches. LOOP AT mt_branches ASSIGNING . IF -type = zif_abapgit_definitions=>c_git_branch_type-branch. APPEND TO rt_branches. ENDIF. ENDLOOP. ENDMETHOD. METHOD get_display_name. rv_display_name = iv_branch_name. IF rv_display_name CP 'refs/heads/*'. REPLACE FIRST OCCURRENCE OF 'refs/heads/' IN rv_display_name WITH ''. ELSEIF rv_display_name CP 'refs/tags/*'. REPLACE FIRST OCCURRENCE OF 'refs/' IN rv_display_name WITH ''. ENDIF. ENDMETHOD. METHOD get_head_symref. rv_head_symref = mv_head_symref. ENDMETHOD. METHOD get_tags_only. FIELD-SYMBOLS LIKE LINE OF mt_branches. LOOP AT mt_branches ASSIGNING WHERE type = zif_abapgit_definitions=>c_git_branch_type-lightweight_tag OR type = zif_abapgit_definitions=>c_git_branch_type-annotated_tag. APPEND TO rt_tags. ENDLOOP. ENDMETHOD. METHOD get_type. DATA: lv_annotated_tag_with_suffix TYPE string. FIELD-SYMBOLS: TYPE LINE OF stringtab. rv_type = zif_abapgit_definitions=>c_git_branch_type-other. IF iv_branch_name CP 'refs/heads/*' OR iv_branch_name = zif_abapgit_definitions=>c_head_name. rv_type = zif_abapgit_definitions=>c_git_branch_type-branch. RETURN. ENDIF. IF iv_branch_name CP 'refs/tags/*'. lv_annotated_tag_with_suffix = iv_branch_name && '^{}'. READ TABLE it_result ASSIGNING INDEX iv_current_row_index + 1. IF sy-subrc = 0 AND CP '*' && lv_annotated_tag_with_suffix. rv_type = zif_abapgit_definitions=>c_git_branch_type-annotated_tag. ELSE. rv_type = zif_abapgit_definitions=>c_git_branch_type-lightweight_tag. ENDIF. ENDIF. ENDMETHOD. METHOD is_ignored. IF iv_branch_name = 'refs/heads/gh-pages'. " Github pages rv_ignore = abap_true. ENDIF. IF iv_branch_name CP 'refs/pull/*' OR iv_branch_name CP 'refs/merge-requests/*' OR iv_branch_name CP 'refs/keep-around/*' OR iv_branch_name CP 'refs/tmp/*'. rv_ignore = abap_true. ENDIF. ENDMETHOD. METHOD normalize_branch_name. rv_name = iv_branch_name. " Force convert to string REPLACE ALL OCCURRENCES OF ` ` IN rv_name WITH '-'. " Disallow space in branch name ENDMETHOD. METHOD parse_branch_list. DATA: lt_result TYPE TABLE OF string, lv_hash TYPE zif_abapgit_definitions=>ty_sha1, lv_name TYPE string, lv_head_params TYPE string, lv_char TYPE c, lv_data LIKE LINE OF lt_result, lv_current_row_index TYPE syst-tabix. FIELD-SYMBOLS: LIKE LINE OF et_list. CLEAR: et_list, ev_head_symref. lv_data = skip_first_pkt( iv_data ). SPLIT lv_data AT zif_abapgit_definitions=>c_newline INTO TABLE lt_result. LOOP AT lt_result INTO lv_data. lv_current_row_index = sy-tabix. IF sy-tabix = 1 AND strlen( lv_data ) > 49. lv_hash = lv_data+8. lv_name = lv_data+49. lv_char = zcl_abapgit_git_utils=>get_null( ). SPLIT lv_name AT lv_char INTO lv_name lv_head_params. ev_head_symref = parse_head_params( lv_head_params ). ELSEIF sy-tabix > 1 AND strlen( lv_data ) > 45. lv_hash = lv_data+4. lv_name = lv_data+45. ELSEIF sy-tabix = 1 AND strlen( lv_data ) = 8 AND lv_data(8) = '00000000'. zcx_abapgit_exception=>raise( 'No branches, create branch manually by adding file' ) ##NO_TEXT. ELSE. CONTINUE. ENDIF. CHECK is_ignored( lv_name ) = abap_false. ASSERT lv_name IS NOT INITIAL. APPEND INITIAL LINE TO et_list ASSIGNING . -sha1 = lv_hash. -name = lv_name. -display_name = get_display_name( lv_name ). -type = get_type( iv_branch_name = lv_name it_result = lt_result iv_current_row_index = lv_current_row_index ). IF -name = zif_abapgit_definitions=>c_head_name OR -name = ev_head_symref. -is_head = abap_true. ENDIF. ENDLOOP. ENDMETHOD. METHOD parse_head_params. DATA: ls_match TYPE match_result, ls_submatch LIKE LINE OF ls_match-submatches. FIND FIRST OCCURRENCE OF REGEX '\ssymref=HEAD:([^\s]+)' IN iv_data RESULTS ls_match. READ TABLE ls_match-submatches INTO ls_submatch INDEX 1. IF sy-subrc IS INITIAL. rv_head_symref = iv_data+ls_submatch-offset(ls_submatch-length). ENDIF. ENDMETHOD. METHOD skip_first_pkt. DATA: lv_hex TYPE x LENGTH 1, lv_length TYPE i. * channel ASSERT iv_data(2) = '00'. lv_hex = to_upper( iv_data+2(2) ). lv_length = lv_hex. rv_data = iv_data+lv_length. ENDMETHOD. ENDCLASS.