mirror of
https://github.com/abapGit/abapGit.git
synced 2025-04-30 11:46:38 +08:00
550 lines
16 KiB
ABAP
550 lines
16 KiB
ABAP
CLASS zcl_abapgit_gui_page_commit DEFINITION
|
|
PUBLIC
|
|
INHERITING FROM zcl_abapgit_gui_component
|
|
FINAL
|
|
CREATE PRIVATE.
|
|
|
|
PUBLIC SECTION.
|
|
|
|
INTERFACES zif_abapgit_gui_event_handler.
|
|
INTERFACES zif_abapgit_gui_renderable.
|
|
|
|
CLASS-METHODS create
|
|
IMPORTING
|
|
!ii_repo_online TYPE REF TO zif_abapgit_repo_online
|
|
!io_stage TYPE REF TO zcl_abapgit_stage
|
|
!iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result DEFAULT zif_abapgit_definitions=>c_sci_result-no_run
|
|
RETURNING
|
|
VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable
|
|
RAISING
|
|
zcx_abapgit_exception.
|
|
METHODS constructor
|
|
IMPORTING
|
|
!ii_repo_online TYPE REF TO zif_abapgit_repo_online
|
|
!io_stage TYPE REF TO zcl_abapgit_stage
|
|
!iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result
|
|
RAISING
|
|
zcx_abapgit_exception.
|
|
|
|
PROTECTED SECTION.
|
|
PRIVATE SECTION.
|
|
|
|
CONSTANTS:
|
|
BEGIN OF c_id,
|
|
committer TYPE string VALUE 'committer',
|
|
committer_name TYPE string VALUE 'committer_name',
|
|
committer_email TYPE string VALUE 'committer_email',
|
|
message TYPE string VALUE 'message',
|
|
comment TYPE string VALUE 'comment',
|
|
body TYPE string VALUE 'body',
|
|
author TYPE string VALUE 'author',
|
|
author_name TYPE string VALUE 'author_name',
|
|
author_email TYPE string VALUE 'author_email',
|
|
new_branch_name TYPE string VALUE 'new_branch_name',
|
|
END OF c_id.
|
|
|
|
CONSTANTS:
|
|
BEGIN OF c_event,
|
|
commit TYPE string VALUE 'commit',
|
|
END OF c_event.
|
|
|
|
DATA mo_form TYPE REF TO zcl_abapgit_html_form.
|
|
DATA mo_form_data TYPE REF TO zcl_abapgit_string_map.
|
|
DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils.
|
|
DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map.
|
|
DATA mo_settings TYPE REF TO zcl_abapgit_settings.
|
|
DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online.
|
|
DATA mo_stage TYPE REF TO zcl_abapgit_stage.
|
|
DATA mt_stage TYPE zif_abapgit_definitions=>ty_stage_tt.
|
|
DATA ms_commit TYPE zif_abapgit_services_git=>ty_commit_fields.
|
|
DATA mv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result.
|
|
|
|
METHODS render_stage_summary
|
|
RETURNING
|
|
VALUE(ri_html) TYPE REF TO zif_abapgit_html
|
|
RAISING
|
|
zcx_abapgit_exception.
|
|
METHODS render_stage_details
|
|
RETURNING
|
|
VALUE(ri_html) TYPE REF TO zif_abapgit_html
|
|
RAISING
|
|
zcx_abapgit_exception.
|
|
METHODS validate_form
|
|
IMPORTING
|
|
!io_form_data TYPE REF TO zcl_abapgit_string_map
|
|
RETURNING
|
|
VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map
|
|
RAISING
|
|
zcx_abapgit_exception.
|
|
METHODS get_form_schema
|
|
RETURNING
|
|
VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form.
|
|
METHODS get_defaults
|
|
RAISING
|
|
zcx_abapgit_exception.
|
|
METHODS get_committer_name
|
|
RETURNING
|
|
VALUE(rv_user) TYPE string
|
|
RAISING
|
|
zcx_abapgit_exception.
|
|
METHODS get_committer_email
|
|
RETURNING
|
|
VALUE(rv_email) TYPE string
|
|
RAISING
|
|
zcx_abapgit_exception.
|
|
METHODS get_comment_default
|
|
RETURNING
|
|
VALUE(rv_text) TYPE string.
|
|
METHODS get_comment_object
|
|
IMPORTING
|
|
!it_stage TYPE zif_abapgit_definitions=>ty_stage_tt
|
|
RETURNING
|
|
VALUE(rv_text) TYPE string.
|
|
METHODS get_comment_file
|
|
IMPORTING
|
|
!it_stage TYPE zif_abapgit_definitions=>ty_stage_tt
|
|
RETURNING
|
|
VALUE(rv_text) TYPE string.
|
|
METHODS branch_name_to_internal
|
|
IMPORTING
|
|
iv_branch_name TYPE string
|
|
RETURNING
|
|
VALUE(rv_new_branch_name) TYPE string.
|
|
ENDCLASS.
|
|
|
|
|
|
|
|
CLASS zcl_abapgit_gui_page_commit IMPLEMENTATION.
|
|
|
|
|
|
METHOD branch_name_to_internal.
|
|
rv_new_branch_name = zcl_abapgit_git_branch_list=>complete_heads_branch_name(
|
|
zcl_abapgit_git_branch_list=>normalize_branch_name( iv_branch_name ) ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD constructor.
|
|
|
|
super->constructor( ).
|
|
|
|
mi_repo_online = ii_repo_online.
|
|
mo_stage = io_stage.
|
|
mt_stage = mo_stage->get_all( ).
|
|
mv_sci_result = iv_sci_result.
|
|
|
|
" Get settings from DB
|
|
mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ).
|
|
|
|
CREATE OBJECT mo_validation_log.
|
|
CREATE OBJECT mo_form_data.
|
|
mo_form = get_form_schema( ).
|
|
mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD create.
|
|
|
|
DATA lo_component TYPE REF TO zcl_abapgit_gui_page_commit.
|
|
|
|
CREATE OBJECT lo_component
|
|
EXPORTING
|
|
ii_repo_online = ii_repo_online
|
|
io_stage = io_stage
|
|
iv_sci_result = iv_sci_result.
|
|
|
|
ri_page = zcl_abapgit_gui_page_hoc=>create(
|
|
iv_page_title = 'Commit'
|
|
ii_child_component = lo_component ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_comment_default.
|
|
|
|
rv_text = mo_settings->get_commitmsg_comment_default( ).
|
|
|
|
IF rv_text IS INITIAL.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
REPLACE '$FILE' IN rv_text WITH get_comment_file( mt_stage ).
|
|
REPLACE '$OBJECT' IN rv_text WITH get_comment_object( mt_stage ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_comment_file.
|
|
|
|
DATA lv_count TYPE i.
|
|
|
|
FIELD-SYMBOLS <ls_stage> LIKE LINE OF it_stage.
|
|
|
|
lv_count = lines( it_stage ).
|
|
|
|
IF lv_count = 1.
|
|
" Just one file so we use the file name
|
|
READ TABLE it_stage ASSIGNING <ls_stage> INDEX 1.
|
|
ASSERT sy-subrc = 0.
|
|
|
|
rv_text = <ls_stage>-file-filename.
|
|
ELSE.
|
|
" For multiple file we use the count instead
|
|
rv_text = |{ lv_count } files|.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_comment_object.
|
|
|
|
DATA:
|
|
lv_count TYPE i,
|
|
ls_item TYPE zif_abapgit_definitions=>ty_item,
|
|
lt_items TYPE zif_abapgit_definitions=>ty_items_tt.
|
|
|
|
FIELD-SYMBOLS <ls_stage> LIKE LINE OF it_stage.
|
|
|
|
" Get objects
|
|
LOOP AT it_stage ASSIGNING <ls_stage>.
|
|
CLEAR ls_item.
|
|
ls_item-obj_type = <ls_stage>-status-obj_type.
|
|
ls_item-obj_name = <ls_stage>-status-obj_name.
|
|
COLLECT ls_item INTO lt_items.
|
|
ENDLOOP.
|
|
|
|
lv_count = lines( lt_items ).
|
|
|
|
IF lv_count = 1.
|
|
" Just one object so we use the object name
|
|
READ TABLE lt_items INTO ls_item INDEX 1.
|
|
ASSERT sy-subrc = 0.
|
|
|
|
CONCATENATE ls_item-obj_type ls_item-obj_name INTO rv_text SEPARATED BY space.
|
|
ELSE.
|
|
" For multiple objects we use the count instead
|
|
rv_text = |{ lv_count } objects|.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_committer_email.
|
|
|
|
DATA li_user TYPE REF TO zif_abapgit_persist_user.
|
|
|
|
li_user = zcl_abapgit_persistence_user=>get_instance( ).
|
|
|
|
rv_email = li_user->get_repo_git_user_email( mi_repo_online->get_url( ) ).
|
|
IF rv_email IS INITIAL.
|
|
rv_email = li_user->get_default_git_user_email( ).
|
|
ENDIF.
|
|
IF rv_email IS INITIAL.
|
|
" get default from user record
|
|
rv_email = zcl_abapgit_env_factory=>get_user_record( )->get_email( sy-uname ).
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_committer_name.
|
|
|
|
DATA li_user TYPE REF TO zif_abapgit_persist_user.
|
|
|
|
li_user = zcl_abapgit_persistence_user=>get_instance( ).
|
|
|
|
rv_user = li_user->get_repo_git_user_name( mi_repo_online->get_url( ) ).
|
|
IF rv_user IS INITIAL.
|
|
rv_user = li_user->get_default_git_user_name( ).
|
|
ENDIF.
|
|
IF rv_user IS INITIAL.
|
|
" get default from user record
|
|
rv_user = zcl_abapgit_env_factory=>get_user_record( )->get_name( sy-uname ).
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_defaults.
|
|
|
|
ms_commit-committer_name = get_committer_name( ).
|
|
ms_commit-committer_email = get_committer_email( ).
|
|
ms_commit-comment = get_comment_default( ).
|
|
|
|
" Committer
|
|
mo_form_data->set(
|
|
iv_key = c_id-committer_name
|
|
iv_val = ms_commit-committer_name ).
|
|
mo_form_data->set(
|
|
iv_key = c_id-committer_email
|
|
iv_val = ms_commit-committer_email ).
|
|
|
|
" Message
|
|
mo_form_data->set(
|
|
iv_key = c_id-comment
|
|
iv_val = ms_commit-comment ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_form_schema.
|
|
|
|
DATA lv_commitmsg_comment_length TYPE i.
|
|
CONSTANTS lc_commitmsg_comment_min_len TYPE i VALUE 1.
|
|
CONSTANTS lc_commitmsg_comment_max_len TYPE i VALUE 255.
|
|
|
|
ro_form = zcl_abapgit_html_form=>create(
|
|
iv_form_id = 'commit-form'
|
|
iv_help_page = 'https://docs.abapgit.org/guide-stage-commit.html' ).
|
|
|
|
lv_commitmsg_comment_length = mo_settings->get_commitmsg_comment_length( ).
|
|
|
|
ro_form->text(
|
|
iv_name = c_id-comment
|
|
iv_label = 'Comment'
|
|
iv_required = abap_true
|
|
iv_min = lc_commitmsg_comment_min_len
|
|
iv_max = lv_commitmsg_comment_length
|
|
iv_placeholder = |Add a mandatory comment with max { lc_commitmsg_comment_max_len } characters|
|
|
)->textarea(
|
|
iv_name = c_id-body
|
|
iv_label = 'Body'
|
|
iv_rows = 6
|
|
iv_cols = mo_settings->get_commitmsg_body_size( )
|
|
iv_placeholder = 'Add an optional description...'
|
|
)->text(
|
|
iv_name = c_id-committer_name
|
|
iv_label = 'Committer Name'
|
|
iv_required = abap_true
|
|
)->text(
|
|
iv_name = c_id-committer_email
|
|
iv_label = 'Committer Email'
|
|
iv_required = abap_true ).
|
|
|
|
IF mo_settings->get_commitmsg_hide_author( ) IS INITIAL.
|
|
ro_form->text(
|
|
iv_name = c_id-author_name
|
|
iv_label = 'Author Name'
|
|
iv_placeholder = 'Optionally, specify an author (same as committer by default)'
|
|
)->text(
|
|
iv_name = c_id-author_email
|
|
iv_label = 'Author Email' ).
|
|
ENDIF.
|
|
|
|
ro_form->text(
|
|
iv_name = c_id-new_branch_name
|
|
iv_label = 'New Branch Name'
|
|
iv_placeholder = 'Optionally, enter a new branch name for this commit'
|
|
iv_condense = abap_true ).
|
|
|
|
|
|
ro_form->command(
|
|
iv_label = 'Commit'
|
|
iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main
|
|
iv_action = c_event-commit
|
|
)->command(
|
|
iv_label = 'Back'
|
|
iv_action = zif_abapgit_definitions=>c_action-go_back ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD render_stage_details.
|
|
|
|
FIELD-SYMBOLS <ls_stage> LIKE LINE OF mt_stage.
|
|
|
|
CREATE OBJECT ri_html TYPE zcl_abapgit_html.
|
|
|
|
ri_html->add( '<table class="stage_tab">' ).
|
|
ri_html->add( '<thead>' ).
|
|
ri_html->add( '<tr>' ).
|
|
ri_html->add( '<th colspan="3">Staged Files (See <a href="#top">Summary</a> Above)</th>' ).
|
|
ri_html->add( '</tr>' ).
|
|
ri_html->add( '</thead>' ).
|
|
|
|
ri_html->add( '<tbody>' ).
|
|
LOOP AT mt_stage ASSIGNING <ls_stage>.
|
|
ri_html->add( '<tr>' ).
|
|
ri_html->add( '<td>' ).
|
|
ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state(
|
|
iv_lstate = <ls_stage>-status-lstate
|
|
iv_rstate = <ls_stage>-status-rstate ) ).
|
|
ri_html->add( '</td>' ).
|
|
ri_html->add( '<td class="method">' ).
|
|
ri_html->add( zcl_abapgit_stage=>method_description( <ls_stage>-method ) ).
|
|
ri_html->add( '</td>' ).
|
|
ri_html->add( '<td>' ).
|
|
ri_html->add( <ls_stage>-file-path && <ls_stage>-file-filename ).
|
|
ri_html->add( '</td>' ).
|
|
ri_html->add( '</tr>' ).
|
|
ENDLOOP.
|
|
ri_html->add( '</tbody>' ).
|
|
|
|
ri_html->add( '</table>' ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD render_stage_summary.
|
|
|
|
DATA:
|
|
BEGIN OF ls_sum,
|
|
method TYPE string,
|
|
count TYPE i,
|
|
END OF ls_sum,
|
|
lt_sum LIKE STANDARD TABLE OF ls_sum WITH DEFAULT KEY.
|
|
|
|
FIELD-SYMBOLS <ls_stage> LIKE LINE OF mt_stage.
|
|
|
|
CREATE OBJECT ri_html TYPE zcl_abapgit_html.
|
|
|
|
LOOP AT mt_stage ASSIGNING <ls_stage>.
|
|
ls_sum-method = <ls_stage>-method.
|
|
ls_sum-count = 1.
|
|
COLLECT ls_sum INTO lt_sum.
|
|
ENDLOOP.
|
|
|
|
ri_html->add( 'Stage Summary: ' ).
|
|
|
|
READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-add.
|
|
IF sy-subrc = 0.
|
|
ri_html->add( |<span class="diff_banner diff_ins" title="add">+ { ls_sum-count }</span>| ).
|
|
ENDIF.
|
|
READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-rm.
|
|
IF sy-subrc = 0.
|
|
ri_html->add( |<span class="diff_banner diff_del" title="remove">- { ls_sum-count }</span>| ).
|
|
ENDIF.
|
|
READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-ignore.
|
|
IF sy-subrc = 0.
|
|
ri_html->add( |<span class="diff_banner diff_upd" title="ignore">~ { ls_sum-count }</span>| ).
|
|
ENDIF.
|
|
|
|
IF lines( mt_stage ) = 1.
|
|
ri_html->add( 'file' ).
|
|
ELSE.
|
|
ri_html->add( 'files' ).
|
|
ENDIF.
|
|
|
|
ri_html->add( '(See <a href="#stage-details">Details</a> Below)' ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD validate_form.
|
|
|
|
DATA: lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt,
|
|
lv_new_branch_name TYPE string.
|
|
|
|
ro_validation_log = mo_form_util->validate( io_form_data ).
|
|
|
|
IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-committer_email ) ) = abap_false.
|
|
ro_validation_log->set(
|
|
iv_key = c_id-committer_email
|
|
iv_val = |Invalid email address| ).
|
|
ENDIF.
|
|
|
|
IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-author_email ) ) = abap_false.
|
|
ro_validation_log->set(
|
|
iv_key = c_id-author_email
|
|
iv_val = |Invalid email address| ).
|
|
ENDIF.
|
|
|
|
lv_new_branch_name = io_form_data->get( c_id-new_branch_name ).
|
|
IF lv_new_branch_name IS NOT INITIAL.
|
|
" check if branch already exists
|
|
lt_branches = zcl_abapgit_git_factory=>get_git_transport(
|
|
)->branches( mi_repo_online->get_url( )
|
|
)->get_branches_only( ).
|
|
READ TABLE lt_branches TRANSPORTING NO FIELDS WITH TABLE KEY name_key
|
|
COMPONENTS name = branch_name_to_internal( lv_new_branch_name ).
|
|
IF sy-subrc = 0.
|
|
ro_validation_log->set(
|
|
iv_key = c_id-new_branch_name
|
|
iv_val = |Branch already exists| ).
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD zif_abapgit_gui_event_handler~on_event.
|
|
DATA lv_new_branch_name TYPE string.
|
|
|
|
mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ).
|
|
|
|
CASE ii_event->mv_action.
|
|
WHEN c_event-commit.
|
|
" Validate form entries before committing
|
|
mo_validation_log = validate_form( mo_form_data ).
|
|
|
|
IF mo_validation_log->is_empty( ) = abap_true.
|
|
|
|
" new branch fields not needed in commit data
|
|
mo_form_data->strict( abap_false ).
|
|
|
|
mo_form_data->to_abap( CHANGING cs_container = ms_commit ).
|
|
|
|
REPLACE ALL OCCURRENCES
|
|
OF cl_abap_char_utilities=>cr_lf
|
|
IN ms_commit-body
|
|
WITH cl_abap_char_utilities=>newline.
|
|
|
|
lv_new_branch_name = mo_form_data->get( c_id-new_branch_name ).
|
|
" create new branch and commit to it if branch name is not empty
|
|
IF lv_new_branch_name IS NOT INITIAL.
|
|
lv_new_branch_name = branch_name_to_internal( lv_new_branch_name ).
|
|
" creates a new branch and automatically switches to it
|
|
mi_repo_online->create_branch( lv_new_branch_name ).
|
|
ENDIF.
|
|
|
|
zcl_abapgit_services_git=>commit(
|
|
is_commit = ms_commit
|
|
ii_repo_online = mi_repo_online
|
|
io_stage = mo_stage ).
|
|
|
|
|
|
MESSAGE 'Commit was successful' TYPE 'S'.
|
|
|
|
rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark.
|
|
ELSE.
|
|
rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render.
|
|
ENDIF.
|
|
WHEN OTHERS.
|
|
ASSERT 1 = 1.
|
|
ENDCASE.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD zif_abapgit_gui_renderable~render.
|
|
|
|
register_handlers( ).
|
|
|
|
IF mo_form_util->is_empty( mo_form_data ) = abap_true.
|
|
get_defaults( ).
|
|
ENDIF.
|
|
|
|
CREATE OBJECT ri_html TYPE zcl_abapgit_html.
|
|
|
|
ri_html->add( '<div class="repo">' ).
|
|
ri_html->add( '<div id="top" class="paddings">' ).
|
|
ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( mi_repo_online ) ).
|
|
ri_html->add( '</div>' ).
|
|
|
|
ri_html->add( '<div id="stage-summary" class="dialog w800px paddings">' ).
|
|
ri_html->add( render_stage_summary( ) ).
|
|
ri_html->add( '</div>' ).
|
|
|
|
ri_html->add( mo_form->render(
|
|
iv_form_class = 'w800px'
|
|
io_values = mo_form_data
|
|
io_validation_log = mo_validation_log ) ).
|
|
|
|
ri_html->add( '<div id="stage-details" class="dialog w800px">' ).
|
|
ri_html->add( render_stage_details( ) ).
|
|
ri_html->add( '</div>' ).
|
|
ri_html->add( '</div>' ).
|
|
|
|
ENDMETHOD.
|
|
ENDCLASS.
|