mirror of
https://github.com/abapGit/abapGit.git
synced 2025-05-01 04:08:27 +08:00
branch overview: compress graph
plus cleanup a few code inspector warnings
This commit is contained in:
parent
a3a5388d63
commit
b286a6c62e
|
@ -3,7 +3,7 @@ REPORT zabapgit LINE-SIZE 100.
|
||||||
* See http://www.abapgit.org
|
* See http://www.abapgit.org
|
||||||
|
|
||||||
CONSTANTS: gc_xml_version TYPE string VALUE 'v1.0.0', "#EC NOTEXT
|
CONSTANTS: gc_xml_version TYPE string VALUE 'v1.0.0', "#EC NOTEXT
|
||||||
gc_abap_version TYPE string VALUE 'v1.12.10'. "#EC NOTEXT
|
gc_abap_version TYPE string VALUE 'v1.12.11'. "#EC NOTEXT
|
||||||
|
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
|
|
|
@ -39,7 +39,7 @@ CLASS lcl_background IMPLEMENTATION.
|
||||||
lo_stage = lcl_app=>repo_srv( )->get_stage( io_repo->get_key( ) ).
|
lo_stage = lcl_app=>repo_srv( )->get_stage( io_repo->get_key( ) ).
|
||||||
|
|
||||||
LOOP AT ls_files-local ASSIGNING <ls_file>.
|
LOOP AT ls_files-local ASSIGNING <ls_file>.
|
||||||
WRITE: / 'stage', <ls_file>-file-path, <ls_file>-file-filename.
|
WRITE: / 'stage', <ls_file>-file-path, <ls_file>-file-filename ##NO_TEXT.
|
||||||
lo_stage->add( iv_path = <ls_file>-file-path
|
lo_stage->add( iv_path = <ls_file>-file-path
|
||||||
iv_filename = <ls_file>-file-filename ).
|
iv_filename = <ls_file>-file-filename ).
|
||||||
ENDLOOP.
|
ENDLOOP.
|
||||||
|
|
|
@ -567,8 +567,7 @@ CLASS lcl_git_transport IMPLEMENTATION.
|
||||||
lv_line TYPE string,
|
lv_line TYPE string,
|
||||||
lv_pack TYPE xstring,
|
lv_pack TYPE xstring,
|
||||||
lt_branches TYPE ty_branch_list_tt,
|
lt_branches TYPE ty_branch_list_tt,
|
||||||
lv_capa TYPE string,
|
lv_capa TYPE string.
|
||||||
lv_pkt1 TYPE string.
|
|
||||||
|
|
||||||
FIELD-SYMBOLS: <ls_branch> LIKE LINE OF lt_branches.
|
FIELD-SYMBOLS: <ls_branch> LIKE LINE OF lt_branches.
|
||||||
|
|
||||||
|
@ -594,7 +593,7 @@ CLASS lcl_git_transport IMPLEMENTATION.
|
||||||
|
|
||||||
LOOP AT lt_branches FROM 1 ASSIGNING <ls_branch>.
|
LOOP AT lt_branches FROM 1 ASSIGNING <ls_branch>.
|
||||||
IF sy-tabix = 1.
|
IF sy-tabix = 1.
|
||||||
lv_capa = 'side-band-64k no-progress agent=' && gv_agent.
|
lv_capa = 'side-band-64k no-progress agent=' && gv_agent ##NO_TEXT.
|
||||||
lv_line = 'want' && ` ` && <ls_branch>-sha1
|
lv_line = 'want' && ` ` && <ls_branch>-sha1
|
||||||
&& ` ` && lv_capa && gc_newline. "#EC NOTEXT
|
&& ` ` && lv_capa && gc_newline. "#EC NOTEXT
|
||||||
ELSE.
|
ELSE.
|
||||||
|
@ -872,9 +871,8 @@ CLASS lcl_git_pack IMPLEMENTATION.
|
||||||
METHOD decode_commit.
|
METHOD decode_commit.
|
||||||
|
|
||||||
DATA: lv_string TYPE string,
|
DATA: lv_string TYPE string,
|
||||||
lv_len TYPE i,
|
|
||||||
lv_word TYPE string,
|
lv_word TYPE string,
|
||||||
lv_trash TYPE string,
|
lv_trash TYPE string ##NEEDED,
|
||||||
lt_string TYPE TABLE OF string.
|
lt_string TYPE TABLE OF string.
|
||||||
|
|
||||||
FIELD-SYMBOLS: <lv_string> LIKE LINE OF lt_string.
|
FIELD-SYMBOLS: <lv_string> LIKE LINE OF lt_string.
|
||||||
|
@ -1618,8 +1616,7 @@ CLASS lcl_git_porcelain IMPLEMENTATION.
|
||||||
METHOD pull.
|
METHOD pull.
|
||||||
|
|
||||||
DATA: ls_object LIKE LINE OF et_objects,
|
DATA: ls_object LIKE LINE OF et_objects,
|
||||||
ls_commit TYPE lcl_git_pack=>ty_commit,
|
ls_commit TYPE lcl_git_pack=>ty_commit.
|
||||||
lv_pack TYPE xstring.
|
|
||||||
|
|
||||||
|
|
||||||
CLEAR et_files.
|
CLEAR et_files.
|
||||||
|
|
|
@ -332,7 +332,7 @@ CLASS lcl_object_webi IMPLEMENTATION.
|
||||||
DATA: ls_webi TYPE ty_webi,
|
DATA: ls_webi TYPE ty_webi,
|
||||||
lv_name TYPE vepname,
|
lv_name TYPE vepname,
|
||||||
ls_header LIKE LINE OF ls_webi-pvepheader,
|
ls_header LIKE LINE OF ls_webi-pvepheader,
|
||||||
lv_text TYPE string,
|
lv_text TYPE string ##NEEDED,
|
||||||
lx_root TYPE REF TO cx_root,
|
lx_root TYPE REF TO cx_root,
|
||||||
lv_exists TYPE abap_bool,
|
lv_exists TYPE abap_bool,
|
||||||
li_root TYPE REF TO if_ws_md_vif_root.
|
li_root TYPE REF TO if_ws_md_vif_root.
|
||||||
|
@ -373,7 +373,7 @@ CLASS lcl_object_webi IMPLEMENTATION.
|
||||||
CATCH cx_ws_md_exception INTO lx_root.
|
CATCH cx_ws_md_exception INTO lx_root.
|
||||||
TRY.
|
TRY.
|
||||||
mi_vi->if_ws_md_lockable_object~unlock( ).
|
mi_vi->if_ws_md_lockable_object~unlock( ).
|
||||||
CATCH cx_ws_md_exception.
|
CATCH cx_ws_md_exception ##NO_HANDLER.
|
||||||
ENDTRY.
|
ENDTRY.
|
||||||
lv_text = lx_root->if_message~get_text( ).
|
lv_text = lx_root->if_message~get_text( ).
|
||||||
_raise 'error deserializing WEBI'.
|
_raise 'error deserializing WEBI'.
|
||||||
|
|
|
@ -21,6 +21,7 @@ CLASS lcl_branch_overview DEFINITION FINAL.
|
||||||
branch TYPE string,
|
branch TYPE string,
|
||||||
merge TYPE string,
|
merge TYPE string,
|
||||||
create TYPE STANDARD TABLE OF ty_create WITH DEFAULT KEY,
|
create TYPE STANDARD TABLE OF ty_create WITH DEFAULT KEY,
|
||||||
|
compressed TYPE abap_bool,
|
||||||
END OF ty_commit.
|
END OF ty_commit.
|
||||||
|
|
||||||
TYPES: ty_commit_tt TYPE STANDARD TABLE OF ty_commit WITH DEFAULT KEY.
|
TYPES: ty_commit_tt TYPE STANDARD TABLE OF ty_commit WITH DEFAULT KEY.
|
||||||
|
@ -30,6 +31,11 @@ CLASS lcl_branch_overview DEFINITION FINAL.
|
||||||
RETURNING VALUE(rt_commits) TYPE ty_commit_tt
|
RETURNING VALUE(rt_commits) TYPE ty_commit_tt
|
||||||
RAISING lcx_exception.
|
RAISING lcx_exception.
|
||||||
|
|
||||||
|
CLASS-METHODS: compress
|
||||||
|
IMPORTING it_commits TYPE ty_commit_tt
|
||||||
|
RETURNING VALUE(rt_commits) TYPE ty_commit_tt
|
||||||
|
RAISING lcx_exception.
|
||||||
|
|
||||||
PRIVATE SECTION.
|
PRIVATE SECTION.
|
||||||
|
|
||||||
CLASS-METHODS:
|
CLASS-METHODS:
|
||||||
|
@ -55,6 +61,67 @@ ENDCLASS.
|
||||||
|
|
||||||
CLASS lcl_branch_overview IMPLEMENTATION.
|
CLASS lcl_branch_overview IMPLEMENTATION.
|
||||||
|
|
||||||
|
METHOD compress.
|
||||||
|
|
||||||
|
DATA: lv_previous TYPE i,
|
||||||
|
lv_index TYPE i,
|
||||||
|
lv_name TYPE string,
|
||||||
|
lt_temp LIKE it_commits.
|
||||||
|
|
||||||
|
FIELD-SYMBOLS: <ls_branch> LIKE LINE OF gt_branches,
|
||||||
|
<ls_new> LIKE LINE OF rt_commits,
|
||||||
|
<ls_temp> LIKE LINE OF lt_temp,
|
||||||
|
<ls_commit> LIKE LINE OF it_commits.
|
||||||
|
|
||||||
|
DEFINE _compress.
|
||||||
|
IF lines( lt_temp ) >= 10.
|
||||||
|
READ TABLE lt_temp ASSIGNING <ls_temp> INDEX 1.
|
||||||
|
ASSERT sy-subrc = 0.
|
||||||
|
APPEND INITIAL LINE TO rt_commits ASSIGNING <ls_new>.
|
||||||
|
<ls_new>-time = <ls_temp>-time.
|
||||||
|
<ls_new>-message = |Compressed, { lines( lt_temp ) } commits|.
|
||||||
|
<ls_new>-branch = lv_name.
|
||||||
|
<ls_new>-compressed = abap_true.
|
||||||
|
ELSE.
|
||||||
|
APPEND LINES OF lt_temp TO rt_commits.
|
||||||
|
ENDIF.
|
||||||
|
END-OF-DEFINITION.
|
||||||
|
|
||||||
|
|
||||||
|
LOOP AT gt_branches ASSIGNING <ls_branch>.
|
||||||
|
|
||||||
|
CLEAR lt_temp.
|
||||||
|
lv_name = <ls_branch>-name+11.
|
||||||
|
|
||||||
|
LOOP AT it_commits ASSIGNING <ls_commit>
|
||||||
|
WHERE branch = lv_name.
|
||||||
|
lv_index = sy-tabix.
|
||||||
|
|
||||||
|
IF NOT <ls_commit>-merge IS INITIAL
|
||||||
|
OR NOT <ls_commit>-create IS INITIAL.
|
||||||
|
* always show these vertices
|
||||||
|
lv_previous = -1.
|
||||||
|
ENDIF.
|
||||||
|
|
||||||
|
IF lv_previous + 1 <> sy-tabix.
|
||||||
|
_compress.
|
||||||
|
CLEAR lt_temp.
|
||||||
|
ENDIF.
|
||||||
|
|
||||||
|
lv_previous = lv_index.
|
||||||
|
|
||||||
|
APPEND <ls_commit> TO lt_temp.
|
||||||
|
|
||||||
|
ENDLOOP.
|
||||||
|
|
||||||
|
_compress.
|
||||||
|
|
||||||
|
ENDLOOP.
|
||||||
|
|
||||||
|
SORT rt_commits BY time ASCENDING.
|
||||||
|
|
||||||
|
ENDMETHOD.
|
||||||
|
|
||||||
METHOD run.
|
METHOD run.
|
||||||
|
|
||||||
DATA: lt_objects TYPE ty_objects_tt.
|
DATA: lt_objects TYPE ty_objects_tt.
|
||||||
|
@ -89,9 +156,9 @@ CLASS lcl_branch_overview IMPLEMENTATION.
|
||||||
|
|
||||||
gt_branches = lcl_git_transport=>branches( io_repo->get_url( ) ).
|
gt_branches = lcl_git_transport=>branches( io_repo->get_url( ) ).
|
||||||
|
|
||||||
DELETE gt_branches WHERE name = 'refs/heads/gh-pages'.
|
DELETE gt_branches WHERE name = 'refs/heads/gh-pages' ##NO_TEXT.
|
||||||
DELETE gt_branches WHERE name CP 'refs/tags/*'.
|
DELETE gt_branches WHERE name CP 'refs/tags/*' ##NO_TEXT.
|
||||||
DELETE gt_branches WHERE name CP 'refs/pull/*'.
|
DELETE gt_branches WHERE name CP 'refs/pull/*' ##NO_TEXT.
|
||||||
|
|
||||||
lcl_git_transport=>upload_pack( EXPORTING io_repo = io_repo
|
lcl_git_transport=>upload_pack( EXPORTING io_repo = io_repo
|
||||||
iv_deepen = abap_false
|
iv_deepen = abap_false
|
||||||
|
@ -105,7 +172,7 @@ CLASS lcl_branch_overview IMPLEMENTATION.
|
||||||
METHOD parse_commits.
|
METHOD parse_commits.
|
||||||
|
|
||||||
DATA: ls_commit LIKE LINE OF gt_commits,
|
DATA: ls_commit LIKE LINE OF gt_commits,
|
||||||
lv_trash TYPE string,
|
lv_trash TYPE string ##NEEDED,
|
||||||
ls_raw TYPE lcl_git_pack=>ty_commit.
|
ls_raw TYPE lcl_git_pack=>ty_commit.
|
||||||
|
|
||||||
FIELD-SYMBOLS: <ls_object> LIKE LINE OF it_objects.
|
FIELD-SYMBOLS: <ls_object> LIKE LINE OF it_objects.
|
||||||
|
@ -237,15 +304,25 @@ CLASS lcl_gui_page_branch_overview DEFINITION FINAL INHERITING FROM lcl_gui_page
|
||||||
METHODS:
|
METHODS:
|
||||||
constructor
|
constructor
|
||||||
IMPORTING io_repo TYPE REF TO lcl_repo_online,
|
IMPORTING io_repo TYPE REF TO lcl_repo_online,
|
||||||
|
lif_gui_page~on_event REDEFINITION,
|
||||||
lif_gui_page~render REDEFINITION.
|
lif_gui_page~render REDEFINITION.
|
||||||
|
|
||||||
PRIVATE SECTION.
|
PRIVATE SECTION.
|
||||||
DATA: mo_repo TYPE REF TO lcl_repo_online.
|
DATA: mo_repo TYPE REF TO lcl_repo_online,
|
||||||
|
mv_compress TYPE abap_bool VALUE abap_false.
|
||||||
|
|
||||||
|
CONSTANTS: BEGIN OF c_actions,
|
||||||
|
uncompress TYPE string VALUE 'uncompress' ##NO_TEXT,
|
||||||
|
compress TYPE string VALUE 'compress' ##NO_TEXT,
|
||||||
|
refresh TYPE string VALUE 'refresh' ##NO_TEXT,
|
||||||
|
END OF c_actions.
|
||||||
|
|
||||||
METHODS:
|
METHODS:
|
||||||
body
|
body
|
||||||
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
|
RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper
|
||||||
RAISING lcx_exception,
|
RAISING lcx_exception,
|
||||||
|
build_menu
|
||||||
|
RETURNING VALUE(ro_menu) TYPE REF TO lcl_html_toolbar,
|
||||||
escape_branch
|
escape_branch
|
||||||
IMPORTING iv_string TYPE string
|
IMPORTING iv_string TYPE string
|
||||||
RETURNING VALUE(rv_string) TYPE string,
|
RETURNING VALUE(rv_string) TYPE string,
|
||||||
|
@ -306,7 +383,7 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
|
||||||
|
|
||||||
CREATE OBJECT ro_html.
|
CREATE OBJECT ro_html.
|
||||||
|
|
||||||
ro_html->add( |Repository: { mo_repo->get_url( ) }| ).
|
ro_html->add( |Repository: { mo_repo->get_url( ) }<br>| ).
|
||||||
|
|
||||||
* see http://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-element
|
* see http://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-element
|
||||||
_add '<canvas id="gitGraph"></canvas>'.
|
_add '<canvas id="gitGraph"></canvas>'.
|
||||||
|
@ -325,7 +402,7 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
|
||||||
|
|
||||||
_add 'var myTemplateConfig = {'.
|
_add 'var myTemplateConfig = {'.
|
||||||
ro_html->add( 'colors: [ "#979797", "#008fb5", "#f1c109", "'
|
ro_html->add( 'colors: [ "#979797", "#008fb5", "#f1c109", "'
|
||||||
&& '#095256", "#087F8C", "#5AAA95", "#86A873", "#BB9F06" ],' ).
|
&& '#095256", "#087F8C", "#5AAA95", "#86A873", "#BB9F06" ],' ) ##NO_TEXT.
|
||||||
_add 'branch: {'.
|
_add 'branch: {'.
|
||||||
_add ' lineWidth: 8,'.
|
_add ' lineWidth: 8,'.
|
||||||
_add ' spacingX: 50'.
|
_add ' spacingX: 50'.
|
||||||
|
@ -342,6 +419,9 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
|
||||||
_add '});'.
|
_add '});'.
|
||||||
|
|
||||||
lt_commits = lcl_branch_overview=>run( mo_repo ).
|
lt_commits = lcl_branch_overview=>run( mo_repo ).
|
||||||
|
IF mv_compress = abap_true.
|
||||||
|
lt_commits = lcl_branch_overview=>compress( lt_commits ).
|
||||||
|
ENDIF.
|
||||||
|
|
||||||
* todo: limit number of commits shown, or squash commits?
|
* todo: limit number of commits shown, or squash commits?
|
||||||
LOOP AT lt_commits ASSIGNING <ls_commit>.
|
LOOP AT lt_commits ASSIGNING <ls_commit>.
|
||||||
|
@ -352,7 +432,11 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
|
||||||
<ls_commit>-branch }");| ).
|
<ls_commit>-branch }");| ).
|
||||||
ENDIF.
|
ENDIF.
|
||||||
|
|
||||||
IF <ls_commit>-merge IS INITIAL.
|
IF <ls_commit>-compressed = abap_true.
|
||||||
|
ro_html->add( |{ escape_branch( <ls_commit>-branch ) }.commit(\{message: "{
|
||||||
|
escape_message( <ls_commit>-message )
|
||||||
|
}", dotColor: "black", dotSize: 15, messageHashDisplay: false, messageAuthorDisplay: false\});| ).
|
||||||
|
ELSEIF <ls_commit>-merge IS INITIAL.
|
||||||
ro_html->add( |{ escape_branch( <ls_commit>-branch ) }.commit(\{message: "{
|
ro_html->add( |{ escape_branch( <ls_commit>-branch ) }.commit(\{message: "{
|
||||||
escape_message( <ls_commit>-message ) }", author: "{
|
escape_message( <ls_commit>-message ) }", author: "{
|
||||||
<ls_commit>-author }", sha1: "{
|
<ls_commit>-author }", sha1: "{
|
||||||
|
@ -395,12 +479,45 @@ CLASS lcl_gui_page_branch_overview IMPLEMENTATION.
|
||||||
|
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
|
|
||||||
|
METHOD build_menu.
|
||||||
|
|
||||||
|
CREATE OBJECT ro_menu.
|
||||||
|
|
||||||
|
IF mv_compress = abap_true.
|
||||||
|
ro_menu->add(
|
||||||
|
iv_txt = 'Uncompress Graph'
|
||||||
|
iv_act = c_actions-uncompress ) ##NO_TEXT.
|
||||||
|
ELSE.
|
||||||
|
ro_menu->add(
|
||||||
|
iv_txt = 'Compress Graph'
|
||||||
|
iv_act = c_actions-compress ) ##NO_TEXT.
|
||||||
|
ENDIF.
|
||||||
|
|
||||||
|
ro_menu->add( iv_txt = 'Refresh' iv_act = c_actions-refresh ) ##NO_TEXT.
|
||||||
|
|
||||||
|
ENDMETHOD.
|
||||||
|
|
||||||
|
METHOD lif_gui_page~on_event.
|
||||||
|
|
||||||
|
CASE iv_action.
|
||||||
|
WHEN c_actions-refresh.
|
||||||
|
rv_state = gc_event_state-re_render.
|
||||||
|
WHEN c_actions-uncompress.
|
||||||
|
mv_compress = abap_false.
|
||||||
|
rv_state = gc_event_state-re_render.
|
||||||
|
WHEN c_actions-compress.
|
||||||
|
mv_compress = abap_true.
|
||||||
|
rv_state = gc_event_state-re_render.
|
||||||
|
ENDCASE.
|
||||||
|
|
||||||
|
ENDMETHOD.
|
||||||
|
|
||||||
METHOD lif_gui_page~render.
|
METHOD lif_gui_page~render.
|
||||||
|
|
||||||
CREATE OBJECT ro_html.
|
CREATE OBJECT ro_html.
|
||||||
|
|
||||||
ro_html->add( header( ) ).
|
ro_html->add( header( ) ).
|
||||||
ro_html->add( title( 'BRANCH_OVERVIEW' ) ).
|
ro_html->add( title( iv_title = 'BRANCH_OVERVIEW' io_menu = build_menu( ) ) ).
|
||||||
_add '<div id="toc">'.
|
_add '<div id="toc">'.
|
||||||
ro_html->add( body( ) ).
|
ro_html->add( body( ) ).
|
||||||
_add '</div>'.
|
_add '</div>'.
|
||||||
|
|
|
@ -61,8 +61,6 @@ CLASS ltcl_dangerous DEFINITION FOR TESTING RISK LEVEL CRITICAL DURATION LONG FI
|
||||||
|
|
||||||
METHODS:
|
METHODS:
|
||||||
run FOR TESTING
|
run FOR TESTING
|
||||||
RAISING lcx_exception,
|
|
||||||
check_empty_package
|
|
||||||
RAISING lcx_exception.
|
RAISING lcx_exception.
|
||||||
|
|
||||||
CONSTANTS: c_package TYPE devclass VALUE '$ABAPGIT_UNIT_TEST'.
|
CONSTANTS: c_package TYPE devclass VALUE '$ABAPGIT_UNIT_TEST'.
|
||||||
|
@ -101,18 +99,6 @@ CLASS ltcl_dangerous IMPLEMENTATION.
|
||||||
|
|
||||||
ENDMETHOD. "class_setup
|
ENDMETHOD. "class_setup
|
||||||
|
|
||||||
METHOD check_empty_package.
|
|
||||||
|
|
||||||
DATA: lt_tadir TYPE ty_tadir_tt.
|
|
||||||
|
|
||||||
|
|
||||||
lt_tadir = lcl_tadir=>read( c_package ).
|
|
||||||
IF lines( lt_tadir ) > 0.
|
|
||||||
cl_abap_unit_assert=>fail( 'Prerequsite: package should be empty' ).
|
|
||||||
ENDIF.
|
|
||||||
|
|
||||||
ENDMETHOD. "check_empty_package
|
|
||||||
|
|
||||||
METHOD run.
|
METHOD run.
|
||||||
|
|
||||||
DATA: lo_repo TYPE REF TO lcl_repo_online,
|
DATA: lo_repo TYPE REF TO lcl_repo_online,
|
||||||
|
@ -762,7 +748,8 @@ CLASS ltcl_object_types IMPLEMENTATION.
|
||||||
|
|
||||||
ENDCLASS. "ltcl_object_types IMPLEMENTATION
|
ENDCLASS. "ltcl_object_types IMPLEMENTATION
|
||||||
|
|
||||||
CLASS ltcl_git_pack_decode_commit DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL.
|
CLASS ltcl_git_pack_decode_commit DEFINITION FOR TESTING
|
||||||
|
RISK LEVEL HARMLESS DURATION SHORT FINAL.
|
||||||
|
|
||||||
PUBLIC SECTION.
|
PUBLIC SECTION.
|
||||||
METHODS:
|
METHODS:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user