From 5c2cac3211b54c59ac55415120eb70c86851e1e2 Mon Sep 17 00:00:00 2001 From: larshp Date: Sat, 2 Jul 2016 11:26:42 +0000 Subject: [PATCH] moving to includes whoa this is a lot of work --- src/zabapgit.prog.abap | 5532 ++-------------------------- src/zabapgit.prog.xml | 2 +- src/zabapgit_dot_abapgit.prog.abap | 208 ++ src/zabapgit_dot_abapgit.prog.xml | 48 + src/zabapgit_file_status.prog.abap | 190 + src/zabapgit_file_status.prog.xml | 48 + src/zabapgit_git.prog.abap | 1773 +++++++++ src/zabapgit_git.prog.xml | 48 + src/zabapgit_html.prog.abap | 543 +++ src/zabapgit_html.prog.xml | 48 + src/zabapgit_persistence.prog.abap | 1682 +++++++++ src/zabapgit_persistence.prog.xml | 48 + src/zabapgit_repo.prog.abap | 213 ++ src/zabapgit_repo.prog.xml | 48 + src/zabapgit_stage.prog.abap | 96 + src/zabapgit_stage.prog.xml | 48 + src/zabapgit_unit_test.prog.abap | 16 +- src/zabapgit_util.prog.abap | 107 + 18 files changed, 5537 insertions(+), 5161 deletions(-) create mode 100644 src/zabapgit_dot_abapgit.prog.abap create mode 100644 src/zabapgit_dot_abapgit.prog.xml create mode 100644 src/zabapgit_file_status.prog.abap create mode 100644 src/zabapgit_file_status.prog.xml create mode 100644 src/zabapgit_git.prog.abap create mode 100644 src/zabapgit_git.prog.xml create mode 100644 src/zabapgit_html.prog.abap create mode 100644 src/zabapgit_html.prog.xml create mode 100644 src/zabapgit_persistence.prog.abap create mode 100644 src/zabapgit_persistence.prog.xml create mode 100644 src/zabapgit_repo.prog.abap create mode 100644 src/zabapgit_repo.prog.xml create mode 100644 src/zabapgit_stage.prog.abap create mode 100644 src/zabapgit_stage.prog.xml diff --git a/src/zabapgit.prog.abap b/src/zabapgit.prog.abap index 0d432450c..6654ddb56 100644 --- a/src/zabapgit.prog.abap +++ b/src/zabapgit.prog.abap @@ -90,6 +90,23 @@ CONSTANTS: BEGIN OF gc_type, TYPES: ty_chmod TYPE c LENGTH 6. +TYPES: BEGIN OF ty_object, + sha1 TYPE ty_sha1, + type TYPE ty_type, + data TYPE xstring, + END OF ty_object. +TYPES: ty_objects_tt TYPE STANDARD TABLE OF ty_object WITH DEFAULT KEY. + +TYPES: BEGIN OF ty_result, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + match TYPE sap_bool, + filename TYPE string, + package TYPE devclass, + path TYPE string, + END OF ty_result. +TYPES: ty_results_tt TYPE STANDARD TABLE OF ty_result WITH DEFAULT KEY. + CONSTANTS: BEGIN OF gc_chmod, file TYPE ty_chmod VALUE '100644', executable TYPE ty_chmod VALUE '100755', @@ -144,381 +161,304 @@ INCLUDE zabapgit_zlib. INCLUDE zabapgit_util. INCLUDE zabapgit_xml. -CLASS lcl_app DEFINITION DEFERRED. +CLASS lcl_gui DEFINITION DEFERRED. +CLASS lcl_persistence_user DEFINITION DEFERRED. +CLASS lcl_repo_srv DEFINITION DEFERRED. +CLASS lcl_persistence_db DEFINITION DEFERRED. + +*----------------------------------------------------------------------* +* CLASS lcl_app DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_app DEFINITION FINAL. + PUBLIC SECTION. + + CLASS-METHODS run + RAISING lcx_exception. + + CLASS-METHODS gui + RETURNING VALUE(ro_gui) TYPE REF TO lcl_gui + RAISING lcx_exception. + + CLASS-METHODS user + IMPORTING iv_user TYPE xubname DEFAULT sy-uname + RETURNING VALUE(ro_user) TYPE REF TO lcl_persistence_user + RAISING lcx_exception. + + CLASS-METHODS repo_srv + RETURNING VALUE(ro_repo_srv) TYPE REF TO lcl_repo_srv. + + CLASS-METHODS db + RETURNING VALUE(ro_db) TYPE REF TO lcl_persistence_db. + + PRIVATE SECTION. + CLASS-DATA: go_gui TYPE REF TO lcl_gui, + go_current_user TYPE REF TO lcl_persistence_user, + go_db TYPE REF TO lcl_persistence_db, + go_repo_srv TYPE REF TO lcl_repo_srv. + +ENDCLASS. "lcl_app + +INCLUDE zabapgit_persistence. +INCLUDE zabapgit_html. +INCLUDE zabapgit_dot_abapgit. +CLASS lcl_log DEFINITION DEFERRED. +CLASS lcl_repo_online DEFINITION DEFERRED. +*CLASS lcl_git_pack DEFINITION DEFERRED. + +*----------------------------------------------------------------------* +* CLASS lcl_stage DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_stage DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_repo_srv. + + PUBLIC SECTION. + TYPES: ty_method TYPE c LENGTH 1. + + CONSTANTS: BEGIN OF c_method, + add TYPE ty_method VALUE 'A', + rm TYPE ty_method VALUE 'R', + ignore TYPE ty_method VALUE 'I', + END OF c_method. + + CONSTANTS: BEGIN OF c_wftype, + local TYPE char1 VALUE 'L', + remote TYPE char1 VALUE 'R', + END OF c_wftype. + + TYPES: BEGIN OF ty_stage, + file TYPE ty_file, + method TYPE ty_method, + END OF ty_stage. + + TYPES: ty_stage_tt TYPE SORTED TABLE OF ty_stage + WITH UNIQUE KEY file-path file-filename. + + TYPES: BEGIN OF ty_work_file, + type TYPE char1, + file TYPE ty_file, + END OF ty_work_file. + + DATA mv_repo_key TYPE lcl_persistence_db=>ty_value READ-ONLY. + DATA mv_local_cnt TYPE i READ-ONLY. + DATA mt_workarea TYPE STANDARD TABLE OF ty_work_file READ-ONLY. + + CLASS-METHODS method_description + IMPORTING iv_method TYPE ty_method + RETURNING VALUE(rv_description) TYPE string + RAISING lcx_exception. + + METHODS constructor + IMPORTING iv_repo_key TYPE lcl_persistence_db=>ty_value + RAISING lcx_exception. + + METHODS update_and_add_dot_abapgit + IMPORTING iv_data TYPE ty_file-data + RAISING lcx_exception. + + METHODS: + add + IMPORTING iv_path TYPE ty_file-path + iv_filename TYPE ty_file-filename + RAISING lcx_exception, + reset + IMPORTING iv_path TYPE ty_file-path + iv_filename TYPE ty_file-filename + RAISING lcx_exception, + rm + IMPORTING iv_path TYPE ty_file-path + iv_filename TYPE ty_file-filename + RAISING lcx_exception, + ignore + IMPORTING iv_path TYPE ty_file-path + iv_filename TYPE ty_file-filename + RAISING lcx_exception, + lookup + IMPORTING iv_path TYPE ty_file-path + iv_filename TYPE ty_file-filename + RETURNING VALUE(rv_method) TYPE ty_method, + count + RETURNING VALUE(rv_count) TYPE i, + get_all + RETURNING VALUE(rt_stage) TYPE ty_stage_tt. + + PRIVATE SECTION. + DATA: mt_stage TYPE ty_stage_tt. + + METHODS append + IMPORTING iv_path TYPE ty_file-path + iv_filename TYPE ty_file-filename + iv_method TYPE ty_method + RAISING lcx_exception. + + METHODS find_work_file + IMPORTING iv_path TYPE ty_file-path + iv_filename TYPE ty_file-filename + RETURNING VALUE(rs_file) TYPE ty_file + RAISING lcx_exception. + +ENDCLASS. "lcl_stage DEFINITION + + +INCLUDE zabapgit_repo. +INCLUDE zabapgit_stage. + +CLASS lcl_stage IMPLEMENTATION. + + METHOD constructor. + DATA: ls_files TYPE lcl_stage_logic=>ty_stage_files, + lo_repo TYPE REF TO lcl_repo_online, + ls_work_file LIKE LINE OF mt_workarea. + + FIELD-SYMBOLS: LIKE LINE OF ls_files-local, + LIKE LINE OF ls_files-remote. + + mv_repo_key = iv_repo_key. + lo_repo ?= lcl_app=>repo_srv( )->get( iv_repo_key ). + ls_files = lcl_stage_logic=>get( lo_repo ). + + " Unify structures + LOOP AT ls_files-local ASSIGNING . + ls_work_file-type = c_wftype-local. + ls_work_file-file = -file. + APPEND ls_work_file TO mt_workarea. + mv_local_cnt = mv_local_cnt + 1. + ENDLOOP. + + LOOP AT ls_files-remote ASSIGNING . + ls_work_file-type = c_wftype-remote. + ls_work_file-file = . + APPEND ls_work_file TO mt_workarea. + ENDLOOP. + + ENDMETHOD. "constructor + + METHOD lookup. + DATA ls_stage LIKE LINE OF mt_stage. + + READ TABLE mt_stage INTO ls_stage + WITH KEY file-path = iv_path + file-filename = iv_filename. + IF sy-subrc = 0. + rv_method = ls_stage-method. + ENDIF. + + ENDMETHOD. "lookup + + METHOD get_all. + rt_stage = mt_stage. + ENDMETHOD. "get_all + + METHOD append. + + DATA: ls_stage LIKE LINE OF mt_stage, + ls_file TYPE ty_file. + + FIELD-SYMBOLS: LIKE LINE OF mt_stage. + + ls_file = find_work_file( iv_path = iv_path iv_filename = iv_filename ). + + READ TABLE mt_stage WITH KEY + file-path = ls_file-path + file-filename = ls_file-filename + ASSIGNING . + IF sy-subrc = 0. + -file-data = ls_file-data. + -method = iv_method. + ELSE. + ls_stage-file = ls_file. + ls_stage-method = iv_method. + INSERT ls_stage INTO TABLE mt_stage. + ENDIF. + + ENDMETHOD. "append + + METHOD method_description. + + CASE iv_method. + WHEN c_method-add. + rv_description = 'add'. + WHEN c_method-rm. + rv_description = 'rm'. + WHEN c_method-ignore. + rv_description = 'ignore' ##NO_TEXT. + WHEN OTHERS. + _raise 'unknown staging method type'. + ENDCASE. + + ENDMETHOD. "method_description + + METHOD add. + append( iv_path = iv_path + iv_filename = iv_filename + iv_method = c_method-add ). + ENDMETHOD. "add + + METHOD reset. + DELETE mt_stage WHERE file-path = iv_path + AND file-filename = iv_filename. + ASSERT sy-subrc = 0. + ENDMETHOD. "reset + + METHOD rm. + append( iv_path = iv_path + iv_filename = iv_filename + iv_method = c_method-rm ). + ENDMETHOD. "rm + + METHOD ignore. + append( iv_path = iv_path + iv_filename = iv_filename + iv_method = c_method-ignore ). + ENDMETHOD. "ignore + + METHOD count. + rv_count = lines( mt_stage ). + ENDMETHOD. "count + + METHOD find_work_file. + DATA ls_work_file LIKE LINE OF mt_workarea. + + READ TABLE mt_workarea INTO ls_work_file + WITH KEY file-path = iv_path + file-filename = iv_filename. + IF sy-subrc = 0. + rs_file = ls_work_file-file. + ELSE. + _raise 'File not found in workarea'. + ENDIF. + + ENDMETHOD. "check_work_file_exists + + METHOD update_and_add_dot_abapgit. + + FIELD-SYMBOLS LIKE LINE OF mt_workarea. + + READ TABLE mt_workarea ASSIGNING + WITH KEY file-path = gc_root_dir + file-filename = gc_dot_abapgit. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO mt_workarea ASSIGNING . + -type = c_wftype-local. + -file-path = gc_root_dir. + -file-filename = gc_dot_abapgit. + ENDIF. + + -file-data = iv_data. + + add( iv_path = gc_root_dir + iv_filename = gc_dot_abapgit ). + + ENDMETHOD. "update_and_add_dot_abapgit + +ENDCLASS. + +INCLUDE zabapgit_git. + + START-OF-SELECTION. PERFORM run. -CLASS lcl_progress DEFINITION FINAL. - - PUBLIC SECTION. - CLASS-METHODS: - show - IMPORTING - iv_key TYPE string - VALUE(iv_current) TYPE i - iv_total TYPE i - iv_text TYPE csequence. - - PRIVATE SECTION. - TYPES: BEGIN OF ty_stack, - key TYPE string, - current TYPE i, - total TYPE i, - text TYPE string, - END OF ty_stack. - - CLASS-DATA: - gt_stack TYPE STANDARD TABLE OF ty_stack WITH DEFAULT KEY. - - CLASS-METHODS: - calc_pct - RETURNING VALUE(rv_pct) TYPE i, - build_text - RETURNING VALUE(rv_text) TYPE string. - -ENDCLASS. - -CLASS lcl_progress IMPLEMENTATION. - - METHOD show. - - DATA: lv_pct TYPE i, - lv_text TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF gt_stack. - -* assumption: -* all callers must end with calling this method with iv_current = iv_total -* to clear the progress of that sub element - ASSERT lines( gt_stack ) < 10. - - READ TABLE gt_stack INDEX lines( gt_stack ) ASSIGNING . - IF sy-subrc <> 0 OR -key <> iv_key. - APPEND INITIAL LINE TO gt_stack ASSIGNING . - ENDIF. - -key = iv_key. - -current = iv_current. - -total = iv_total. - -text = iv_text. - - lv_pct = calc_pct( ). - lv_text = build_text( ). - - CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR' - EXPORTING - percentage = lv_pct - text = lv_text. - - IF iv_current = iv_total. - DELETE gt_stack INDEX lines( gt_stack ). - ENDIF. - - ENDMETHOD. - - METHOD build_text. - - FIELD-SYMBOLS: LIKE LINE OF gt_stack. - - - LOOP AT gt_stack ASSIGNING . - IF sy-tabix = 1. - rv_text = |{ -key } { -text }|. - ELSE. - rv_text = |{ rv_text } - { -key } { -text }|. - - IF -current <> 1 AND -total <> 1. - rv_text = |{ rv_text } ({ -current }/{ -total })|. - ENDIF. - ENDIF. - ENDLOOP. - - ENDMETHOD. - - METHOD calc_pct. - - DATA: lv_f TYPE f. - - FIELD-SYMBOLS: LIKE LINE OF gt_stack. - - - READ TABLE gt_stack ASSIGNING INDEX 1. - ASSERT sy-subrc = 0. - - lv_f = ( -current / -total ) * 100. - rv_pct = lv_f. - - IF rv_pct = 100. - rv_pct = 99. - ENDIF. - - ENDMETHOD. - -ENDCLASS. - -*----------------------------------------------------------------------* -* CLASS lcl_html_helper DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_html_helper DEFINITION FINAL. - PUBLIC SECTION. - CONSTANTS: c_indent_size TYPE i VALUE 2. - - DATA mv_html TYPE string READ-ONLY. - DATA mv_indent TYPE i READ-ONLY. - - METHODS add IMPORTING iv_chunk TYPE any. - METHODS reset. - - METHODS add_anchor IMPORTING iv_txt TYPE string - iv_act TYPE string - iv_opt TYPE char1 OPTIONAL - iv_typ TYPE char1 DEFAULT gc_action_type-sapevent - iv_class TYPE string OPTIONAL. - - PRIVATE SECTION. - METHODS _add_str IMPORTING iv_str TYPE csequence. - METHODS _add_htm IMPORTING io_html TYPE REF TO lcl_html_helper. - -ENDCLASS. "lcl_html_helper DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_html_helper IMPLEMENTATION -*----------------------------------------------------------------------* -CLASS lcl_html_helper IMPLEMENTATION. - METHOD add. - DATA lo_type TYPE REF TO cl_abap_typedescr. - DATA lo_html TYPE REF TO lcl_html_helper. - - lo_type = cl_abap_typedescr=>describe_by_data( iv_chunk ). - - CASE lo_type->type_kind. - WHEN cl_abap_typedescr=>typekind_char - OR cl_abap_typedescr=>typekind_string. - IF strlen( iv_chunk ) = 0. - RETURN. - ENDIF. - _add_str( iv_chunk ). - WHEN cl_abap_typedescr=>typekind_oref. - ASSERT iv_chunk IS BOUND. " Dev mistake - TRY. - lo_html ?= iv_chunk. - CATCH cx_sy_move_cast_error. - ASSERT 1 = 0. " Dev mistake - ENDTRY. - _add_htm( lo_html ). - WHEN OTHERS. - ASSERT 1 = 0. " Dev mistake - ENDCASE. - - ENDMETHOD. " add - - METHOD reset. - CLEAR: me->mv_html, me->mv_indent. - ENDMETHOD. "reset - - METHOD _add_str. - CONSTANTS lc_single_tags_re TYPE string " HTML5 singleton tags - VALUE '<(area|base|br|col|command|embed|hr|img|input|link|meta|param|source|!)'. - - DATA lv_tags TYPE i. - DATA lv_tags_open TYPE i. - DATA lv_tags_close TYPE i. - DATA lv_tags_single TYPE i. - DATA lv_close_offs TYPE i. - DATA lv_shift_back TYPE i. - - FIND FIRST OCCURRENCE OF ' 0. " Found close tag @beginning - lv_shift_back = 1. - ENDIF. - - mv_html = mv_html - && repeat( val = ` ` occ = ( mv_indent - lv_shift_back ) * c_indent_size ) - && iv_str - && gc_newline. - - FIND ALL OCCURRENCES OF '<' IN iv_str MATCH COUNT lv_tags. - FIND ALL OCCURRENCES OF '' - IF lv_tags_open > lv_tags_close. - mv_indent = mv_indent + 1. - ELSEIF lv_tags_open < lv_tags_close AND mv_indent > 0. - mv_indent = mv_indent - 1. - ENDIF. - - ENDMETHOD. "_add_str - - METHOD _add_htm. - - DATA lt_strtab TYPE TABLE OF string. - DATA lv_str TYPE string. - - SPLIT io_html->mv_html AT gc_newline INTO TABLE lt_strtab. - LOOP AT lt_strtab INTO lv_str. - SHIFT lv_str LEFT DELETING LEADING space. - _add_str( lv_str ). - ENDLOOP. - - ENDMETHOD. "_add_htm - - METHOD add_anchor. - DATA: lv_class TYPE string, - lv_href TYPE string. - - lv_class = iv_class. - - IF iv_opt = gc_html_opt-emphas. - lv_class = lv_class && ' emphasis' ##NO_TEXT. - ENDIF. - IF iv_opt = gc_html_opt-cancel. - lv_class = lv_class && ' attention' ##NO_TEXT. - ENDIF. - IF lv_class IS NOT INITIAL. - SHIFT lv_class LEFT DELETING LEADING space. - lv_class = | class="{ lv_class }"|. - ENDIF. - - IF iv_act IS NOT INITIAL. - CASE iv_typ. - WHEN gc_action_type-url. - lv_href = | href="{ iv_act }"|. - WHEN gc_action_type-sapevent. - lv_href = | href="sapevent:{ iv_act }"|. - WHEN gc_action_type-onclick. - lv_href = | onclick="{ iv_act }"|. - WHEN OTHERS. - ENDCASE. - ENDIF. - - _add_str( |{ iv_txt }| ). - - ENDMETHOD. "add_action - -ENDCLASS. "lcl_html_helper IMPLEMENTATION - -*----------------------------------------------------------------------* -* CLASS lcl_html_toolbar DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_html_toolbar DEFINITION FINAL. - PUBLIC SECTION. - METHODS add IMPORTING iv_txt TYPE string - io_sub TYPE REF TO lcl_html_toolbar OPTIONAL - iv_act TYPE string OPTIONAL - iv_opt TYPE c OPTIONAL - iv_typ TYPE c DEFAULT gc_action_type-sapevent. - - METHODS render IMPORTING iv_as_droplist_with_label TYPE string OPTIONAL - iv_no_separator TYPE abap_bool OPTIONAL - iv_vertical TYPE abap_bool OPTIONAL - RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. - - METHODS reset. - - PRIVATE SECTION. - TYPES: BEGIN OF ty_item, - txt TYPE string, - act TYPE string, - sub TYPE REF TO lcl_html_toolbar, - opt TYPE char1, - typ TYPE char1, - END OF ty_item. - TYPES: tt_items TYPE STANDARD TABLE OF ty_item. - - DATA mt_items TYPE tt_items. - -ENDCLASS. "lcl_html_toolbar DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_html_toolbar IMPLEMENTATION -*----------------------------------------------------------------------* -CLASS lcl_html_toolbar IMPLEMENTATION. - - METHOD reset. - CLEAR mt_items. - ENDMETHOD. "reset - - METHOD add. - DATA ls_item TYPE ty_item. - - ASSERT iv_act IS INITIAL AND io_sub IS NOT INITIAL - OR iv_act IS NOT INITIAL AND io_sub IS INITIAL. " Only one supplied - - ls_item-txt = iv_txt. - ls_item-act = iv_act. - ls_item-sub = io_sub. - ls_item-opt = iv_opt. - ls_item-typ = iv_typ. - APPEND ls_item TO mt_items. - ENDMETHOD. "add - - METHOD render. - DATA: - lv_class TYPE string, - lv_last TYPE abap_bool. - - FIELD-SYMBOLS LIKE LINE OF mt_items. - - CREATE OBJECT ro_html. - - IF iv_as_droplist_with_label IS INITIAL. - IF iv_vertical = abap_true. - lv_class = 'menu_vertical' ##NO_TEXT. - ELSE. - lv_class = 'menu' ##NO_TEXT. - ENDIF. - ELSE. - lv_class = 'dropdown' ##NO_TEXT. - ENDIF. - - ro_html->add( |
| ). - - IF iv_as_droplist_with_label IS NOT INITIAL. - lv_class = 'dropbtn'. - IF iv_no_separator = abap_true. - lv_class = lv_class && ' menu_end' ##NO_TEXT. - ENDIF. - ro_html->add( |{ iv_as_droplist_with_label }| ). - ro_html->add( '' ). - ENDIF. - - ro_html->add( '
' ). - - ENDMETHOD. "render - -ENDCLASS. "lcl_html_toolbar IMPLEMENTATION - *----------------------------------------------------------------------* * CLASS lcl_tadir DEFINITION *----------------------------------------------------------------------* @@ -563,533 +503,7 @@ CLASS lcl_tadir DEFINITION FINAL. ENDCLASS. "lcl_tadir DEFINITION -CLASS lcl_persistence_migrate DEFINITION FINAL. - PUBLIC SECTION. - CLASS-METHODS: run RAISING lcx_exception. - - PRIVATE SECTION. - CONSTANTS: - c_text TYPE string VALUE 'Generated by abapGit' ##NO_TEXT. - - CLASS-METHODS: - migrate_repo RAISING lcx_exception, - migrate_user RAISING lcx_exception, - table_create RAISING lcx_exception, - table_exists - RETURNING VALUE(rv_exists) TYPE abap_bool, - lock_create RAISING lcx_exception, - lock_exists - RETURNING VALUE(rv_exists) TYPE abap_bool. - -ENDCLASS. - -*----------------------------------------------------------------------* -* CLASS lcl_user DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_user DEFINITION FINAL FRIENDS lcl_persistence_migrate. - -* this class is obsolete, use LCL_PERSISTENCE_USER instead - - PRIVATE SECTION. - TYPES: BEGIN OF ty_user, - user LIKE sy-uname, - username TYPE string, - email TYPE string, - END OF ty_user. - - TYPES: ty_user_tt TYPE STANDARD TABLE OF ty_user WITH DEFAULT KEY. - - CLASS-METHODS set_username - IMPORTING iv_user TYPE xubname DEFAULT sy-uname - iv_username TYPE string - RAISING lcx_exception. - - CLASS-METHODS get_username - IMPORTING iv_user TYPE xubname DEFAULT sy-uname - RETURNING VALUE(rv_username) TYPE string - RAISING lcx_exception. - - CLASS-METHODS set_email - IMPORTING iv_user TYPE xubname DEFAULT sy-uname - iv_email TYPE string - RAISING lcx_exception. - - CLASS-METHODS get_email - IMPORTING iv_user TYPE xubname DEFAULT sy-uname - RETURNING VALUE(rv_email) TYPE string - RAISING lcx_exception. - - CLASS-METHODS list - RETURNING VALUE(rt_data) TYPE ty_user_tt - RAISING lcx_exception. - - CLASS-METHODS read - IMPORTING iv_name TYPE tdobname - RETURNING VALUE(rv_value) TYPE string - RAISING lcx_exception. - - CLASS-METHODS save - IMPORTING iv_name TYPE tdobname - iv_value TYPE string - RAISING lcx_exception. - -ENDCLASS. "lcl_user DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_user IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_user IMPLEMENTATION. - -* this class is obsolete, use LCL_PERSISTENCE_USER instead - - METHOD read. - - DATA: lt_lines TYPE TABLE OF tline, - ls_line LIKE LINE OF lt_lines. - - - CALL FUNCTION 'READ_TEXT' - EXPORTING - id = 'ST' - language = gc_english - name = iv_name - object = 'TEXT' - TABLES - lines = lt_lines - EXCEPTIONS - id = 1 - language = 2 - name = 3 - not_found = 4 - object = 5 - reference_check = 6 - wrong_access_to_archive = 7 - OTHERS = 8. - IF sy-subrc <> 4 AND sy-subrc <> 0. - _raise 'error from READ_TEXT'. - ENDIF. - - READ TABLE lt_lines INTO ls_line INDEX 1. - IF sy-subrc = 0. - rv_value = ls_line-tdline. - ENDIF. - - ENDMETHOD. "get_details - - METHOD save. - - DATA: ls_header TYPE thead, - lt_lines TYPE TABLE OF tline, - ls_line LIKE LINE OF lt_lines. - - - ls_line-tdformat = '*'. - ls_line-tdline = iv_value. - APPEND ls_line TO lt_lines. - - ls_header-tdid = 'ST'. - ls_header-tdspras = gc_english. - ls_header-tdname = iv_name. - ls_header-tdobject = 'TEXT'. - - CALL FUNCTION 'SAVE_TEXT' - EXPORTING - header = ls_header - TABLES - lines = lt_lines - EXCEPTIONS - id = 1 - language = 2 - name = 3 - object = 4 - OTHERS = 5. - IF sy-subrc <> 0. - ROLLBACK WORK. "#EC CI_ROLLBACK - _raise 'error from SAVE_TEXT'. - ENDIF. - - COMMIT WORK. - - ENDMETHOD. "change - - METHOD set_username. - - DATA: lv_name TYPE tdobname. - - - CONCATENATE 'ZABAPGIT_USERNAME_' iv_user INTO lv_name. - - save( iv_name = lv_name - iv_value = iv_username ). - - ENDMETHOD. "set_username - - METHOD get_username. - - DATA: lv_name TYPE tdobname. - - - CONCATENATE 'ZABAPGIT_USERNAME_' iv_user INTO lv_name. - - rv_username = read( lv_name ). - - ENDMETHOD. "get_username - - METHOD set_email. - - DATA: lv_name TYPE tdobname. - - - CONCATENATE 'ZABAPGIT_EMAIL_' iv_user INTO lv_name. - - save( iv_name = lv_name - iv_value = iv_email ). - - ENDMETHOD. "set_email - - METHOD list. - - DATA: lt_stxh TYPE STANDARD TABLE OF stxh WITH DEFAULT KEY. - - FIELD-SYMBOLS: LIKE LINE OF rt_data, - LIKE LINE OF lt_stxh. - - - SELECT * FROM stxh INTO TABLE lt_stxh - WHERE tdobject = 'TEXT' - AND tdname LIKE 'ZABAPGIT_USERNAME_%'. - - LOOP AT lt_stxh ASSIGNING . - APPEND INITIAL LINE TO rt_data ASSIGNING . - - -user = -tdname+18. - -username = get_username( -user ). - -email = get_email( -user ). - ENDLOOP. - - ENDMETHOD. - - METHOD get_email. - - DATA: lv_name TYPE tdobname. - - - CONCATENATE 'ZABAPGIT_EMAIL_' iv_user INTO lv_name. - - rv_email = read( lv_name ). - - ENDMETHOD. "get_email - -ENDCLASS. "lcl_user IMPLEMENTATION - -CLASS ltcl_dot_abapgit DEFINITION DEFERRED. - -CLASS lcl_dot_abapgit DEFINITION CREATE PRIVATE FINAL FRIENDS ltcl_dot_abapgit. - - PUBLIC SECTION. - CLASS-METHODS: - build_default - IMPORTING iv_master_language TYPE spras - RETURNING VALUE(ro_dot_abapgit) TYPE REF TO lcl_dot_abapgit, - deserialize - IMPORTING iv_xstr TYPE xstring - RETURNING VALUE(ro_dot_abapgit) TYPE REF TO lcl_dot_abapgit - RAISING lcx_exception. - - METHODS: - serialize - RETURNING VALUE(rv_xstr) TYPE xstring, - add_ignore - IMPORTING iv_path TYPE string - iv_filename TYPE string, - is_ignored - IMPORTING iv_path TYPE string - iv_filename TYPE string - RETURNING VALUE(rv_ignored) TYPE abap_bool, - remove_ignore - IMPORTING iv_path TYPE string - iv_filename TYPE string, - get_starting_folder - RETURNING VALUE(rv_path) TYPE string, -* set_starting_folder -* IMPORTING iv_path TYPE string, - get_master_language - RETURNING VALUE(rv_language) TYPE spras. -* set_master_language -* IMPORTING iv_language TYPE spras. - - PRIVATE SECTION. - TYPES: BEGIN OF ty_dot_abapgit, - master_language TYPE spras, - starting_folder TYPE string, - ignore TYPE STANDARD TABLE OF string WITH DEFAULT KEY, - END OF ty_dot_abapgit. - - DATA: ms_data TYPE ty_dot_abapgit. - - METHODS: - constructor - IMPORTING is_data TYPE ty_dot_abapgit. - - CLASS-METHODS: - to_xml - IMPORTING is_data TYPE ty_dot_abapgit - RETURNING VALUE(rv_xml) TYPE string, - from_xml - IMPORTING iv_xml TYPE string - RETURNING VALUE(rs_data) TYPE ty_dot_abapgit. - -ENDCLASS. - -CLASS lcl_dot_abapgit IMPLEMENTATION. - - METHOD constructor. - ms_data = is_data. - ENDMETHOD. - - METHOD deserialize. - - DATA: lv_xml TYPE string, - ls_data TYPE ty_dot_abapgit. - - - lv_xml = lcl_convert=>xstring_to_string_utf8( iv_xstr ). - - ls_data = from_xml( lv_xml ). - - CREATE OBJECT ro_dot_abapgit - EXPORTING - is_data = ls_data. - - ENDMETHOD. - - METHOD serialize. - - DATA: lv_xml TYPE string. - - lv_xml = to_xml( ms_data ). - - rv_xstr = lcl_convert=>string_to_xstring_utf8( lv_xml ). - - ENDMETHOD. - - METHOD build_default. - - DATA: ls_data TYPE ty_dot_abapgit. - - - ls_data-master_language = iv_master_language. - ls_data-starting_folder = '/'. - APPEND '/.gitignore' TO ls_data-ignore. - APPEND '/LICENSE' TO ls_data-ignore. - APPEND '/README.md' TO ls_data-ignore. - APPEND '/package.json' TO ls_data-ignore. - APPEND '/.travis.yml' TO ls_data-ignore. - - CREATE OBJECT ro_dot_abapgit - EXPORTING - is_data = ls_data. - - ENDMETHOD. - - METHOD to_xml. - CALL TRANSFORMATION id - SOURCE data = is_data - RESULT XML rv_xml. - - rv_xml = lcl_xml_pretty=>print( rv_xml ). - - REPLACE FIRST OCCURRENCE - OF '' - IN rv_xml - WITH ''. - ASSERT sy-subrc = 0. - ENDMETHOD. - - METHOD from_xml. - - DATA: lv_xml TYPE string. - - lv_xml = iv_xml. - -* fix downward compatibility - REPLACE ALL OCCURRENCES OF '<_--28C_DATA_--29>' IN lv_xml WITH ''. - REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. - - CALL TRANSFORMATION id - OPTIONS value_handling = 'accept_data_loss' - SOURCE XML lv_xml - RESULT data = rs_data ##NO_TEXT. - ENDMETHOD. - - METHOD add_ignore. - - DATA: lv_name TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF ms_data-ignore. - - - lv_name = iv_path && iv_filename. - - READ TABLE ms_data-ignore FROM lv_name TRANSPORTING NO FIELDS. - IF sy-subrc = 0. - RETURN. - ENDIF. - - APPEND INITIAL LINE TO ms_data-ignore ASSIGNING . - = lv_name. - - ENDMETHOD. - - METHOD is_ignored. - - DATA: lv_name TYPE string, - lv_ignore TYPE string. - - - lv_name = iv_path && iv_filename. - - LOOP AT ms_data-ignore INTO lv_ignore. - IF lv_name CP lv_ignore. - rv_ignored = abap_true. - RETURN. - ENDIF. - ENDLOOP. - - ENDMETHOD. - - METHOD remove_ignore. - - DATA: lv_name TYPE string. - - - lv_name = iv_path && iv_filename. - - DELETE TABLE ms_data-ignore FROM lv_name. - - ENDMETHOD. - - METHOD get_starting_folder. - rv_path = ms_data-starting_folder. - ENDMETHOD. - -* METHOD set_starting_folder. -* ms_data-starting_folder = iv_path. -* ENDMETHOD. - - METHOD get_master_language. - rv_language = ms_data-master_language. - ENDMETHOD. - -* METHOD set_master_language. -* ms_data-master_language = iv_language. -* ENDMETHOD. - -ENDCLASS. - -CLASS ltcl_git_pack DEFINITION DEFERRED. - -*----------------------------------------------------------------------* -* CLASS lcl_pack DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_git_pack DEFINITION FINAL FRIENDS ltcl_git_pack. - - PUBLIC SECTION. - TYPES: BEGIN OF ty_node, - chmod TYPE ty_chmod, - name TYPE string, - sha1 TYPE ty_sha1, - END OF ty_node. - TYPES: ty_nodes_tt TYPE STANDARD TABLE OF ty_node WITH DEFAULT KEY. - - TYPES: BEGIN OF ty_object, - sha1 TYPE ty_sha1, - type TYPE ty_type, - data TYPE xstring, - END OF ty_object. - TYPES: ty_objects_tt TYPE STANDARD TABLE OF ty_object WITH DEFAULT KEY. - - TYPES: BEGIN OF ty_commit, - tree TYPE ty_sha1, - parent TYPE ty_sha1, - author TYPE string, - committer TYPE string, - body TYPE string, - END OF ty_commit. - - CLASS-METHODS decode - IMPORTING iv_data TYPE xstring - RETURNING VALUE(rt_objects) TYPE ty_objects_tt - RAISING lcx_exception. - - CLASS-METHODS decode_tree - IMPORTING iv_data TYPE xstring - RETURNING VALUE(rt_nodes) TYPE ty_nodes_tt - RAISING lcx_exception. - - CLASS-METHODS decode_deltas - CHANGING ct_objects TYPE ty_objects_tt - RAISING lcx_exception. - - CLASS-METHODS decode_commit - IMPORTING iv_data TYPE xstring - RETURNING VALUE(rs_commit) TYPE ty_commit - RAISING lcx_exception. - - CLASS-METHODS encode - IMPORTING it_objects TYPE ty_objects_tt - RETURNING VALUE(rv_data) TYPE xstring - RAISING lcx_exception. - - CLASS-METHODS encode_tree - IMPORTING it_nodes TYPE ty_nodes_tt - RETURNING VALUE(rv_data) TYPE xstring. - - CLASS-METHODS encode_commit - IMPORTING is_commit TYPE ty_commit - RETURNING VALUE(rv_data) TYPE xstring. - - PRIVATE SECTION. - CONSTANTS: c_pack_start TYPE x LENGTH 4 VALUE '5041434B', " PACK - c_zlib TYPE x LENGTH 2 VALUE '789C', - c_zlib_hmm TYPE x LENGTH 2 VALUE '7801', - c_version TYPE x LENGTH 4 VALUE '00000002'. - - CLASS-METHODS type_and_length - IMPORTING is_object TYPE ty_object - RETURNING VALUE(rv_xstring) TYPE xstring - RAISING lcx_exception. - - CLASS-METHODS delta - IMPORTING is_object TYPE ty_object - CHANGING ct_objects TYPE ty_objects_tt - RAISING lcx_exception. - - CLASS-METHODS delta_header - EXPORTING ev_header TYPE i - CHANGING cv_delta TYPE xstring. - - CLASS-METHODS sort_tree - IMPORTING it_nodes TYPE ty_nodes_tt - RETURNING VALUE(rt_nodes) TYPE ty_nodes_tt. - - CLASS-METHODS get_type - IMPORTING iv_x TYPE x - RETURNING VALUE(rv_type) TYPE ty_type - RAISING lcx_exception. - - CLASS-METHODS get_length - EXPORTING ev_length TYPE i - CHANGING cv_data TYPE xstring. - -ENDCLASS. "lcl_pack DEFINITION *----------------------------------------------------------------------* * CLASS lcl_objects_activation DEFINITION @@ -11848,442 +11262,6 @@ CLASS lcl_object_shi3 IMPLEMENTATION. ENDCLASS. "lcl_object_shi3 IMPLEMENTATION -CLASS lcl_persistence_db DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. - - PUBLIC SECTION. - CONSTANTS: - c_tabname TYPE tabname VALUE 'ZABAPGIT', - c_lock TYPE viewname VALUE 'EZABAPGIT'. - - TYPES: ty_type TYPE c LENGTH 12. - TYPES: ty_value TYPE c LENGTH 12. - - TYPES: BEGIN OF ty_content, - type TYPE ty_type, - value TYPE ty_value, - data_str TYPE string, - END OF ty_content, - tt_content TYPE SORTED TABLE OF ty_content WITH UNIQUE KEY type value. - - METHODS list_by_type - IMPORTING iv_type TYPE ty_type - RETURNING VALUE(rt_content) TYPE tt_content. - - METHODS list - RETURNING VALUE(rt_content) TYPE tt_content. - - METHODS add - IMPORTING iv_type TYPE ty_type - iv_value TYPE ty_content-value - iv_data TYPE ty_content-data_str - RAISING lcx_exception. - - METHODS delete - IMPORTING iv_type TYPE ty_type - iv_value TYPE ty_content-value - RAISING lcx_exception. - - METHODS update - IMPORTING iv_type TYPE ty_type - iv_value TYPE ty_content-value - iv_data TYPE ty_content-data_str - RAISING lcx_exception. - - METHODS modify - IMPORTING iv_type TYPE ty_type - iv_value TYPE ty_content-value - iv_data TYPE ty_content-data_str - RAISING lcx_exception. - - METHODS read - IMPORTING iv_type TYPE ty_type - iv_value TYPE ty_content-value - RETURNING VALUE(rv_data) TYPE ty_content-data_str - RAISING lcx_not_found. - - METHODS lock - IMPORTING iv_mode TYPE enqmode DEFAULT 'E' - iv_type TYPE ty_type - iv_value TYPE ty_content-value - RAISING lcx_exception. - -ENDCLASS. - -CLASS lcl_persistence_repo DEFINITION FINAL. - - PUBLIC SECTION. - TYPES: BEGIN OF ty_local_checksum, - item TYPE ty_item, - sha1 TYPE ty_sha1, - END OF ty_local_checksum. - - TYPES: ty_local_checksum_tt TYPE STANDARD TABLE OF ty_local_checksum WITH DEFAULT KEY. - - TYPES: BEGIN OF ty_repo_xml, - url TYPE string, - branch_name TYPE string, - sha1 TYPE ty_sha1, - package TYPE devclass, - offline TYPE sap_bool, - local_checksums TYPE ty_local_checksum_tt, - master_language TYPE spras, - END OF ty_repo_xml. - - TYPES: BEGIN OF ty_repo, - key TYPE lcl_persistence_db=>ty_value. - INCLUDE TYPE ty_repo_xml. - TYPES: END OF ty_repo. - TYPES: tt_repo TYPE STANDARD TABLE OF ty_repo WITH DEFAULT KEY. - - METHODS constructor. - - METHODS list - RETURNING VALUE(rt_repos) TYPE tt_repo - RAISING lcx_exception. - - METHODS update_sha1 - IMPORTING iv_key TYPE ty_repo-key - iv_branch_sha1 TYPE ty_repo_xml-sha1 - RAISING lcx_exception. - - METHODS update_local_checksums - IMPORTING iv_key TYPE ty_repo-key - it_checksums TYPE ty_repo_xml-local_checksums - RAISING lcx_exception. - - METHODS update_url - IMPORTING iv_key TYPE ty_repo-key - iv_url TYPE ty_repo_xml-url - RAISING lcx_exception. - - METHODS update_branch_name - IMPORTING iv_key TYPE ty_repo-key - iv_branch_name TYPE ty_repo_xml-branch_name - RAISING lcx_exception. - - METHODS add - IMPORTING iv_url TYPE string - iv_branch_name TYPE string - iv_branch TYPE ty_sha1 OPTIONAL - iv_package TYPE devclass - iv_offline TYPE sap_bool DEFAULT abap_false - RETURNING VALUE(rv_key) TYPE ty_repo-key - RAISING lcx_exception. - - METHODS delete - IMPORTING iv_key TYPE ty_repo-key - RAISING lcx_exception. - - METHODS read - IMPORTING iv_key TYPE ty_repo-key - RETURNING VALUE(rs_repo) TYPE ty_repo - RAISING lcx_exception - lcx_not_found. - - METHODS lock - IMPORTING iv_mode TYPE enqmode - iv_key TYPE ty_repo-key - RAISING lcx_exception. - - PRIVATE SECTION. - CONSTANTS c_type_repo TYPE lcl_persistence_db=>ty_type VALUE 'REPO'. - - DATA: mo_db TYPE REF TO lcl_persistence_db. - - METHODS from_xml - IMPORTING iv_repo_xml_string TYPE string - RETURNING VALUE(rs_repo) TYPE ty_repo_xml - RAISING lcx_exception. - - METHODS to_xml - IMPORTING is_repo TYPE ty_repo - RETURNING VALUE(rv_repo_xml_string) TYPE string. - - METHODS get_next_id - RETURNING VALUE(rv_next_repo_id) TYPE lcl_persistence_db=>ty_content-value - RAISING lcx_exception. - -ENDCLASS. - - -*----------------------------------------------------------------------* -* CLASS lcl_html_action_utils DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_html_action_utils DEFINITION FINAL. - PUBLIC SECTION. - - TYPES: BEGIN OF ty_commit_fields, "TODO refactor ! Move to normal place - repo_key TYPE lcl_persistence_repo=>ty_repo-key, - username TYPE string, - email TYPE string, - comment TYPE string, - body TYPE string, - END OF ty_commit_fields. - - CLASS-METHODS jump_encode - IMPORTING iv_obj_type TYPE tadir-object - iv_obj_name TYPE tadir-obj_name - RETURNING VALUE(rv_string) TYPE string. - - CLASS-METHODS jump_decode - IMPORTING iv_string TYPE clike - EXPORTING ev_obj_type TYPE tadir-object - ev_obj_name TYPE tadir-obj_name - RAISING lcx_exception. - - CLASS-METHODS file_encode - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - ig_file TYPE any "ty_repo_file - RETURNING VALUE(rv_string) TYPE string. - - CLASS-METHODS file_decode - IMPORTING iv_string TYPE clike - EXPORTING ev_key TYPE lcl_persistence_repo=>ty_repo-key - eg_file TYPE any "ty_repo_file - RAISING lcx_exception. - - CLASS-METHODS dbkey_encode - IMPORTING is_key TYPE lcl_persistence_db=>ty_content - RETURNING VALUE(rv_string) TYPE string. - - CLASS-METHODS dbkey_decode - IMPORTING iv_string TYPE clike - RETURNING VALUE(rs_key) TYPE lcl_persistence_db=>ty_content. - - CLASS-METHODS parse_commit_request - IMPORTING it_postdata TYPE cnht_post_data_tab - RETURNING VALUE(rs_fields) TYPE ty_commit_fields. - - CLASS-METHODS repo_key_encode - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RETURNING VALUE(rv_string) TYPE string. - - CLASS-METHODS repo_key_decode - IMPORTING iv_string TYPE clike - RETURNING VALUE(rv_key) TYPE lcl_persistence_repo=>ty_repo-key. - -ENDCLASS. "lcl_html_action_utils DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_html_action_utils IMPLEMENTATION -*----------------------------------------------------------------------* -CLASS lcl_html_action_utils IMPLEMENTATION. - - METHOD jump_encode. - - DATA: lt_fields TYPE tihttpnvp, - ls_field LIKE LINE OF lt_fields. - - - ls_field-name = 'TYPE'. - ls_field-value = iv_obj_type. - APPEND ls_field TO lt_fields. - - ls_field-name = 'NAME'. - ls_field-value = iv_obj_name. - APPEND ls_field TO lt_fields. - - rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). - - ENDMETHOD. "jump_encode - - METHOD jump_decode. - - DATA: lt_fields TYPE tihttpnvp, - lv_string TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields. - - - lv_string = iv_string. " type conversion - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'TYPE'. - IF sy-subrc = 0. - ev_obj_type = -value. - ELSE. - CLEAR ev_obj_type. - ENDIF. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'NAME'. - IF sy-subrc = 0. - ev_obj_name = -value. - ELSE. - CLEAR ev_obj_name. - ENDIF. - - ENDMETHOD. "jump_decode - - METHOD file_encode. - - DATA: lt_fields TYPE tihttpnvp, - ls_field LIKE LINE OF lt_fields. - - FIELD-SYMBOLS TYPE string. - - ls_field-name = 'KEY'. - ls_field-value = iv_key. - APPEND ls_field TO lt_fields. - - ls_field-name = 'PATH'. - ASSIGN COMPONENT ls_field-name OF STRUCTURE ig_file TO . - ASSERT IS ASSIGNED. - ls_field-value = . - APPEND ls_field TO lt_fields. - - ls_field-name = 'FILENAME'. - ASSIGN COMPONENT ls_field-name OF STRUCTURE ig_file TO . - ASSERT IS ASSIGNED. - ls_field-value = . - APPEND ls_field TO lt_fields. - - rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). - - ENDMETHOD. "file_encode - - METHOD file_decode. - - DATA: lt_fields TYPE tihttpnvp, - lv_string TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields, - TYPE string. - - CLEAR: ev_key, eg_file. - lv_string = iv_string. " type conversion - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'KEY'. - IF sy-subrc = 0. - ev_key = -value. - ENDIF. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'PATH'. - IF sy-subrc = 0. - ASSIGN COMPONENT 'PATH' OF STRUCTURE eg_file TO . - ASSERT IS ASSIGNED. - = -value. - ENDIF. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'FILENAME'. - IF sy-subrc = 0. - ASSIGN COMPONENT 'FILENAME' OF STRUCTURE eg_file TO . - ASSERT IS ASSIGNED. - = -value. - ENDIF. - - ENDMETHOD. "file_decode - - METHOD dbkey_encode. - - DATA: lt_fields TYPE tihttpnvp, - ls_field LIKE LINE OF lt_fields. - - ls_field-name = 'TYPE'. - ls_field-value = is_key-type. - APPEND ls_field TO lt_fields. - - ls_field-name = 'VALUE'. - ls_field-value = is_key-value. - APPEND ls_field TO lt_fields. - - rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). - - ENDMETHOD. "dbkey_encode - - METHOD dbkey_decode. - - DATA: lt_fields TYPE tihttpnvp, - lv_string TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields. - - lv_string = iv_string. " type conversion - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'TYPE'. - IF sy-subrc = 0. - rs_key-type = -value. - ENDIF. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'VALUE'. - IF sy-subrc = 0. - rs_key-value = -value. - ENDIF. - - ENDMETHOD. "dbkey_decode - - METHOD parse_commit_request. - - CONSTANTS: lc_replace TYPE string VALUE '<>'. - - DATA: lv_string TYPE string, - lt_fields TYPE tihttpnvp. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields. - - - CONCATENATE LINES OF it_postdata INTO lv_string. - - REPLACE ALL OCCURRENCES OF gc_newline IN lv_string WITH lc_replace. - - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'key' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-repo_key = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'username' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-username = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'email' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-email = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'comment' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-comment = -value. - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'body' ##NO_TEXT. - ASSERT sy-subrc = 0. - rs_fields-body = -value. - REPLACE ALL OCCURRENCES OF lc_replace IN rs_fields-body WITH gc_newline. - - ENDMETHOD. "parse_commit_request - - METHOD repo_key_encode. - - DATA: lt_fields TYPE tihttpnvp, - ls_field LIKE LINE OF lt_fields. - - ls_field-name = 'KEY'. - ls_field-value = iv_key. - APPEND ls_field TO lt_fields. - - rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). - - ENDMETHOD. "repo_key_encode - - METHOD repo_key_decode. - - DATA: lt_fields TYPE tihttpnvp, - lv_string TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF lt_fields. - - lv_string = iv_string. " type conversion - lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). - - READ TABLE lt_fields ASSIGNING WITH KEY name = 'KEY'. - IF sy-subrc = 0. - rv_key = -value. - ENDIF. - - ENDMETHOD. "repo_key_decode - -ENDCLASS. "lcl_html_action_utils IMPLEMENTATION - CLASS lcl_log DEFINITION FINAL. PUBLIC SECTION. @@ -12364,104 +11342,6 @@ CLASS lcl_log IMPLEMENTATION. ENDCLASS. -*----------------------------------------------------------------------* -* CLASS lcl_repo DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_repo DEFINITION ABSTRACT. - - PUBLIC SECTION. - METHODS: - constructor - IMPORTING is_data TYPE lcl_persistence_repo=>ty_repo, - get_key - RETURNING VALUE(rv_key) TYPE lcl_persistence_db=>ty_value, - get_name - RETURNING VALUE(rv_name) TYPE string - RAISING lcx_exception, - get_files_local - IMPORTING io_log TYPE REF TO lcl_log OPTIONAL - RETURNING VALUE(rt_files) TYPE ty_files_item_tt - RAISING lcx_exception, - get_local_checksums - RETURNING VALUE(rt_checksums) TYPE lcl_persistence_repo=>ty_local_checksum_tt, - get_files_remote - RETURNING VALUE(rt_files) TYPE ty_files_tt - RAISING lcx_exception, - get_package - RETURNING VALUE(rv_package) TYPE lcl_persistence_repo=>ty_repo-package, - get_master_language - RETURNING VALUE(rv_language) TYPE spras, - delete - RAISING lcx_exception, - get_dot_abapgit - RETURNING VALUE(ro_dot_abapgit) TYPE REF TO lcl_dot_abapgit, - deserialize - RAISING lcx_exception, - refresh - RAISING lcx_exception, - build_local_checksums - RETURNING VALUE(rt_checksums) TYPE lcl_persistence_repo=>ty_local_checksum_tt - RAISING lcx_exception, - is_offline - RETURNING VALUE(rv_offline) TYPE abap_bool - RAISING lcx_exception. - - PROTECTED SECTION. - - DATA: mt_local TYPE ty_files_item_tt, - mt_remote TYPE ty_files_tt, - mo_dot_abapgit TYPE REF TO lcl_dot_abapgit, - ms_data TYPE lcl_persistence_repo=>ty_repo. - - METHODS: - find_dot_abapgit - RAISING lcx_exception, - set - IMPORTING iv_sha1 TYPE ty_sha1 OPTIONAL - it_checksums TYPE lcl_persistence_repo=>ty_local_checksum_tt OPTIONAL - iv_url TYPE lcl_persistence_repo=>ty_repo-url OPTIONAL - iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name OPTIONAL - RAISING lcx_exception. - -ENDCLASS. "lcl_repo DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_file_status DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_file_status DEFINITION FINAL. - - PUBLIC SECTION. - - TYPES: BEGIN OF ty_result, - obj_type TYPE tadir-object, - obj_name TYPE tadir-obj_name, - match TYPE sap_bool, - filename TYPE string, - package TYPE devclass, - path TYPE string, - END OF ty_result. - TYPES: ty_results_tt TYPE STANDARD TABLE OF ty_result WITH DEFAULT KEY. - - CLASS-METHODS status - IMPORTING io_repo TYPE REF TO lcl_repo - io_log TYPE REF TO lcl_log OPTIONAL - RETURNING VALUE(rt_results) TYPE ty_results_tt - RAISING lcx_exception. - - PRIVATE SECTION. - - CLASS-METHODS compare_files - IMPORTING it_repo TYPE ty_files_tt - is_gen TYPE ty_file - RETURNING VALUE(rv_match) TYPE sap_bool - RAISING lcx_exception. - -ENDCLASS. "lcl_file_status DEFINITION - *----------------------------------------------------------------------* * CLASS lcl_object DEFINITION *----------------------------------------------------------------------* @@ -12511,8 +11391,8 @@ CLASS lcl_objects DEFINITION FINAL. CLASS-METHODS prioritize_deser - IMPORTING it_results TYPE lcl_file_status=>ty_results_tt - RETURNING VALUE(rt_results) TYPE lcl_file_status=>ty_results_tt. + IMPORTING it_results TYPE ty_results_tt + RETURNING VALUE(rt_results) TYPE ty_results_tt. CLASS-METHODS path_to_package @@ -12532,7 +11412,7 @@ CLASS lcl_objects DEFINITION FINAL. CLASS-METHODS warning_overwrite IMPORTING io_repo TYPE REF TO lcl_repo - CHANGING ct_results TYPE lcl_file_status=>ty_results_tt + CHANGING ct_results TYPE ty_results_tt RAISING lcx_exception. CLASS-METHODS warning_package @@ -12550,6 +11430,8 @@ CLASS lcl_objects DEFINITION FINAL. ENDCLASS. "lcl_object DEFINITION + + *----------------------------------------------------------------------* * CLASS lcl_tadir IMPLEMENTATION *----------------------------------------------------------------------* @@ -12697,7 +11579,7 @@ CLASS lcl_sap_package DEFINITION FINAL. CLASS-METHODS: check IMPORTING io_log TYPE REF TO lcl_log - it_results TYPE lcl_file_status=>ty_results_tt + it_results TYPE ty_results_tt iv_start TYPE string iv_top TYPE devclass, list_subpackages IMPORTING iv_package TYPE devclass @@ -12729,167 +11611,7 @@ CLASS lcl_sap_package DEFINITION FINAL. ENDCLASS. "lcl_package DEFINITION -*----------------------------------------------------------------------* -* CLASS lcl_file_status IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_file_status IMPLEMENTATION. - - METHOD compare_files. - - READ TABLE it_repo WITH KEY - path = is_gen-path - filename = is_gen-filename - data = is_gen-data - TRANSPORTING NO FIELDS. - IF sy-subrc <> 0. - rv_match = abap_false. - ELSE. - rv_match = abap_true. - ENDIF. - - ENDMETHOD. "compare_files - - METHOD status. - - DATA: lv_pre TYPE tadir-obj_name, - lt_files TYPE ty_files_tt, - ls_result LIKE LINE OF rt_results, - lv_type TYPE string, - ls_item TYPE ty_item, - lt_tadir TYPE lcl_tadir=>ty_tadir_tt, - lt_local TYPE ty_files_item_tt, - ls_tadir TYPE tadir, - lt_remote TYPE ty_files_tt, - lv_ext TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF lt_remote, - LIKE LINE OF lt_tadir, - LIKE LINE OF rt_results, - LIKE LINE OF lt_local, - LIKE LINE OF lt_files. - - - lt_remote = io_repo->get_files_remote( ). - lt_local = io_repo->get_files_local( io_log ). - - LOOP AT lt_remote ASSIGNING . - lcl_progress=>show( iv_key = 'Status' - iv_current = sy-tabix - iv_total = lines( lt_remote ) - iv_text = -filename ) ##NO_TEXT. - - SPLIT -filename AT '.' INTO lv_pre lv_type lv_ext. - TRANSLATE lv_pre TO UPPER CASE. - TRANSLATE lv_type TO UPPER CASE. - - IF lv_ext <> 'xml' OR strlen( lv_type ) <> 4. - CONTINUE. " current loop - ENDIF. - -* handle namespaces - REPLACE ALL OCCURRENCES OF '#' IN lv_pre WITH '/'. - - CLEAR ls_result. - ls_result-obj_type = lv_type. - ls_result-obj_name = lv_pre. - - CLEAR ls_item. - ls_item-obj_type = lv_type. - ls_item-obj_name = lv_pre. - - CLEAR lt_files. - LOOP AT lt_local ASSIGNING WHERE item = ls_item. - APPEND -file TO lt_files. - ENDLOOP. - - IF lt_files[] IS INITIAL. -* item does not exist locally - ls_result-filename = -filename. - APPEND ls_result TO rt_results. - CONTINUE. " current loop - ENDIF. - - LOOP AT lt_files ASSIGNING . - ls_result-filename = -filename. - ls_result-match = compare_files( it_repo = lt_remote - is_gen = ). - APPEND ls_result TO rt_results. - ENDLOOP. - ENDLOOP. - -* find files only existing remotely, including non abapGit related - LOOP AT lt_remote ASSIGNING . - READ TABLE rt_results WITH KEY filename = -filename - TRANSPORTING NO FIELDS. - IF sy-subrc <> 0. - IF io_repo->get_dot_abapgit( )->is_ignored( - iv_path = -path - iv_filename = -filename ) = abap_true. - CONTINUE. - ENDIF. - - CLEAR ls_result. - ls_result-match = abap_true. - ls_result-filename = -filename. - APPEND ls_result TO rt_results. - ENDIF. - ENDLOOP. - -* find objects only existing locally - lt_tadir = lcl_tadir=>read( io_repo->get_package( ) ). - LOOP AT lt_tadir ASSIGNING . - READ TABLE rt_results - WITH KEY obj_type = -object - obj_name = -obj_name - TRANSPORTING NO FIELDS. - IF sy-subrc <> 0. - ls_item-obj_type = -object. - ls_item-obj_name = -obj_name. - IF lcl_objects=>is_supported( ls_item ) = abap_false. - CONTINUE. - ENDIF. - - CLEAR ls_result. - ls_result-match = abap_true. - ls_result-obj_type = -object. - ls_result-obj_name = -obj_name. - APPEND ls_result TO rt_results. - ENDIF. - ENDLOOP. - -* add path information for files - LOOP AT lt_remote ASSIGNING . - READ TABLE rt_results ASSIGNING WITH KEY filename = -filename. - IF sy-subrc = 0. - -path = -path. - ENDIF. - ENDLOOP. - -* add package information - LOOP AT rt_results ASSIGNING WHERE NOT obj_type IS INITIAL. - ls_tadir = lcl_tadir=>read_single( iv_object = -obj_type - iv_obj_name = -obj_name ). - -package = ls_tadir-devclass. - ENDLOOP. - - SORT rt_results BY - obj_type ASCENDING - obj_name ASCENDING - filename ASCENDING. - DELETE ADJACENT DUPLICATES FROM rt_results - COMPARING obj_type obj_name filename. - - lcl_sap_package=>check( - io_log = io_log - it_results = rt_results - iv_start = io_repo->get_dot_abapgit( )->get_starting_folder( ) - iv_top = io_repo->get_package( ) ). - - ENDMETHOD. "status - -ENDCLASS. "lcl_file_status IMPLEMENTATION +INCLUDE zabapgit_file_status. *----------------------------------------------------------------------* * CLASS lcl_package IMPLEMENTATION @@ -13687,7 +12409,7 @@ CLASS lcl_objects IMPLEMENTATION. lv_package TYPE devclass, lo_files TYPE REF TO lcl_objects_files, lo_xml TYPE REF TO lcl_xml_input, - lt_results TYPE lcl_file_status=>ty_results_tt, + lt_results TYPE ty_results_tt, lt_late TYPE TABLE OF ty_late. FIELD-SYMBOLS: LIKE LINE OF lt_results, @@ -13771,1384 +12493,6 @@ CLASS lcl_objects IMPLEMENTATION. ENDCLASS. "lcl_object IMPLEMENTATION -*----------------------------------------------------------------------* -* CLASS lcl_pack IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_git_pack IMPLEMENTATION. - - METHOD sort_tree. - - TYPES: BEGIN OF ty_sort, - sort TYPE string, - node TYPE ty_node, - END OF ty_sort. - - DATA: lt_sort TYPE STANDARD TABLE OF ty_sort WITH DEFAULT KEY. - - FIELD-SYMBOLS: LIKE LINE OF lt_sort, - LIKE LINE OF it_nodes. - - - LOOP AT it_nodes ASSIGNING . - APPEND INITIAL LINE TO lt_sort ASSIGNING . - IF -chmod = gc_chmod-dir. - CONCATENATE -name '/' INTO -sort. - ELSE. - -sort = -name. - ENDIF. - -node = . - ENDLOOP. - -* following has to be done, or unpack will fail on server side - SORT lt_sort BY sort ASCENDING. - - LOOP AT lt_sort ASSIGNING . - APPEND -node TO rt_nodes. - ENDLOOP. - - ENDMETHOD. - - METHOD type_and_length. - - DATA: lv_bits TYPE string, - lv_type TYPE string, - lv_result TYPE string, - lv_c TYPE c, - lv_offset TYPE i, - lv_x4 TYPE x LENGTH 4, - lv_x TYPE x LENGTH 1. - - - CASE is_object-type. - WHEN gc_type-commit. - lv_type = '001'. - WHEN gc_type-tree. - lv_type = '010'. - WHEN gc_type-blob. - lv_type = '011'. - WHEN gc_type-ref_d. - lv_type = '111'. - WHEN OTHERS. - _raise 'Unexpected object type while encoding pack'. - ENDCASE. - - lv_x4 = xstrlen( is_object-data ). - DO 32 TIMES. - GET BIT sy-index OF lv_x4 INTO lv_c. - CONCATENATE lv_bits lv_c INTO lv_bits. - ENDDO. - - IF lv_bits(28) = '0000000000000000000000000000'. - CONCATENATE '0' lv_type lv_bits+28(4) INTO lv_result. - ELSEIF lv_bits(21) = '000000000000000000000'. - CONCATENATE '1' lv_type lv_bits+28(4) INTO lv_result. - CONCATENATE lv_result '0' lv_bits+21(7) INTO lv_result. - ELSEIF lv_bits(14) = '00000000000000'. - CONCATENATE '1' lv_type lv_bits+28(4) INTO lv_result. - CONCATENATE lv_result '1' lv_bits+21(7) INTO lv_result. - CONCATENATE lv_result '0' lv_bits+14(7) INTO lv_result. - ELSEIF lv_bits(7) = '0000000'. - CONCATENATE '1' lv_type lv_bits+28(4) INTO lv_result. - CONCATENATE lv_result '1' lv_bits+21(7) INTO lv_result. - CONCATENATE lv_result '1' lv_bits+14(7) INTO lv_result. - CONCATENATE lv_result '0' lv_bits+7(7) INTO lv_result. - ELSE. -* this IF can be refactored, use shifting? - _raise 'Todo, encoding length'. - ENDIF. - -* convert bit string to xstring - CLEAR lv_x. - DO strlen( lv_result ) TIMES. - lv_offset = sy-index - 1. - IF lv_result+lv_offset(1) = '1'. - SET BIT ( lv_offset MOD 8 ) + 1 OF lv_x. - ENDIF. - IF ( lv_offset + 1 ) MOD 8 = 0. - CONCATENATE rv_xstring lv_x INTO rv_xstring IN BYTE MODE. - CLEAR lv_x. - ENDIF. - ENDDO. - - ENDMETHOD. "type_and_length - - METHOD get_length. - - DATA: lv_x TYPE x, - lv_length_bits TYPE string, - lv_bitbyte TYPE ty_bitbyte. - - - lv_x = cv_data(1). - lv_bitbyte = lcl_convert=>x_to_bitbyte( lv_x ). - - cv_data = cv_data+1. - lv_length_bits = lv_bitbyte+4. - - WHILE lv_bitbyte(1) <> '0'. - lv_x = cv_data(1). - lv_bitbyte = lcl_convert=>x_to_bitbyte( lv_x ). - cv_data = cv_data+1. - CONCATENATE lv_bitbyte+1 lv_length_bits INTO lv_length_bits. - ENDWHILE. - - ev_length = lcl_convert=>bitbyte_to_int( lv_length_bits ). - - ENDMETHOD. "get_length - - METHOD encode_tree. - - CONSTANTS: lc_null TYPE x VALUE '00'. - - DATA: lv_string TYPE string, - lt_nodes LIKE it_nodes, - lv_hex20 TYPE x LENGTH 20, - lv_xstring TYPE xstring. - - FIELD-SYMBOLS: LIKE LINE OF it_nodes. - - - lt_nodes = sort_tree( it_nodes ). - - LOOP AT lt_nodes ASSIGNING . - ASSERT NOT -chmod IS INITIAL. - ASSERT NOT -name IS INITIAL. - ASSERT NOT -sha1 IS INITIAL. - - CONCATENATE -chmod -name INTO lv_string SEPARATED BY space. - lv_xstring = lcl_convert=>string_to_xstring_utf8( lv_string ). - - lv_hex20 = to_upper( -sha1 ). - CONCATENATE rv_data lv_xstring lc_null lv_hex20 INTO rv_data IN BYTE MODE. - ENDLOOP. - - ENDMETHOD. "encode_tree - - METHOD encode_commit. - - DATA: lv_string TYPE string, - lv_tmp TYPE string, - lv_tree_lower TYPE string, - lv_parent_lower TYPE string. - - - lv_tree_lower = is_commit-tree. - TRANSLATE lv_tree_lower TO LOWER CASE. - - lv_parent_lower = is_commit-parent. - TRANSLATE lv_parent_lower TO LOWER CASE. - - lv_string = ''. - - CONCATENATE 'tree' lv_tree_lower INTO lv_tmp SEPARATED BY space. "#EC NOTEXT - CONCATENATE lv_string lv_tmp gc_newline INTO lv_string. - - IF NOT is_commit-parent IS INITIAL. - CONCATENATE 'parent' lv_parent_lower - INTO lv_tmp SEPARATED BY space. "#EC NOTEXT - CONCATENATE lv_string lv_tmp gc_newline INTO lv_string. - ENDIF. - - CONCATENATE 'author' is_commit-author - INTO lv_tmp SEPARATED BY space. "#EC NOTEXT - CONCATENATE lv_string lv_tmp gc_newline INTO lv_string. - - CONCATENATE 'committer' is_commit-committer - INTO lv_tmp SEPARATED BY space. "#EC NOTEXT - CONCATENATE lv_string lv_tmp gc_newline INTO lv_string. - - CONCATENATE lv_string gc_newline is_commit-body INTO lv_string. - - rv_data = lcl_convert=>string_to_xstring_utf8( lv_string ). - - ENDMETHOD. "encode_commit - - METHOD get_type. - - DATA: lv_char3 TYPE c LENGTH 3, - lv_bitbyte TYPE ty_bitbyte. - - - lv_bitbyte = lcl_convert=>x_to_bitbyte( iv_x ). - lv_char3 = lv_bitbyte+1. - - CASE lv_char3. - WHEN '001'. - rv_type = gc_type-commit. - WHEN '010'. - rv_type = gc_type-tree. - WHEN '011'. - rv_type = gc_type-blob. - WHEN '111'. - rv_type = gc_type-ref_d. - WHEN OTHERS. - _raise 'Todo, unknown type'. - ENDCASE. - - ENDMETHOD. "get_type - - METHOD decode_commit. - - DATA: lv_string TYPE string, - lv_mode TYPE string, - lv_len TYPE i, - lt_string TYPE TABLE OF string. - - FIELD-SYMBOLS: LIKE LINE OF lt_string. - - - lv_string = lcl_convert=>xstring_to_string_utf8( iv_data ). - - SPLIT lv_string AT gc_newline INTO TABLE lt_string. - - lv_mode = 'tree'. "#EC NOTEXT - LOOP AT lt_string ASSIGNING . - lv_len = strlen( lv_mode ). - - IF NOT lv_mode IS INITIAL AND (lv_len) = lv_mode. - CASE lv_mode. - WHEN 'tree'. - rs_commit-tree = +5. - lv_mode = 'parent'. "#EC NOTEXT - WHEN 'parent'. - rs_commit-parent = +7. - lv_mode = 'author'. "#EC NOTEXT - WHEN 'author'. - rs_commit-author = +7. - lv_mode = 'committer'. "#EC NOTEXT - WHEN 'committer'. - rs_commit-committer = +10. - CLEAR lv_mode. - ENDCASE. - ELSEIF lv_mode = 'parent' AND (6) = 'author'. "#EC NOTEXT -* first commit doesnt have parent - rs_commit-author = +7. - lv_mode = 'committer'. "#EC NOTEXT - ELSE. -* body - CONCATENATE rs_commit-body INTO rs_commit-body - SEPARATED BY gc_newline. - ENDIF. - ENDLOOP. - -* strip first newline - IF strlen( rs_commit-body ) >= 2. - rs_commit-body = rs_commit-body+2. - ENDIF. - - IF rs_commit-author IS INITIAL - OR rs_commit-committer IS INITIAL - OR rs_commit-tree IS INITIAL. - _raise 'multiple parents? not supported'. - ENDIF. - - ENDMETHOD. "decode_commit - - METHOD delta_header. - - DATA: lv_bitbyte TYPE ty_bitbyte, - lv_bits TYPE string, - lv_x TYPE x. - - - lv_bits = ''. - DO. - lv_x = cv_delta(1). - cv_delta = cv_delta+1. - lv_bitbyte = lcl_convert=>x_to_bitbyte( lv_x ). - CONCATENATE lv_bitbyte+1 lv_bits INTO lv_bits. - IF lv_bitbyte(1) = '0'. - EXIT. " current loop - ENDIF. - ENDDO. - ev_header = lcl_convert=>bitbyte_to_int( lv_bits ). - - ENDMETHOD. "delta_header - - METHOD delta. - - DATA: lv_delta TYPE xstring, - lv_base TYPE xstring, - lv_result TYPE xstring, - lv_bitbyte TYPE ty_bitbyte, - lv_offset TYPE i, - lv_message TYPE string, - lv_sha1 TYPE ty_sha1, - ls_object LIKE LINE OF ct_objects, - lv_len TYPE i, - lv_x TYPE x. - - FIELD-SYMBOLS: LIKE LINE OF ct_objects. - - - lv_delta = is_object-data. - -* find base - READ TABLE ct_objects ASSIGNING WITH KEY sha1 = is_object-sha1. - IF sy-subrc <> 0. - CONCATENATE 'Base not found,' is_object-sha1 INTO lv_message - SEPARATED BY space. "#EC NOTEXT - _raise lv_message. - ELSE. - lv_base = -data. - ENDIF. - -* sanity check - IF -type = gc_type-ref_d. - _raise 'Delta, base eq delta'. - ENDIF. - -* skip the 2 headers - delta_header( CHANGING cv_delta = lv_delta ). - delta_header( CHANGING cv_delta = lv_delta ). - - WHILE xstrlen( lv_delta ) > 0. - - lv_x = lv_delta(1). - lv_delta = lv_delta+1. - lv_bitbyte = lcl_convert=>x_to_bitbyte( lv_x ). - - IF lv_bitbyte(1) = '1'. " MSB - - lv_offset = 0. - IF lv_bitbyte+7(1) = '1'. - lv_x = lv_delta(1). - lv_delta = lv_delta+1. - lv_offset = lv_x. - ENDIF. - IF lv_bitbyte+6(1) = '1'. - lv_x = lv_delta(1). - lv_delta = lv_delta+1. - lv_offset = lv_offset + lv_x * 256. - ENDIF. - IF lv_bitbyte+5(1) = '1'. - lv_x = lv_delta(1). - lv_delta = lv_delta+1. - lv_offset = lv_offset + lv_x * 65536. - ENDIF. - IF lv_bitbyte+4(1) = '1'. - lv_x = lv_delta(1). - lv_delta = lv_delta+1. - lv_offset = lv_offset + lv_x * 16777216. " hmm, overflow? - ENDIF. - - lv_len = 0. - IF lv_bitbyte+3(1) = '1'. - lv_x = lv_delta(1). - lv_delta = lv_delta+1. - lv_len = lv_x. - ENDIF. - IF lv_bitbyte+2(1) = '1'. - lv_x = lv_delta(1). - lv_delta = lv_delta+1. - lv_len = lv_len + lv_x * 256. - ENDIF. - IF lv_bitbyte+1(1) = '1'. - lv_x = lv_delta(1). - lv_delta = lv_delta+1. - lv_len = lv_len + lv_x * 65536. - ENDIF. - - IF lv_len = 0. - lv_len = 65536. - ENDIF. - - CONCATENATE lv_result lv_base+lv_offset(lv_len) - INTO lv_result IN BYTE MODE. - ELSE. " lv_bitbyte(1) = '0' -* insert from delta - lv_len = lv_x. - CONCATENATE lv_result lv_delta(lv_len) INTO lv_result IN BYTE MODE. - lv_delta = lv_delta+lv_len. - ENDIF. - - ENDWHILE. - - lv_sha1 = lcl_hash=>sha1( iv_type = -type iv_data = lv_result ). - - CLEAR ls_object. - ls_object-sha1 = lv_sha1. - ls_object-type = -type. - ls_object-data = lv_result. - APPEND ls_object TO ct_objects. - - ENDMETHOD. "delta - - METHOD decode_deltas. - - DATA: ls_object LIKE LINE OF ct_objects, - lt_deltas LIKE ct_objects. - - - LOOP AT ct_objects INTO ls_object WHERE type = gc_type-ref_d. - DELETE ct_objects INDEX sy-tabix. - APPEND ls_object TO lt_deltas. - ENDLOOP. - - LOOP AT lt_deltas INTO ls_object. - delta( EXPORTING is_object = ls_object - CHANGING ct_objects = ct_objects ). - ENDLOOP. - - ENDMETHOD. "decode_deltas - - METHOD decode_tree. - - CONSTANTS: lc_sha_length TYPE i VALUE 20, - lc_null TYPE x VALUE '00'. - - DATA: lv_xstring TYPE xstring, - lv_chmod TYPE ty_chmod, - lv_name TYPE string, - lv_string TYPE string, - lv_len TYPE i, - lv_offset TYPE i, - lv_cursor TYPE i, - ls_node TYPE ty_node, - lv_start TYPE i. - - - DO. - IF lv_cursor >= xstrlen( iv_data ). - EXIT. " current loop - ENDIF. - - IF iv_data+lv_cursor(1) = lc_null. - lv_len = lv_cursor - lv_start. - lv_xstring = iv_data+lv_start(lv_len). - - lv_string = lcl_convert=>xstring_to_string_utf8( lv_xstring ). - SPLIT lv_string AT space INTO lv_chmod lv_name. - - lv_offset = lv_cursor + 1. - - CLEAR ls_node. - ls_node-chmod = lv_chmod. - IF ls_node-chmod <> gc_chmod-dir - AND ls_node-chmod <> gc_chmod-file - AND ls_node-chmod <> gc_chmod-executable. - _raise 'Unknown chmod'. - ENDIF. - - ls_node-name = lv_name. - ls_node-sha1 = iv_data+lv_offset(lc_sha_length). - TRANSLATE ls_node-sha1 TO LOWER CASE. - APPEND ls_node TO rt_nodes. - - lv_start = lv_cursor + 1 + lc_sha_length. - lv_cursor = lv_start. - ELSE. - lv_cursor = lv_cursor + 1. - ENDIF. - ENDDO. - - ENDMETHOD. "decode_tree - - METHOD decode. - - DATA: lv_x TYPE x, - lv_data TYPE xstring, - lv_type TYPE c LENGTH 6, - lv_zlib TYPE x LENGTH 2, - lv_objects TYPE i, - lv_len TYPE i, - lv_sha1 TYPE ty_sha1, - lv_ref_delta TYPE ty_sha1, - lv_adler32 TYPE lcl_hash=>ty_adler32, - lv_compressed TYPE xstring, - lv_compressed_len TYPE i, - lv_decompress_len TYPE i, - lv_decompressed TYPE xstring, - lv_xstring TYPE xstring, - lv_expected TYPE i, - ls_object LIKE LINE OF rt_objects, - ls_data TYPE lcl_zlib=>ty_decompress. - - - lv_data = iv_data. - -* header - IF NOT xstrlen( lv_data ) > 4 OR lv_data(4) <> c_pack_start. - _raise 'Unexpected pack header'. - ENDIF. - lv_data = lv_data+4. - -* version - IF lv_data(4) <> c_version. - _raise 'Version not supported'. - ENDIF. - lv_data = lv_data+4. - -* number of objects - lv_xstring = lv_data(4). - lv_objects = lcl_convert=>xstring_to_int( lv_xstring ). - lv_data = lv_data+4. - - - DO lv_objects TIMES. - - lv_x = lv_data(1). - lv_type = get_type( lv_x ). - - get_length( IMPORTING ev_length = lv_expected - CHANGING cv_data = lv_data ). - - IF lv_type = gc_type-ref_d. - lv_ref_delta = lv_data(20). - lv_data = lv_data+20. - ENDIF. - -* strip header, '789C', CMF + FLG - lv_zlib = lv_data(2). - IF lv_zlib <> c_zlib AND lv_zlib <> c_zlib_hmm. - _raise 'Unexpected zlib header'. - ENDIF. - lv_data = lv_data+2. - -******************************* - - IF lv_zlib = c_zlib. - cl_abap_gzip=>decompress_binary( - EXPORTING - gzip_in = lv_data - IMPORTING - raw_out = lv_decompressed - raw_out_len = lv_decompress_len ). - - IF lv_expected <> lv_decompress_len. - _raise 'Decompression falied'. - ENDIF. - - cl_abap_gzip=>compress_binary( - EXPORTING - raw_in = lv_decompressed - IMPORTING - gzip_out = lv_compressed - gzip_out_len = lv_compressed_len ). - - IF lv_compressed(lv_compressed_len) <> lv_data(lv_compressed_len). - _raise 'Compressed data doesnt match'. - ENDIF. - - lv_data = lv_data+lv_compressed_len. - - ELSEIF lv_zlib = c_zlib_hmm. -* cl_abap_gzip copmression works for header '789C', but does not work for -* '7801', call custom implementation of DEFLATE algorithm. -* The custom implementation could handle both, but most likely the kernel -* implementation runs faster than the custom ABAP. - ls_data = lcl_zlib=>decompress( lv_data ). - lv_compressed_len = ls_data-compressed_len. - lv_decompressed = ls_data-raw. - - IF lv_compressed_len IS INITIAL. - _raise 'Decompression falied :o/'. - ENDIF. - - lv_data = lv_data+lv_compressed_len. - - lv_adler32 = lcl_hash=>adler32( lv_decompressed ). - IF lv_data(4) <> lv_adler32. - lv_data = lv_data+1. - ENDIF. - IF lv_data(4) <> lv_adler32. - lv_data = lv_data+1. - ENDIF. - IF lv_data(4) <> lv_adler32. - _raise 'Wrong Adler checksum'. - ENDIF. - - ENDIF. - - lv_data = lv_data+4. " skip adler checksum - -************************* - - CLEAR ls_object. - IF lv_type = gc_type-ref_d. - ls_object-sha1 = lv_ref_delta. - TRANSLATE ls_object-sha1 TO LOWER CASE. - ELSE. - ls_object-sha1 = lcl_hash=>sha1( - iv_type = lv_type - iv_data = lv_decompressed ). - ENDIF. - ls_object-type = lv_type. - ls_object-data = lv_decompressed. - APPEND ls_object TO rt_objects. - ENDDO. - -* check SHA1 at end of pack - lv_len = xstrlen( iv_data ) - 20. - lv_xstring = iv_data(lv_len). - lv_sha1 = lcl_hash=>sha1_raw( lv_xstring ). - IF to_upper( lv_sha1 ) <> lv_data. - _raise 'SHA1 at end of pack doesnt match'. - ENDIF. - - ENDMETHOD. "decode - - METHOD encode. - - DATA: lv_sha1 TYPE x LENGTH 20, - lv_adler32 TYPE lcl_hash=>ty_adler32, - lv_len TYPE i, - lv_compressed TYPE xstring, - lv_xstring TYPE xstring. - - FIELD-SYMBOLS: LIKE LINE OF it_objects. - - - rv_data = c_pack_start. - - CONCATENATE rv_data c_version INTO rv_data IN BYTE MODE. - - lv_len = lines( it_objects ). - lv_xstring = lcl_convert=>int_to_xstring( iv_i = lv_len - iv_length = 4 ). - CONCATENATE rv_data lv_xstring INTO rv_data IN BYTE MODE. - - LOOP AT it_objects ASSIGNING . - lv_xstring = type_and_length( ). - CONCATENATE rv_data lv_xstring INTO rv_data IN BYTE MODE. - - cl_abap_gzip=>compress_binary( - EXPORTING - raw_in = -data - IMPORTING - gzip_out = lv_compressed ). - - CONCATENATE rv_data c_zlib lv_compressed INTO rv_data IN BYTE MODE. - - lv_adler32 = lcl_hash=>adler32( -data ). - CONCATENATE rv_data lv_adler32 INTO rv_data IN BYTE MODE. - - ENDLOOP. - - lv_sha1 = to_upper( lcl_hash=>sha1_raw( rv_data ) ). - CONCATENATE rv_data lv_sha1 INTO rv_data IN BYTE MODE. - - ENDMETHOD. "encode - -ENDCLASS. "lcl_pack IMPLEMENTATION - -*----------------------------------------------------------------------* -* CLASS lcl_persistence DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_persistence DEFINITION FINAL FRIENDS lcl_persistence_migrate. - -* this class is obsolete, use LCL_PERSISTENCE_REPO instead - - PRIVATE SECTION. - TYPES: BEGIN OF ty_repo_persi, - url TYPE string, - branch_name TYPE string, - sha1 TYPE ty_sha1, - package TYPE devclass, - offline TYPE sap_bool, - END OF ty_repo_persi. - TYPES: ty_repos_persi_tt TYPE STANDARD TABLE OF ty_repo_persi WITH DEFAULT KEY. - - METHODS list - RETURNING VALUE(rt_repos) TYPE ty_repos_persi_tt - RAISING lcx_exception. - - METHODS update - IMPORTING iv_url TYPE ty_repo_persi-url - iv_branch_name TYPE ty_repo_persi-branch_name - iv_branch TYPE ty_sha1 - RAISING lcx_exception. - - METHODS add - IMPORTING iv_url TYPE string - iv_branch_name TYPE string - iv_branch TYPE ty_sha1 OPTIONAL - iv_package TYPE devclass - iv_offline TYPE sap_bool DEFAULT abap_false - RAISING lcx_exception. - - METHODS delete - IMPORTING iv_url TYPE ty_repo_persi-url - iv_branch_name TYPE ty_repo_persi-branch_name - RAISING lcx_exception. - - METHODS read_text_online - RETURNING VALUE(rt_repos) TYPE ty_repos_persi_tt - RAISING lcx_exception. - - METHODS save_text_online - IMPORTING it_repos TYPE ty_repos_persi_tt - RAISING lcx_exception. - - METHODS header_online - RETURNING VALUE(rs_header) TYPE thead. - - METHODS read_text_offline - RETURNING VALUE(rt_repos) TYPE ty_repos_persi_tt - RAISING lcx_exception. - - METHODS save_text_offline - IMPORTING it_repos TYPE ty_repos_persi_tt - RAISING lcx_exception. - - METHODS header_offline - RETURNING VALUE(rs_header) TYPE thead. - - METHODS read_text - IMPORTING is_header TYPE thead - RETURNING VALUE(rt_lines) TYPE tlinetab - RAISING lcx_exception. - - METHODS save_text - IMPORTING is_header TYPE thead - it_lines TYPE tlinetab - RAISING lcx_exception. - -ENDCLASS. "lcl_persistence DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_persistence IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_persistence IMPLEMENTATION. - - METHOD save_text. - - CALL FUNCTION 'SAVE_TEXT' - EXPORTING - header = is_header - TABLES - lines = it_lines - EXCEPTIONS - id = 1 - language = 2 - name = 3 - object = 4 - OTHERS = 5. - IF sy-subrc <> 0. - ROLLBACK WORK. "#EC CI_ROLLBACK - _raise 'error from SAVE_TEXT'. - ENDIF. - - ENDMETHOD. "save_text - - METHOD header_online. - rs_header-tdid = 'ST'. - rs_header-tdspras = gc_english. - rs_header-tdname = 'ZABAPGIT'. - rs_header-tdobject = 'TEXT'. - ENDMETHOD. "header - - METHOD header_offline. - rs_header-tdid = 'ST'. - rs_header-tdspras = gc_english. - rs_header-tdname = 'ZABAPGIT_OFFLINE'. - rs_header-tdobject = 'TEXT'. - ENDMETHOD. "header_offline - - METHOD delete. - - DATA: lt_repos TYPE ty_repos_persi_tt. - - - lt_repos = list( ). - - DELETE lt_repos WHERE url = iv_url AND branch_name = iv_branch_name. - IF sy-subrc <> 0. - _raise 'repo not found, delete'. - ENDIF. - - save_text_online( lt_repos ). - save_text_offline( lt_repos ). - - ENDMETHOD. "delete - - METHOD save_text_online. - - DATA: lt_lines TYPE TABLE OF tline. - - FIELD-SYMBOLS: LIKE LINE OF it_repos, - LIKE LINE OF lt_lines. - - - LOOP AT it_repos ASSIGNING WHERE offline = abap_false. - APPEND INITIAL LINE TO lt_lines ASSIGNING . - -tdformat = '*'. - -tdline = -url. - APPEND INITIAL LINE TO lt_lines ASSIGNING . - -tdformat = '*'. - -tdline = -branch_name. - APPEND INITIAL LINE TO lt_lines ASSIGNING . - -tdformat = '*'. - -tdline = -sha1. - APPEND INITIAL LINE TO lt_lines ASSIGNING . - -tdformat = '*'. - -tdline = -package. - ENDLOOP. - - save_text( is_header = header_online( ) - it_lines = lt_lines ). - - COMMIT WORK. - - ENDMETHOD. "save_text - - METHOD save_text_offline. - - DATA: lt_lines TYPE TABLE OF tline. - - FIELD-SYMBOLS: LIKE LINE OF it_repos, - LIKE LINE OF lt_lines. - - - LOOP AT it_repos ASSIGNING WHERE offline = abap_true. - APPEND INITIAL LINE TO lt_lines ASSIGNING . - -tdformat = '*'. - -tdline = -url. - APPEND INITIAL LINE TO lt_lines ASSIGNING . - -tdformat = '*'. - -tdline = -package. - ENDLOOP. - - save_text( is_header = header_offline( ) - it_lines = lt_lines ). - - COMMIT WORK. - - ENDMETHOD. "save_text_offline - - METHOD add. - - DATA: lt_repos TYPE ty_repos_persi_tt. - - FIELD-SYMBOLS: LIKE LINE OF lt_repos. - - - ASSERT NOT iv_url IS INITIAL. - ASSERT NOT iv_package IS INITIAL. - - lt_repos = list( ). - - READ TABLE lt_repos WITH KEY url = iv_url branch_name = iv_branch_name - TRANSPORTING NO FIELDS. - IF sy-subrc = 0. - _raise 'already inserted'. - ENDIF. - - APPEND INITIAL LINE TO lt_repos ASSIGNING . - -url = iv_url. - -branch_name = iv_branch_name. - -sha1 = iv_branch. - -package = iv_package. - -offline = iv_offline. - - save_text_online( lt_repos ). - save_text_offline( lt_repos ). - - ENDMETHOD. "insert - - METHOD update. - - DATA: lt_repos TYPE ty_repos_persi_tt. - - FIELD-SYMBOLS: LIKE LINE OF lt_repos. - - - IF iv_branch IS INITIAL. - _raise 'update, sha empty'. - ENDIF. - - lt_repos = list( ). - - READ TABLE lt_repos ASSIGNING - WITH KEY url = iv_url branch_name = iv_branch_name. - IF sy-subrc <> 0. - _raise 'persist update, repo not found'. - ENDIF. - - -sha1 = iv_branch. - - save_text_online( lt_repos ). - - ENDMETHOD. "update - - METHOD list. - CLEAR rt_repos. - APPEND LINES OF read_text_online( ) TO rt_repos. - APPEND LINES OF read_text_offline( ) TO rt_repos. - ENDMETHOD. "list - - METHOD read_text. - - CALL FUNCTION 'READ_TEXT' - EXPORTING - id = is_header-tdid - language = is_header-tdspras - name = is_header-tdname - object = is_header-tdobject - TABLES - lines = rt_lines - EXCEPTIONS - id = 1 - language = 2 - name = 3 - not_found = 4 - object = 5 - reference_check = 6 - wrong_access_to_archive = 7 - OTHERS = 8. - IF sy-subrc = 4. - RETURN. - ELSEIF sy-subrc <> 0. - _raise 'Error from READ_TEXT'. - ENDIF. - - ENDMETHOD. "read_text - - METHOD read_text_online. - - DATA: lt_lines TYPE TABLE OF tline, - lv_step TYPE i, - ls_repo TYPE ty_repo_persi. - - FIELD-SYMBOLS: LIKE LINE OF lt_lines. - - - lt_lines = read_text( header_online( ) ). - IF lines( lt_lines ) = 0. - RETURN. - ENDIF. - - IF lines( lt_lines ) MOD 4 <> 0. -* if this happens, delete text ZABAPGIT in SO10 or edit the text -* manually, so it contains the right information - _raise 'Persistence, text broken'. - ENDIF. - - CLEAR ls_repo. - LOOP AT lt_lines ASSIGNING . - lv_step = lv_step + 1. - CASE lv_step. - WHEN 4. - ls_repo-package = -tdline. - - IF ls_repo-url IS INITIAL OR ls_repo-branch_name IS INITIAL. - _raise 'Persistence, text broken 2'. - ENDIF. - APPEND ls_repo TO rt_repos. - CLEAR ls_repo. - lv_step = 0. - WHEN 3. - ls_repo-sha1 = -tdline. - WHEN 2. - ls_repo-branch_name = -tdline. - WHEN 1. - ls_repo-url = -tdline. - WHEN OTHERS. - ASSERT 1 = 0. - ENDCASE. - ENDLOOP. - - ENDMETHOD. "list - - METHOD read_text_offline. - - DATA: lt_lines TYPE TABLE OF tline, - ls_repo TYPE ty_repo_persi. - - FIELD-SYMBOLS: LIKE LINE OF lt_lines. - - - lt_lines = read_text( header_offline( ) ). - IF lines( lt_lines ) = 0. - RETURN. - ENDIF. - - IF lines( lt_lines ) MOD 2 <> 0. -* if this happens, delete text ZABAPGIT in SO10 or edit the text -* manually, so it contains the right information - _raise 'Persistence, text broken'. - ENDIF. - - CLEAR ls_repo. - LOOP AT lt_lines ASSIGNING . - IF -tdline IS INITIAL. - _raise 'Persistence, text broken'. - ENDIF. - IF ls_repo-url IS INITIAL. - ls_repo-url = -tdline. - CONTINUE. " current loop - ENDIF. - - ls_repo-package = -tdline. - ls_repo-offline = abap_true. - APPEND ls_repo TO rt_repos. - CLEAR ls_repo. - ENDLOOP. - - ENDMETHOD. "list - -ENDCLASS. "lcl_persistence IMPLEMENTATION - -CLASS lcl_repo_srv DEFINITION DEFERRED. - -*----------------------------------------------------------------------* -* CLASS lcl_stage DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_stage DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_repo_srv. - - PUBLIC SECTION. - TYPES: ty_method TYPE c LENGTH 1. - - CONSTANTS: BEGIN OF c_method, - add TYPE ty_method VALUE 'A', - rm TYPE ty_method VALUE 'R', - ignore TYPE ty_method VALUE 'I', - END OF c_method. - - CONSTANTS: BEGIN OF c_wftype, - local TYPE char1 VALUE 'L', - remote TYPE char1 VALUE 'R', - END OF c_wftype. - - TYPES: BEGIN OF ty_stage, - file TYPE ty_file, - method TYPE ty_method, - END OF ty_stage. - - TYPES: ty_stage_tt TYPE SORTED TABLE OF ty_stage - WITH UNIQUE KEY file-path file-filename. - - TYPES: BEGIN OF ty_work_file, - type TYPE char1, - file TYPE ty_file, - END OF ty_work_file. - - DATA mv_repo_key TYPE lcl_persistence_db=>ty_value READ-ONLY. - DATA mv_local_cnt TYPE i READ-ONLY. - DATA mt_workarea TYPE STANDARD TABLE OF ty_work_file READ-ONLY. - - CLASS-METHODS method_description - IMPORTING iv_method TYPE ty_method - RETURNING VALUE(rv_description) TYPE string - RAISING lcx_exception. - - METHODS constructor - IMPORTING iv_repo_key TYPE lcl_persistence_db=>ty_value - RAISING lcx_exception. - - METHODS update_and_add_dot_abapgit - IMPORTING iv_data TYPE ty_file-data - RAISING lcx_exception. - - METHODS: - add - IMPORTING iv_path TYPE ty_file-path - iv_filename TYPE ty_file-filename - RAISING lcx_exception, - reset - IMPORTING iv_path TYPE ty_file-path - iv_filename TYPE ty_file-filename - RAISING lcx_exception, - rm - IMPORTING iv_path TYPE ty_file-path - iv_filename TYPE ty_file-filename - RAISING lcx_exception, - ignore - IMPORTING iv_path TYPE ty_file-path - iv_filename TYPE ty_file-filename - RAISING lcx_exception, - lookup - IMPORTING iv_path TYPE ty_file-path - iv_filename TYPE ty_file-filename - RETURNING VALUE(rv_method) TYPE ty_method, - count - RETURNING VALUE(rv_count) TYPE i, - get_all - RETURNING VALUE(rt_stage) TYPE ty_stage_tt. - - PRIVATE SECTION. - DATA: mt_stage TYPE ty_stage_tt. - - METHODS append - IMPORTING iv_path TYPE ty_file-path - iv_filename TYPE ty_file-filename - iv_method TYPE ty_method - RAISING lcx_exception. - - METHODS find_work_file - IMPORTING iv_path TYPE ty_file-path - iv_filename TYPE ty_file-filename - RETURNING VALUE(rs_file) TYPE ty_file - RAISING lcx_exception. - -ENDCLASS. "lcl_stage DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_repo_online DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_repo_online DEFINITION INHERITING FROM lcl_repo FINAL. - - PUBLIC SECTION. - METHODS: - refresh REDEFINITION, - constructor - IMPORTING is_data TYPE lcl_persistence_repo=>ty_repo - RAISING lcx_exception, - get_url - RETURNING VALUE(rv_url) TYPE lcl_persistence_repo=>ty_repo-url, - get_branch_name - RETURNING VALUE(rv_name) TYPE lcl_persistence_repo=>ty_repo-branch_name, - set_url - IMPORTING iv_url TYPE lcl_persistence_repo=>ty_repo-url - RAISING lcx_exception, - set_branch_name - IMPORTING iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name - RAISING lcx_exception, - get_sha1_local - RETURNING VALUE(rv_sha1) TYPE lcl_persistence_repo=>ty_repo-sha1, - get_sha1_remote - RETURNING VALUE(rv_sha1) TYPE lcl_persistence_repo=>ty_repo-sha1 - RAISING lcx_exception, - get_files_remote REDEFINITION, - get_objects - RETURNING VALUE(rt_objects) TYPE lcl_git_pack=>ty_objects_tt - RAISING lcx_exception, - deserialize REDEFINITION, - status - IMPORTING io_log TYPE REF TO lcl_log OPTIONAL - RETURNING VALUE(rt_results) TYPE lcl_file_status=>ty_results_tt - RAISING lcx_exception, - push - IMPORTING is_comment TYPE ty_comment - io_stage TYPE REF TO lcl_stage - RAISING lcx_exception. - - PRIVATE SECTION. - DATA: - mt_objects TYPE lcl_git_pack=>ty_objects_tt, - mv_branch TYPE ty_sha1, - mv_initialized TYPE abap_bool. - - METHODS: - handle_stage_ignore - IMPORTING io_stage TYPE REF TO lcl_stage - RAISING lcx_exception, - initialize - RAISING lcx_exception. - -ENDCLASS. "lcl_repo_online DEFINITION - -CLASS lcl_stage_logic DEFINITION FINAL. - - PUBLIC SECTION. - TYPES: BEGIN OF ty_stage_files, - local TYPE ty_files_item_tt, - remote TYPE ty_files_tt, - END OF ty_stage_files. - - CLASS-METHODS: - get - IMPORTING io_repo TYPE REF TO lcl_repo_online - RETURNING VALUE(rs_files) TYPE ty_stage_files - RAISING lcx_exception, - count - IMPORTING io_repo TYPE REF TO lcl_repo_online - RETURNING VALUE(rv_count) TYPE i - RAISING lcx_exception. - - PRIVATE SECTION. - CLASS-METHODS: - remove_ignored - IMPORTING io_repo TYPE REF TO lcl_repo_online - CHANGING cs_files TYPE ty_stage_files, - remove_identical - CHANGING cs_files TYPE ty_stage_files. - -ENDCLASS. - -CLASS lcl_stage_logic IMPLEMENTATION. - - METHOD get. - rs_files-local = io_repo->get_files_local( ). - rs_files-remote = io_repo->get_files_remote( ). - remove_identical( CHANGING cs_files = rs_files ). - remove_ignored( EXPORTING io_repo = io_repo - CHANGING cs_files = rs_files ). - ENDMETHOD. - - METHOD count. - - DATA: ls_files TYPE ty_stage_files. - - ls_files = get( io_repo ). - - rv_count = lines( ls_files-remote ) + lines( ls_files-local ). - - ENDMETHOD. - - METHOD remove_ignored. - - DATA: lv_index TYPE i. - - FIELD-SYMBOLS: LIKE LINE OF cs_files-remote. - - - LOOP AT cs_files-remote ASSIGNING . - lv_index = sy-tabix. - - IF io_repo->get_dot_abapgit( )->is_ignored( - iv_path = -path - iv_filename = -filename ) = abap_true. - DELETE cs_files-remote INDEX lv_index. - ENDIF. - ENDLOOP. - - ENDMETHOD. - - METHOD remove_identical. - - DATA: lv_index TYPE i, - ls_remote LIKE LINE OF cs_files-remote. - - FIELD-SYMBOLS: LIKE LINE OF cs_files-local. - - - LOOP AT cs_files-local ASSIGNING . - lv_index = sy-tabix. - - READ TABLE cs_files-remote INTO ls_remote - WITH KEY path = -file-path - filename = -file-filename. - IF sy-subrc = 0. - DELETE cs_files-remote INDEX sy-tabix. - IF ls_remote-data = -file-data. - DELETE cs_files-local INDEX lv_index. - ENDIF. - ENDIF. - ENDLOOP. - - ENDMETHOD. - -ENDCLASS. - -*----------------------------------------------------------------------* -* CLASS lcl_repo_offline DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_repo_offline DEFINITION INHERITING FROM lcl_repo FINAL. - - PUBLIC SECTION. - METHODS: - set_files_remote - IMPORTING it_files TYPE ty_files_tt - RAISING lcx_exception. - -ENDCLASS. "lcl_repo_offline DEFINITION - -CLASS ltcl_git_porcelain DEFINITION DEFERRED. - -*----------------------------------------------------------------------* -* CLASS lcl_porcelain DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_git_porcelain DEFINITION FINAL FRIENDS ltcl_git_porcelain. - - PUBLIC SECTION. - - CLASS-METHODS pull - IMPORTING io_repo TYPE REF TO lcl_repo_online - EXPORTING et_files TYPE ty_files_tt - et_objects TYPE lcl_git_pack=>ty_objects_tt - ev_branch TYPE ty_sha1 - RAISING lcx_exception. - - CLASS-METHODS push - IMPORTING io_repo TYPE REF TO lcl_repo_online - is_comment TYPE ty_comment - io_stage TYPE REF TO lcl_stage - RETURNING VALUE(rv_branch) TYPE ty_sha1 - RAISING lcx_exception. - - CLASS-METHODS create_branch - IMPORTING io_repo TYPE REF TO lcl_repo_online - iv_name TYPE string - iv_from TYPE ty_sha1 - RAISING lcx_exception. - - PRIVATE SECTION. - TYPES: BEGIN OF ty_expanded, - path TYPE string, - name TYPE string, - sha1 TYPE ty_sha1, - chmod TYPE ty_chmod, - END OF ty_expanded. - - TYPES: ty_expanded_tt TYPE STANDARD TABLE OF ty_expanded WITH DEFAULT KEY. - - TYPES: BEGIN OF ty_tree, - path TYPE string, - data TYPE xstring, - sha1 TYPE ty_sha1, - END OF ty_tree. - - TYPES: ty_trees_tt TYPE STANDARD TABLE OF ty_tree WITH DEFAULT KEY. - - TYPES: BEGIN OF ty_folder, - path TYPE string, - count TYPE i, - sha1 TYPE ty_sha1, - END OF ty_folder. - - TYPES: ty_folders_tt TYPE STANDARD TABLE OF ty_folder WITH DEFAULT KEY. - - CLASS-METHODS build_trees - IMPORTING it_expanded TYPE ty_expanded_tt - RETURNING VALUE(rt_trees) TYPE ty_trees_tt - RAISING lcx_exception. - - CLASS-METHODS find_folders - IMPORTING it_expanded TYPE ty_expanded_tt - RETURNING VALUE(rt_folders) TYPE ty_folders_tt. - - CLASS-METHODS walk - IMPORTING it_objects TYPE lcl_git_pack=>ty_objects_tt - iv_sha1 TYPE ty_sha1 - iv_path TYPE string - CHANGING ct_files TYPE ty_files_tt - RAISING lcx_exception. - - CLASS-METHODS walk_tree - IMPORTING it_objects TYPE lcl_git_pack=>ty_objects_tt - iv_tree TYPE ty_sha1 - iv_base TYPE string - RETURNING VALUE(rt_expanded) TYPE ty_expanded_tt - RAISING lcx_exception. - - CLASS-METHODS full_tree - IMPORTING it_objects TYPE lcl_git_pack=>ty_objects_tt - iv_branch TYPE ty_sha1 - RETURNING VALUE(rt_expanded) TYPE ty_expanded_tt - RAISING lcx_exception. - - CLASS-METHODS receive_pack - IMPORTING is_comment TYPE ty_comment - io_repo TYPE REF TO lcl_repo_online - it_trees TYPE ty_trees_tt - it_blobs TYPE ty_files_tt - iv_branch TYPE ty_sha1 - RETURNING VALUE(rv_branch) TYPE ty_sha1 - RAISING lcx_exception. - -ENDCLASS. "lcl_porcelain DEFINITION - *----------------------------------------------------------------------* * INTERFACE lif_gui_page DEFINITION *----------------------------------------------------------------------* @@ -15172,81 +12516,6 @@ INTERFACE lif_gui_page. ENDINTERFACE. -*----------------------------------------------------------------------* -* CLASS lcl_persistence_user DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_persistence_user DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. - - PUBLIC SECTION. - - METHODS set_username - IMPORTING iv_username TYPE string - RAISING lcx_exception. - - METHODS get_username - RETURNING VALUE(rv_username) TYPE string - RAISING lcx_exception. - - METHODS set_email - IMPORTING iv_email TYPE string - RAISING lcx_exception. - - METHODS get_email - RETURNING VALUE(rv_email) TYPE string - RAISING lcx_exception. - - METHODS is_hidden - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RETURNING VALUE(rv_hidden) TYPE abap_bool - RAISING lcx_exception. - - METHODS hide - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RAISING lcx_exception. - - METHODS unhide - IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key - RAISING lcx_exception. - - PRIVATE SECTION. - CONSTANTS c_type_user TYPE lcl_persistence_db=>ty_type VALUE 'USER'. - - DATA: mv_user TYPE xubname. - - TYPES: - ty_repo_hidden_tt - TYPE STANDARD TABLE OF lcl_persistence_repo=>ty_repo-key - WITH DEFAULT KEY. - - TYPES: BEGIN OF ty_user, - username TYPE string, - email TYPE string, - repo_hidden TYPE ty_repo_hidden_tt, - END OF ty_user. - - METHODS constructor - IMPORTING iv_user TYPE xubname DEFAULT sy-uname. - - METHODS from_xml - IMPORTING iv_xml TYPE string - RETURNING VALUE(rs_user) TYPE ty_user - RAISING lcx_exception. - - METHODS to_xml - IMPORTING is_user TYPE ty_user - RETURNING VALUE(rv_xml) TYPE string. - - METHODS read - RETURNING VALUE(rs_user) TYPE ty_user - RAISING lcx_exception. - - METHODS update - IMPORTING is_user TYPE ty_user - RAISING lcx_exception. - -ENDCLASS. "lcl_persistence_user DEFINITION - - *----------------------------------------------------------------------* * CLASS lcl_gui_router DEFINITION *----------------------------------------------------------------------* @@ -15439,232 +12708,6 @@ CLASS lcl_repo_offline IMPLEMENTATION. ENDCLASS. "lcl_repo_offline IMPLEMENTATION -*----------------------------------------------------------------------* -* CLASS lcl_repo_srv DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_repo_srv DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. - - PUBLIC SECTION. - - TYPES: ty_repo_tt TYPE STANDARD TABLE OF REF TO lcl_repo WITH DEFAULT KEY. - - METHODS list - RETURNING VALUE(rt_list) TYPE ty_repo_tt - RAISING lcx_exception. - - METHODS refresh - RAISING lcx_exception. - - METHODS new_online - IMPORTING iv_url TYPE string - iv_branch_name TYPE string - iv_package TYPE devclass - RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo_online - RAISING lcx_exception. - - METHODS new_offline - IMPORTING iv_url TYPE string - iv_package TYPE devclass - RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo_offline - RAISING lcx_exception. - - METHODS delete - IMPORTING io_repo TYPE REF TO lcl_repo - RAISING lcx_exception. - - METHODS get - IMPORTING iv_key TYPE lcl_persistence_db=>ty_value - RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo - RAISING lcx_exception. - - METHODS is_repo_installed - IMPORTING iv_url TYPE string - iv_target_package TYPE devclass OPTIONAL - RETURNING VALUE(rv_installed) TYPE abap_bool - RAISING lcx_exception. - - METHODS get_stage - IMPORTING iv_repo_key TYPE lcl_persistence_db=>ty_value - iv_new TYPE abap_bool DEFAULT abap_false - RETURNING VALUE(ro_stage) TYPE REF TO lcl_stage - RAISING lcx_exception. - - METHODS free_stage - IMPORTING iv_repo_key TYPE lcl_persistence_db=>ty_value. - - PRIVATE SECTION. - - TYPES: BEGIN OF ty_stage_list, - repo_key TYPE lcl_persistence_db=>ty_value, - stage TYPE REF TO lcl_stage, - END OF ty_stage_list. - - METHODS constructor. - - DATA: mv_init TYPE abap_bool VALUE abap_false, - mo_persistence TYPE REF TO lcl_persistence_repo, - mt_stages TYPE TABLE OF ty_stage_list, - mt_list TYPE ty_repo_tt. - - METHODS add - IMPORTING io_repo TYPE REF TO lcl_repo - RAISING lcx_exception. - - METHODS validate_package - IMPORTING iv_package TYPE devclass - RAISING lcx_exception. - -ENDCLASS. "lcl_repo_srv DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_app DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_app DEFINITION FINAL. - PUBLIC SECTION. - - CLASS-METHODS run - RAISING lcx_exception. - - CLASS-METHODS gui - RETURNING VALUE(ro_gui) TYPE REF TO lcl_gui - RAISING lcx_exception. - - CLASS-METHODS user - IMPORTING iv_user TYPE xubname DEFAULT sy-uname - RETURNING VALUE(ro_user) TYPE REF TO lcl_persistence_user - RAISING lcx_exception. - - CLASS-METHODS repo_srv - RETURNING VALUE(ro_repo_srv) TYPE REF TO lcl_repo_srv. - - CLASS-METHODS db - RETURNING VALUE(ro_db) TYPE REF TO lcl_persistence_db. - - PRIVATE SECTION. - CLASS-DATA: go_gui TYPE REF TO lcl_gui, - go_current_user TYPE REF TO lcl_persistence_user, - go_db TYPE REF TO lcl_persistence_db, - go_repo_srv TYPE REF TO lcl_repo_srv. - -ENDCLASS. "lcl_app - -CLASS lcl_persistence_background DEFINITION FINAL. - - PUBLIC SECTION. - - CONSTANTS: BEGIN OF c_method, - nothing TYPE string VALUE 'nothing', - pull TYPE string VALUE 'pull', - push TYPE string VALUE 'push', - END OF c_method. - - TYPES: BEGIN OF ty_xml, - method TYPE string, - username TYPE string, - password TYPE string, - END OF ty_xml. - - TYPES: BEGIN OF ty_background, - key TYPE lcl_persistence_db=>ty_value. - INCLUDE TYPE ty_xml. - TYPES: END OF ty_background. - TYPES: tt_background TYPE STANDARD TABLE OF ty_background WITH DEFAULT KEY. - - METHODS constructor. - - METHODS list - RETURNING VALUE(rt_list) TYPE tt_background - RAISING lcx_exception. - - METHODS modify - IMPORTING is_data TYPE ty_background - RAISING lcx_exception. - - METHODS delete - IMPORTING iv_key TYPE ty_background-key - RAISING lcx_exception. - - PRIVATE SECTION. - CONSTANTS c_type TYPE lcl_persistence_db=>ty_type VALUE 'BACKGROUND'. - - DATA: mo_db TYPE REF TO lcl_persistence_db. - - METHODS from_xml - IMPORTING iv_string TYPE string - RETURNING VALUE(rs_xml) TYPE ty_xml - RAISING lcx_exception. - - METHODS to_xml - IMPORTING is_background TYPE ty_background - RETURNING VALUE(rv_string) TYPE string. - -ENDCLASS. "lcl_persistence_background DEFINITION - -CLASS lcl_persistence_background IMPLEMENTATION. - - METHOD constructor. - mo_db = lcl_app=>db( ). - ENDMETHOD. - - METHOD list. - - DATA: lt_list TYPE lcl_persistence_db=>tt_content, - ls_xml TYPE ty_xml. - - FIELD-SYMBOLS: LIKE LINE OF lt_list, - LIKE LINE OF rt_list. - - - lt_list = mo_db->list_by_type( c_type ). - - LOOP AT lt_list ASSIGNING . - ls_xml = from_xml( -data_str ). - - APPEND INITIAL LINE TO rt_list ASSIGNING . - MOVE-CORRESPONDING ls_xml TO . - -key = -value. - ENDLOOP. - - ENDMETHOD. - - METHOD modify. - mo_db->modify( - iv_type = c_type - iv_value = is_data-key - iv_data = to_xml( is_data ) ). - ENDMETHOD. - - METHOD delete. - TRY. - mo_db->read( iv_type = c_type - iv_value = iv_key ). - CATCH lcx_not_found. - RETURN. - ENDTRY. - - mo_db->delete( iv_type = c_type - iv_value = iv_key ). - ENDMETHOD. - - METHOD from_xml. - CALL TRANSFORMATION id - OPTIONS value_handling = 'accept_data_loss' - SOURCE XML iv_string - RESULT data = rs_xml ##NO_TEXT. - ENDMETHOD. - - METHOD to_xml. - DATA: ls_xml TYPE ty_xml. - - MOVE-CORRESPONDING is_background TO ls_xml. - - CALL TRANSFORMATION id - SOURCE data = ls_xml - RESULT XML rv_string. - ENDMETHOD. - -ENDCLASS. " lcl_persistence_background IMPLEMENTATION - *----------------------------------------------------------------------* * CLASS lcl_repo_online IMPLEMENTATION *----------------------------------------------------------------------* @@ -16294,540 +13337,6 @@ CLASS lcl_repo_srv IMPLEMENTATION. ENDCLASS. "lcl_repo_srv IMPLEMENTATION -*----------------------------------------------------------------------* -* CLASS lcl_transport DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_git_transport DEFINITION FINAL. - - PUBLIC SECTION. - TYPES: BEGIN OF ty_branch_list, - sha1 TYPE ty_sha1, - name TYPE string, - END OF ty_branch_list. - TYPES: ty_branch_list_tt TYPE STANDARD TABLE OF ty_branch_list WITH DEFAULT KEY. - -* remote to local - CLASS-METHODS upload_pack - IMPORTING io_repo TYPE REF TO lcl_repo_online - EXPORTING ev_pack TYPE xstring - ev_branch TYPE ty_sha1 - RAISING lcx_exception. - -* local to remote - CLASS-METHODS receive_pack - IMPORTING io_repo TYPE REF TO lcl_repo_online - iv_old TYPE ty_sha1 - iv_new TYPE ty_sha1 - iv_branch_name TYPE string - iv_pack TYPE xstring - RAISING lcx_exception. - - CLASS-METHODS branches - IMPORTING iv_url TYPE string - RETURNING VALUE(rt_branch_list) TYPE ty_branch_list_tt - RAISING lcx_exception. - - CLASS-METHODS class_constructor. - - PRIVATE SECTION. - CLASS-DATA: gv_agent TYPE string. - - CONSTANTS: BEGIN OF c_service, - receive TYPE string VALUE 'receive', "#EC NOTEXT - upload TYPE string VALUE 'upload', "#EC NOTEXT - END OF c_service. - - CLASS-METHODS branch_list - IMPORTING iv_url TYPE string - iv_service TYPE string - EXPORTING ei_client TYPE REF TO if_http_client - et_branch_list TYPE ty_branch_list_tt - RAISING lcx_exception. - - CLASS-METHODS pkt_string - IMPORTING iv_string TYPE string - RETURNING VALUE(rv_pkt) TYPE string - RAISING lcx_exception. - - CLASS-METHODS find_branch - IMPORTING io_repo TYPE REF TO lcl_repo_online - iv_service TYPE string - EXPORTING ei_client TYPE REF TO if_http_client - ev_branch TYPE ty_sha1 - RAISING lcx_exception. - - CLASS-METHODS parse - EXPORTING ev_pack TYPE xstring - CHANGING cv_data TYPE xstring - RAISING lcx_exception. - - CLASS-METHODS length_utf8_hex - IMPORTING iv_data TYPE xstring - RETURNING VALUE(rv_len) TYPE i - RAISING lcx_exception. - - CLASS-METHODS parse_branch_list - IMPORTING iv_data TYPE string - RETURNING VALUE(rt_list) TYPE ty_branch_list_tt - RAISING lcx_exception. - - CLASS-METHODS set_headers - IMPORTING io_repo TYPE REF TO lcl_repo_online - iv_service TYPE string - ii_client TYPE REF TO if_http_client - RAISING lcx_exception. - - CLASS-METHODS check_http_200 - IMPORTING ii_client TYPE REF TO if_http_client - RAISING lcx_exception. - - CLASS-METHODS get_null - RETURNING VALUE(rv_c) TYPE char1. - -ENDCLASS. "lcl_transport DEFINITION - -*----------------------------------------------------------------------* -* CLASS lcl_transport IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_git_transport IMPLEMENTATION. - - METHOD class_constructor. - -* bitbucket require agent prefix = "git/" - gv_agent = 'git/abapGit ' && gc_abap_version. - - ENDMETHOD. "class_constructor - - METHOD set_headers. - - DATA: lv_value TYPE string. - - - ii_client->request->set_header_field( - name = '~request_method' - value = 'POST' ). - - lv_value = lcl_url=>path_name( io_repo->get_url( ) ) && - '.git/git-' && - iv_service && - '-pack'. - ii_client->request->set_header_field( - name = '~request_uri' - value = lv_value ). - - lv_value = 'application/x-git-' - && iv_service && '-pack-request'. "#EC NOTEXT - ii_client->request->set_header_field( - name = 'Content-Type' - value = lv_value ). "#EC NOTEXT - - lv_value = 'application/x-git-' - && iv_service && '-pack-result'. "#EC NOTEXT - ii_client->request->set_header_field( - name = 'Accept' - value = lv_value ). "#EC NOTEXT - - ENDMETHOD. "set_headers - - METHOD get_null. - - DATA: lv_x(4) TYPE x VALUE '00000000', - lv_z(2) TYPE c. - - FIELD-SYMBOLS TYPE c. - - - ASSIGN lv_x TO CASTING. - lv_z = . - rv_c = lv_z(1). - - ENDMETHOD. "get_null - - METHOD check_http_200. - - DATA: lv_code TYPE i. - - - ii_client->response->get_status( - IMPORTING - code = lv_code ). - CASE lv_code. - WHEN 200. - RETURN. - WHEN 302. - _raise 'HTTP redirect, check URL'. - WHEN 401. - _raise 'HTTP 401, unauthorized'. - WHEN 403. - _raise 'HTTP 403, forbidden'. - WHEN 404. - _raise 'HTTP 404, not found'. - WHEN 415. - _raise 'HTTP 415, unsupported media type'. - WHEN OTHERS. - _raise 'HTTP error code'. - ENDCASE. - - ENDMETHOD. "http_200 - - METHOD parse_branch_list. - - DATA: lt_result TYPE TABLE OF string, - lv_hash TYPE ty_sha1, - lv_name TYPE string, - lv_foo TYPE string ##needed, - lv_char TYPE c, - lv_data LIKE LINE OF lt_result. - - FIELD-SYMBOLS: LIKE LINE OF rt_list. - - - SPLIT iv_data AT gc_newline INTO TABLE lt_result. - LOOP AT lt_result INTO lv_data. - IF sy-tabix = 1. - CONTINUE. " current loop - ELSEIF sy-tabix = 2 AND strlen( lv_data ) > 49. - lv_hash = lv_data+8. - lv_name = lv_data+49. - lv_char = get_null( ). - SPLIT lv_name AT lv_char INTO lv_name lv_foo. - ELSEIF sy-tabix > 2 AND strlen( lv_data ) > 45. - lv_hash = lv_data+4. - lv_name = lv_data+45. - ELSEIF sy-tabix = 2 AND strlen( lv_data ) = 8 AND lv_data(8) = '00000000'. - _raise 'No branches, create branch manually by adding file'. - ELSE. - CONTINUE. - ENDIF. - - IF lv_name CP 'refs/pull/*'. - CONTINUE. - ENDIF. - - APPEND INITIAL LINE TO rt_list ASSIGNING . - -sha1 = lv_hash. - -name = lv_name. - ENDLOOP. - - ENDMETHOD. "parse_branch_list - - METHOD find_branch. - - DATA: lt_branch_list TYPE ty_branch_list_tt, - ls_branch_list LIKE LINE OF lt_branch_list. - - - branch_list( - EXPORTING - iv_url = io_repo->get_url( ) - iv_service = iv_service - IMPORTING - ei_client = ei_client - et_branch_list = lt_branch_list ). - - IF io_repo->get_branch_name( ) IS INITIAL. - _raise 'branch empty'. - ENDIF. - - READ TABLE lt_branch_list INTO ls_branch_list - WITH KEY name = io_repo->get_branch_name( ). - IF sy-subrc <> 0. - _raise 'Branch not found'. - ENDIF. - - ev_branch = ls_branch_list-sha1. - - ENDMETHOD. "find_branch - - METHOD branches. - - DATA: li_client TYPE REF TO if_http_client. - - - lcl_git_transport=>branch_list( - EXPORTING - iv_url = iv_url - iv_service = c_service-upload - IMPORTING - ei_client = li_client - et_branch_list = rt_branch_list ). - li_client->close( ). - - ENDMETHOD. "branches - - METHOD branch_list. - - DATA: lv_data TYPE string, - lv_uri TYPE string, - lv_text TYPE string. - - - cl_http_client=>create_by_url( - EXPORTING - url = lcl_url=>host( iv_url ) - ssl_id = 'ANONYM' - IMPORTING - client = ei_client ). - - ei_client->request->set_cdata( '' ). - ei_client->request->set_header_field( - name = '~request_method' - value = 'GET' ). - ei_client->request->set_header_field( - name = 'user-agent' - value = gv_agent ). "#EC NOTEXT - lv_uri = lcl_url=>path_name( iv_url ) && - '.git/info/refs?service=git-' && - iv_service && - '-pack'. - ei_client->request->set_header_field( - name = '~request_uri' - value = lv_uri ). - - lcl_login_manager=>load( iv_uri = iv_url - ii_client = ei_client ). - - ei_client->send( ). - ei_client->receive( - EXCEPTIONS - http_communication_failure = 1 - http_invalid_state = 2 - http_processing_failed = 3 - OTHERS = 4 ). - IF sy-subrc <> 0. - CASE sy-subrc. - WHEN 1. -* make sure: -* a) SSL is setup properly in STRUST -* b) no firewalls -* check trace file in transaction SMICM - lv_text = 'HTTP Communication Failure'. "#EC NOTEXT - WHEN 2. - lv_text = 'HTTP Invalid State'. "#EC NOTEXT - WHEN 3. - lv_text = 'HTTP Processing failed'. "#EC NOTEXT - WHEN OTHERS. - lv_text = 'Another error occured'. "#EC NOTEXT - ENDCASE. - RAISE EXCEPTION TYPE lcx_exception - EXPORTING - iv_text = lv_text. - ENDIF. - - check_http_200( ei_client ). - - lcl_login_manager=>save( iv_uri = iv_url - ii_client = ei_client ). - - lv_data = ei_client->response->get_cdata( ). - et_branch_list = parse_branch_list( lv_data ). - - ENDMETHOD. "ref_discovery - - METHOD receive_pack. - - DATA: li_client TYPE REF TO if_http_client, - lv_cmd_pkt TYPE string, - lv_line TYPE string, - lv_tmp TYPE xstring, - lv_xstring TYPE xstring, - lv_string TYPE string, - lv_cap_list TYPE string, - lv_buffer TYPE string. - - - find_branch( - EXPORTING - io_repo = io_repo - iv_service = c_service-receive - IMPORTING - ei_client = li_client ). - - set_headers( - io_repo = io_repo - iv_service = c_service-receive - ii_client = li_client ). - - lv_cap_list = 'report-status agent=' && gv_agent. - - lv_line = iv_old && - ` ` && - iv_new && - ` ` && - iv_branch_name && - get_null( ) && - ` ` && - lv_cap_list && - gc_newline. "#EC NOTEXT - lv_cmd_pkt = pkt_string( lv_line ). - - lv_buffer = lv_cmd_pkt && '0000'. - lv_tmp = lcl_convert=>string_to_xstring_utf8( lv_buffer ). - - CONCATENATE lv_tmp iv_pack INTO lv_xstring IN BYTE MODE. - - li_client->request->set_data( lv_xstring ). - - li_client->send( ). - li_client->receive( ). - check_http_200( li_client ). - - lv_xstring = li_client->response->get_data( ). - li_client->close( ). - - lv_string = lcl_convert=>xstring_to_string_utf8( lv_xstring ). - IF NOT lv_string CP '*unpack ok*'. - _raise 'unpack not ok'. - ELSEIF lv_string CP '*pre-receive hook declined*'. - _raise 'pre-receive hook declined'. - ENDIF. - - ENDMETHOD. "receive_pack - - METHOD length_utf8_hex. - - DATA: lv_xstring TYPE xstring, - lv_string TYPE string, - lv_char4 TYPE c LENGTH 4, - lv_x TYPE x LENGTH 2, - lo_obj TYPE REF TO cl_abap_conv_in_ce, - lv_len TYPE int4. - -* hmm, can this be done easier? - - lv_xstring = iv_data(4). - - lo_obj = cl_abap_conv_in_ce=>create( - input = lv_xstring - encoding = 'UTF-8' ). - lv_len = xstrlen( lv_xstring ). - - TRY. - lo_obj->read( EXPORTING n = lv_len - IMPORTING data = lv_string ). - CATCH cx_sy_conversion_codepage. - _raise 'error converting to hex, LENGTH_UTF8_HEX'. - ENDTRY. - - lv_char4 = lv_string. - TRANSLATE lv_char4 TO UPPER CASE. - lv_x = lv_char4. - rv_len = lv_x. - - ENDMETHOD. "length_utf8_hex - - METHOD parse. - - CONSTANTS: lc_band1 TYPE x VALUE '01'. - - DATA: lv_len TYPE i, - lv_contents TYPE xstring, - lv_pack TYPE xstring. - - - WHILE xstrlen( cv_data ) >= 4. - lv_len = length_utf8_hex( cv_data ). - - IF lv_len > xstrlen( cv_data ). - _raise 'parse, string length too large'. - ENDIF. - - lv_contents = cv_data(lv_len). - IF lv_len = 0. - cv_data = cv_data+4. - CONTINUE. - ELSE. - cv_data = cv_data+lv_len. - ENDIF. - - lv_contents = lv_contents+4. - - IF xstrlen( lv_contents ) > 1 AND lv_contents(1) = lc_band1. - CONCATENATE lv_pack lv_contents+1 INTO lv_pack IN BYTE MODE. - ENDIF. - - ENDWHILE. - - ev_pack = lv_pack. - - ENDMETHOD. "parse - - METHOD upload_pack. - - DATA: li_client TYPE REF TO if_http_client, - lv_buffer TYPE string, - lv_xstring TYPE xstring, - lv_line TYPE string, - lv_pkt1 TYPE string, - lv_pkt2 TYPE string. - - - find_branch( - EXPORTING - io_repo = io_repo - iv_service = c_service-upload - IMPORTING - ei_client = li_client - ev_branch = ev_branch ). - - set_headers( - io_repo = io_repo - iv_service = c_service-upload - ii_client = li_client ). - - lv_line = 'want' && - ` ` && - ev_branch && - ` ` && - 'side-band-64k no-progress agent=' && gv_agent - && gc_newline. "#EC NOTEXT - lv_pkt1 = pkt_string( lv_line ). - - lv_pkt2 = pkt_string( 'deepen 1' && gc_newline ). "#EC NOTEXT - - lv_buffer = lv_pkt1 - && lv_pkt2 - && '0000' - && '0009done' && gc_newline. - -* do not use set_cdata as it modifies the Content-Type header field - li_client->request->set_data( lcl_convert=>string_to_xstring_utf8( lv_buffer ) ). - li_client->send( ). - li_client->receive( ). - check_http_200( li_client ). - lv_xstring = li_client->response->get_data( ). - li_client->close( ). - - parse( IMPORTING ev_pack = ev_pack - CHANGING cv_data = lv_xstring ). - - ENDMETHOD. "upload_pack - - METHOD pkt_string. - - DATA: lv_x TYPE x, - lv_len TYPE i. - - - lv_len = strlen( iv_string ). - - IF lv_len >= 255. - _raise 'PKT, todo'. - ENDIF. - - lv_x = lv_len + 4. - - rv_pkt = rv_pkt && '00' && lv_x && iv_string. - - ENDMETHOD. "pkt - -ENDCLASS. "lcl_transport IMPLEMENTATION - - *----------------------------------------------------------------------* * CLASS lcl_zip DEFINITION *----------------------------------------------------------------------* @@ -17313,391 +13822,6 @@ CLASS lcl_zip IMPLEMENTATION. ENDCLASS. "lcl_zip IMPLEMENTATION -*----------------------------------------------------------------------* -* CLASS lcl_porcelain IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_git_porcelain IMPLEMENTATION. - - METHOD receive_pack. - - DATA: lv_time TYPE lcl_time=>ty_unixtime, - lv_commit TYPE xstring, - lt_objects TYPE lcl_git_pack=>ty_objects_tt, - lv_pack TYPE xstring, - ls_object LIKE LINE OF lt_objects, - ls_commit TYPE lcl_git_pack=>ty_commit. - - FIELD-SYMBOLS: LIKE LINE OF it_trees, - LIKE LINE OF it_blobs. - - - lv_time = lcl_time=>get( ). - - READ TABLE it_trees ASSIGNING WITH KEY path = '/'. - ASSERT sy-subrc = 0. - -* new commit - ls_commit-tree = -sha1. - ls_commit-parent = iv_branch. - CONCATENATE is_comment-username space '<' is_comment-email '>' space lv_time - INTO ls_commit-author RESPECTING BLANKS. - ls_commit-committer = ls_commit-author. - ls_commit-body = is_comment-comment. - lv_commit = lcl_git_pack=>encode_commit( ls_commit ). - - CLEAR ls_object. - ls_object-sha1 = lcl_hash=>sha1( iv_type = gc_type-commit iv_data = lv_commit ). - ls_object-type = gc_type-commit. - ls_object-data = lv_commit. - APPEND ls_object TO lt_objects. - - LOOP AT it_trees ASSIGNING . - CLEAR ls_object. - ls_object-sha1 = -sha1. - ls_object-type = gc_type-tree. - ls_object-data = -data. - APPEND ls_object TO lt_objects. - ENDLOOP. - - LOOP AT it_blobs ASSIGNING . - CLEAR ls_object. - ls_object-sha1 = lcl_hash=>sha1( iv_type = gc_type-blob iv_data = -data ). - ls_object-type = gc_type-blob. - ls_object-data = -data. - APPEND ls_object TO lt_objects. - ENDLOOP. - - lv_pack = lcl_git_pack=>encode( lt_objects ). - - rv_branch = lcl_hash=>sha1( - iv_type = gc_type-commit - iv_data = lv_commit ). - - lcl_git_transport=>receive_pack( - io_repo = io_repo - iv_old = io_repo->get_sha1_local( ) - iv_new = rv_branch - iv_branch_name = io_repo->get_branch_name( ) - iv_pack = lv_pack ). - - ENDMETHOD. "receive_pack - - METHOD create_branch. - - DATA: lv_zero TYPE ty_sha1, - lt_objects TYPE lcl_git_pack=>ty_objects_tt, - lv_pack TYPE xstring. - - - lv_zero = '0000000000000000000000000000000000000000'. - -* "client MUST send an empty packfile" -* https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L514 - lv_pack = lcl_git_pack=>encode( lt_objects ). - - lcl_git_transport=>receive_pack( - io_repo = io_repo - iv_old = lv_zero - iv_new = iv_from - iv_branch_name = iv_name - iv_pack = lv_pack ). - - ENDMETHOD. - - METHOD push. - - DATA: lt_expanded TYPE ty_expanded_tt, - lt_blobs TYPE ty_files_tt, - lv_sha1 TYPE ty_sha1, - lt_trees TYPE ty_trees_tt, - lt_stage TYPE lcl_stage=>ty_stage_tt. - - FIELD-SYMBOLS: LIKE LINE OF lt_stage, - LIKE LINE OF lt_expanded. - - - lt_expanded = full_tree( it_objects = io_repo->get_objects( ) - iv_branch = io_repo->get_sha1_remote( ) ). - - lt_stage = io_stage->get_all( ). - LOOP AT lt_stage ASSIGNING . - CASE -method. - WHEN lcl_stage=>c_method-add. - APPEND -file TO lt_blobs. - - READ TABLE lt_expanded ASSIGNING WITH KEY - name = -file-filename - path = -file-path. - IF sy-subrc <> 0. " new files - APPEND INITIAL LINE TO lt_expanded ASSIGNING . - -name = -file-filename. - -path = -file-path. - -chmod = gc_chmod-file. - ENDIF. - - lv_sha1 = lcl_hash=>sha1( iv_type = gc_type-blob iv_data = -file-data ). - IF -sha1 <> lv_sha1. - -sha1 = lv_sha1. - ENDIF. - WHEN lcl_stage=>c_method-rm. - DELETE lt_expanded - WHERE name = -file-filename - AND path = -file-path. - ASSERT sy-subrc = 0. - WHEN OTHERS. - _raise 'stage method not supported, todo'. - ENDCASE. - ENDLOOP. - - lt_trees = build_trees( lt_expanded ). - - rv_branch = receive_pack( is_comment = is_comment - io_repo = io_repo - it_trees = lt_trees - it_blobs = lt_blobs - iv_branch = io_repo->get_sha1_remote( ) ). - - ENDMETHOD. "push - - METHOD walk_tree. - - DATA: ls_object LIKE LINE OF it_objects, - lt_expanded LIKE rt_expanded, - lt_nodes TYPE lcl_git_pack=>ty_nodes_tt. - - FIELD-SYMBOLS: LIKE LINE OF rt_expanded, - LIKE LINE OF lt_nodes. - - - READ TABLE it_objects INTO ls_object - WITH KEY sha1 = iv_tree - type = gc_type-tree. - IF sy-subrc <> 0. - _raise 'tree not found'. - ENDIF. - lt_nodes = lcl_git_pack=>decode_tree( ls_object-data ). - - LOOP AT lt_nodes ASSIGNING . - CASE -chmod. - WHEN gc_chmod-file - OR gc_chmod-executable. - APPEND INITIAL LINE TO rt_expanded ASSIGNING . - -path = iv_base. - -name = -name. - -sha1 = -sha1. - -chmod = -chmod. - WHEN gc_chmod-dir. - lt_expanded = walk_tree( - it_objects = it_objects - iv_tree = -sha1 - iv_base = iv_base && -name && '/' ). - APPEND LINES OF lt_expanded TO rt_expanded. - WHEN OTHERS. - _raise 'walk_tree: unknown chmod'. - ENDCASE. - ENDLOOP. - - ENDMETHOD. - - METHOD full_tree. - - DATA: ls_object LIKE LINE OF it_objects, - ls_commit TYPE lcl_git_pack=>ty_commit. - - - READ TABLE it_objects INTO ls_object WITH KEY sha1 = iv_branch type = gc_type-commit. - IF sy-subrc <> 0. - _raise 'commit not found'. - ENDIF. - ls_commit = lcl_git_pack=>decode_commit( ls_object-data ). - - rt_expanded = walk_tree( it_objects = it_objects - iv_tree = ls_commit-tree - iv_base = '/' ). - - ENDMETHOD. "root_tree - - METHOD pull. - - DATA: ls_object LIKE LINE OF et_objects, - ls_commit TYPE lcl_git_pack=>ty_commit, - lv_pack TYPE xstring. - - - CLEAR et_files. - CLEAR et_objects. - CLEAR ev_branch. - - lcl_git_transport=>upload_pack( EXPORTING io_repo = io_repo - IMPORTING ev_pack = lv_pack - ev_branch = ev_branch ). - - IF lv_pack IS INITIAL. - _raise 'empty pack'. - ENDIF. - - et_objects = lcl_git_pack=>decode( lv_pack ). - - lcl_git_pack=>decode_deltas( CHANGING ct_objects = et_objects ). - - READ TABLE et_objects INTO ls_object WITH KEY sha1 = ev_branch type = gc_type-commit. - IF sy-subrc <> 0. - _raise 'Commit/branch not found'. - ENDIF. - ls_commit = lcl_git_pack=>decode_commit( ls_object-data ). - - walk( EXPORTING it_objects = et_objects - iv_sha1 = ls_commit-tree - iv_path = '/' - CHANGING ct_files = et_files ). - - ENDMETHOD. "pull - - METHOD find_folders. - - DATA: lt_paths TYPE TABLE OF string, - lv_split TYPE string, - lv_path TYPE string. - - FIELD-SYMBOLS: LIKE LINE OF rt_folders, - LIKE LINE OF rt_folders, - LIKE LINE OF it_expanded. - - - LOOP AT it_expanded ASSIGNING . - READ TABLE rt_folders WITH KEY path = -path TRANSPORTING NO FIELDS. - IF sy-subrc <> 0. - APPEND INITIAL LINE TO rt_folders ASSIGNING . - -path = -path. - ENDIF. - ENDLOOP. - -* add empty folders - LOOP AT rt_folders ASSIGNING . - SPLIT -path AT '/' INTO TABLE lt_paths. - - CLEAR lv_path. - LOOP AT lt_paths INTO lv_split. - CONCATENATE lv_path lv_split '/' INTO lv_path. - READ TABLE rt_folders WITH KEY path = lv_path TRANSPORTING NO FIELDS. - IF sy-subrc <> 0. - APPEND INITIAL LINE TO rt_folders ASSIGNING . - -path = lv_path. - ENDIF. - ENDLOOP. - ENDLOOP. - - LOOP AT rt_folders ASSIGNING . - FIND ALL OCCURRENCES OF '/' IN -path MATCH COUNT -count. - ENDLOOP. - - ENDMETHOD. - - METHOD build_trees. - - DATA: lt_nodes TYPE lcl_git_pack=>ty_nodes_tt, - ls_tree LIKE LINE OF rt_trees, - lv_sub TYPE string, - lv_len TYPE i, - lt_folders TYPE ty_folders_tt. - - FIELD-SYMBOLS: LIKE LINE OF lt_folders, - LIKE LINE OF lt_nodes, - LIKE LINE OF lt_folders, - LIKE LINE OF it_expanded. - - - lt_folders = find_folders( it_expanded ). - -* start with the deepest folders - SORT lt_folders BY count DESCENDING. - - LOOP AT lt_folders ASSIGNING . - CLEAR lt_nodes. - -* files - LOOP AT it_expanded ASSIGNING WHERE path = -path. - APPEND INITIAL LINE TO lt_nodes ASSIGNING . - -chmod = -chmod. - -name = -name. - -sha1 = -sha1. - ENDLOOP. - -* folders - lv_sub = -path && '+*'. - LOOP AT lt_folders ASSIGNING - WHERE count = -count + 1 AND path CP lv_sub. - APPEND INITIAL LINE TO lt_nodes ASSIGNING . - -chmod = gc_chmod-dir. - -* extract folder name, this can probably be done easier using regular expressions - lv_len = strlen( -path ). - -name = -path+lv_len. - lv_len = strlen( -name ) - 1. - -name = -name(lv_len). - - -sha1 = -sha1. - ENDLOOP. - - CLEAR ls_tree. - ls_tree-path = -path. - ls_tree-data = lcl_git_pack=>encode_tree( lt_nodes ). - ls_tree-sha1 = lcl_hash=>sha1( iv_type = gc_type-tree iv_data = ls_tree-data ). - APPEND ls_tree TO rt_trees. - - -sha1 = ls_tree-sha1. - ENDLOOP. - - ENDMETHOD. - - METHOD walk. - - DATA: lv_path TYPE string, - ls_file LIKE LINE OF ct_files, - lt_nodes TYPE lcl_git_pack=>ty_nodes_tt. - - FIELD-SYMBOLS: LIKE LINE OF it_objects, - LIKE LINE OF it_objects, - LIKE LINE OF lt_nodes. - - - READ TABLE it_objects ASSIGNING WITH KEY sha1 = iv_sha1 type = gc_type-tree. - IF sy-subrc <> 0. - _raise 'Walk, tree not found'. - ENDIF. - - lt_nodes = lcl_git_pack=>decode_tree( -data ). - - LOOP AT lt_nodes ASSIGNING . - IF -chmod = gc_chmod-file. - READ TABLE it_objects ASSIGNING - WITH KEY sha1 = -sha1 type = gc_type-blob. - IF sy-subrc <> 0. - _raise 'Walk, blob not found'. - ENDIF. - - CLEAR ls_file. - ls_file-path = iv_path. - ls_file-filename = -name. - ls_file-data = -data. - APPEND ls_file TO ct_files. - ENDIF. - ENDLOOP. - - LOOP AT lt_nodes ASSIGNING WHERE chmod = gc_chmod-dir. - CONCATENATE iv_path -name '/' INTO lv_path. - walk( EXPORTING it_objects = it_objects - iv_sha1 = -sha1 - iv_path = lv_path - CHANGING ct_files = ct_files ). - ENDLOOP. - - ENDMETHOD. "walk - -ENDCLASS. "lcl_porcelain IMPLEMENTATION - *----------------------------------------------------------------------* * CLASS lcl_view IMPLEMENTATION *----------------------------------------------------------------------* @@ -18643,156 +14767,6 @@ CLASS lcl_gui_page_diff IMPLEMENTATION. ENDCLASS. -CLASS lcl_stage IMPLEMENTATION. - - METHOD constructor. - DATA: ls_files TYPE lcl_stage_logic=>ty_stage_files, - lo_repo TYPE REF TO lcl_repo_online, - ls_work_file LIKE LINE OF mt_workarea. - - FIELD-SYMBOLS: LIKE LINE OF ls_files-local, - LIKE LINE OF ls_files-remote. - - mv_repo_key = iv_repo_key. - lo_repo ?= lcl_app=>repo_srv( )->get( iv_repo_key ). - ls_files = lcl_stage_logic=>get( lo_repo ). - - " Unify structures - LOOP AT ls_files-local ASSIGNING . - ls_work_file-type = c_wftype-local. - ls_work_file-file = -file. - APPEND ls_work_file TO mt_workarea. - mv_local_cnt = mv_local_cnt + 1. - ENDLOOP. - - LOOP AT ls_files-remote ASSIGNING . - ls_work_file-type = c_wftype-remote. - ls_work_file-file = . - APPEND ls_work_file TO mt_workarea. - ENDLOOP. - - ENDMETHOD. "constructor - - METHOD lookup. - DATA ls_stage LIKE LINE OF mt_stage. - - READ TABLE mt_stage INTO ls_stage - WITH KEY file-path = iv_path - file-filename = iv_filename. - IF sy-subrc = 0. - rv_method = ls_stage-method. - ENDIF. - - ENDMETHOD. "lookup - - METHOD get_all. - rt_stage = mt_stage. - ENDMETHOD. "get_all - - METHOD append. - - DATA: ls_stage LIKE LINE OF mt_stage, - ls_file TYPE ty_file. - - FIELD-SYMBOLS: LIKE LINE OF mt_stage. - - ls_file = find_work_file( iv_path = iv_path iv_filename = iv_filename ). - - READ TABLE mt_stage WITH KEY - file-path = ls_file-path - file-filename = ls_file-filename - ASSIGNING . - IF sy-subrc = 0. - -file-data = ls_file-data. - -method = iv_method. - ELSE. - ls_stage-file = ls_file. - ls_stage-method = iv_method. - INSERT ls_stage INTO TABLE mt_stage. - ENDIF. - - ENDMETHOD. "append - - METHOD method_description. - - CASE iv_method. - WHEN c_method-add. - rv_description = 'add'. - WHEN c_method-rm. - rv_description = 'rm'. - WHEN c_method-ignore. - rv_description = 'ignore' ##NO_TEXT. - WHEN OTHERS. - _raise 'unknown staging method type'. - ENDCASE. - - ENDMETHOD. "method_description - - METHOD add. - append( iv_path = iv_path - iv_filename = iv_filename - iv_method = c_method-add ). - ENDMETHOD. "add - - METHOD reset. - DELETE mt_stage WHERE file-path = iv_path - AND file-filename = iv_filename. - ASSERT sy-subrc = 0. - ENDMETHOD. "reset - - METHOD rm. - append( iv_path = iv_path - iv_filename = iv_filename - iv_method = c_method-rm ). - ENDMETHOD. "rm - - METHOD ignore. - append( iv_path = iv_path - iv_filename = iv_filename - iv_method = c_method-ignore ). - ENDMETHOD. "ignore - - METHOD count. - rv_count = lines( mt_stage ). - ENDMETHOD. "count - - METHOD find_work_file. - DATA ls_work_file LIKE LINE OF mt_workarea. - - READ TABLE mt_workarea INTO ls_work_file - WITH KEY file-path = iv_path - file-filename = iv_filename. - IF sy-subrc = 0. - rs_file = ls_work_file-file. - ELSE. - _raise 'File not found in workarea'. - ENDIF. - - ENDMETHOD. "check_work_file_exists - - METHOD update_and_add_dot_abapgit. - - FIELD-SYMBOLS LIKE LINE OF mt_workarea. - - READ TABLE mt_workarea ASSIGNING - WITH KEY file-path = gc_root_dir - file-filename = gc_dot_abapgit. - IF sy-subrc <> 0. - APPEND INITIAL LINE TO mt_workarea ASSIGNING . - -type = c_wftype-local. - -file-path = gc_root_dir. - -file-filename = gc_dot_abapgit. - ENDIF. - - -file-data = iv_data. - - add( iv_path = gc_root_dir - iv_filename = gc_dot_abapgit ). - - ENDMETHOD. "update_and_add_dot_abapgit - -ENDCLASS. - CLASS lcl_background DEFINITION FINAL. PUBLIC SECTION. @@ -18896,6 +14870,67 @@ CLASS lcl_gui_page_background DEFINITION FINAL ENDCLASS. +*----------------------------------------------------------------------* +* CLASS lcl_app IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_app IMPLEMENTATION. + + METHOD run. + + IF sy-batch = abap_true. + lcl_background=>run( ). + ELSE. + gui( )->go_home( ). + CALL SELECTION-SCREEN 1001. " trigger screen + ENDIF. + + ENDMETHOD. "run + + METHOD gui. + + IF go_gui IS NOT BOUND. + CREATE OBJECT go_gui. + ENDIF. + ro_gui = go_gui. + + ENDMETHOD. "gui + + METHOD user. + + IF iv_user = sy-uname ##USER_OK. + IF go_current_user IS NOT BOUND. + CREATE OBJECT go_current_user. + ENDIF. + ro_user = go_current_user. + ELSE. + CREATE OBJECT ro_user + EXPORTING + iv_user = iv_user. + ENDIF. + + ENDMETHOD. "user + + METHOD repo_srv. + + IF go_repo_srv IS NOT BOUND. + CREATE OBJECT go_repo_srv. + ENDIF. + ro_repo_srv = go_repo_srv. + + ENDMETHOD. "repo_srv + + METHOD db. + + IF go_db IS NOT BOUND. + CREATE OBJECT go_db. + ENDIF. + ro_db = go_db. + + ENDMETHOD. "repo_srv + +ENDCLASS. "lcl_app + + CLASS lcl_gui_page_background IMPLEMENTATION. METHOD parse_fields. @@ -19817,7 +15852,7 @@ CLASS lcl_gui_page_main IMPLEMENTATION. lt_tadir TYPE lcl_tadir=>ty_tadir_tt, ls_repo_item TYPE ty_repo_item, ls_file TYPE ty_repo_file, - lt_results TYPE lcl_file_status=>ty_results_tt. + lt_results TYPE ty_results_tt. FIELD-SYMBOLS: LIKE LINE OF lt_results, LIKE LINE OF lt_tadir. @@ -20226,67 +16261,6 @@ CLASS lcl_background IMPLEMENTATION. ENDCLASS. -*----------------------------------------------------------------------* -* CLASS lcl_app IMPLEMENTATION -*----------------------------------------------------------------------* -CLASS lcl_app IMPLEMENTATION. - - METHOD run. - - IF sy-batch = abap_true. - lcl_background=>run( ). - ELSE. - gui( )->go_home( ). - CALL SELECTION-SCREEN 1001. " trigger screen - ENDIF. - - ENDMETHOD. "run - - METHOD gui. - - IF go_gui IS NOT BOUND. - CREATE OBJECT go_gui. - ENDIF. - ro_gui = go_gui. - - ENDMETHOD. "gui - - METHOD user. - - IF iv_user = sy-uname ##USER_OK. - IF go_current_user IS NOT BOUND. - CREATE OBJECT go_current_user. - ENDIF. - ro_user = go_current_user. - ELSE. - CREATE OBJECT ro_user - EXPORTING - iv_user = iv_user. - ENDIF. - - ENDMETHOD. "user - - METHOD repo_srv. - - IF go_repo_srv IS NOT BOUND. - CREATE OBJECT go_repo_srv. - ENDIF. - ro_repo_srv = go_repo_srv. - - ENDMETHOD. "repo_srv - - METHOD db. - - IF go_db IS NOT BOUND. - CREATE OBJECT go_db. - ENDIF. - ro_db = go_db. - - ENDMETHOD. "repo_srv - -ENDCLASS. "lcl_app - - *&---------------------------------------------------------------------* *& Form run *&---------------------------------------------------------------------* @@ -20434,752 +16408,6 @@ FORM branch_popup TABLES tt_fields STRUCTURE sval ENDFORM. "branch_popup -CLASS lcl_persistence_user IMPLEMENTATION. - - METHOD constructor. - mv_user = iv_user. - ENDMETHOD. - - METHOD from_xml. - - DATA: lv_xml TYPE string. - - lv_xml = iv_xml. - -* fix downward compatibility - REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_USER_--29>' IN lv_xml WITH ''. - REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. - - CALL TRANSFORMATION id - OPTIONS value_handling = 'accept_data_loss' - SOURCE XML lv_xml - RESULT user = rs_user ##NO_TEXT. - ENDMETHOD. - - METHOD to_xml. - CALL TRANSFORMATION id - SOURCE user = is_user - RESULT XML rv_xml. - ENDMETHOD. - - METHOD read. - - DATA: lv_xml TYPE string. - - TRY. - lv_xml = lcl_app=>db( )->read( - iv_type = c_type_user - iv_value = mv_user ). - CATCH lcx_not_found. - RETURN. - ENDTRY. - - rs_user = from_xml( lv_xml ). - - ENDMETHOD. - - METHOD update. - - DATA: lv_xml TYPE string. - - lv_xml = to_xml( is_user ). - - lcl_app=>db( )->modify( - iv_type = c_type_user - iv_value = mv_user - iv_data = lv_xml ). - - ENDMETHOD. - - METHOD set_username. - - DATA: ls_user TYPE ty_user. - - - ls_user = read( ). - - ls_user-username = iv_username. - - update( ls_user ). - - ENDMETHOD. - - METHOD get_username. - - rv_username = read( )-username. - - ENDMETHOD. - - METHOD is_hidden. - - DATA: lt_hidden TYPE ty_repo_hidden_tt. - - - lt_hidden = read( )-repo_hidden. - READ TABLE lt_hidden FROM iv_key TRANSPORTING NO FIELDS. - IF sy-subrc = 0. - rv_hidden = abap_true. - ELSE. - rv_hidden = abap_false. - ENDIF. - - ENDMETHOD. - - METHOD hide. - - DATA: ls_user TYPE ty_user. - - - ls_user = read( ). - APPEND iv_key TO ls_user-repo_hidden. - update( ls_user ). - - ENDMETHOD. - - METHOD unhide. - - DATA: ls_user TYPE ty_user. - - - ls_user = read( ). - DELETE TABLE ls_user-repo_hidden FROM iv_key. - update( ls_user ). - - ENDMETHOD. - - METHOD set_email. - - DATA: ls_user TYPE ty_user. - - - ls_user = read( ). - ls_user-email = iv_email. - update( ls_user ). - - ENDMETHOD. - - METHOD get_email. - - rv_email = read( )-email. - - ENDMETHOD. - -ENDCLASS. - -CLASS lcl_persistence_db IMPLEMENTATION. - - METHOD list_by_type. - SELECT * FROM (c_tabname) - INTO TABLE rt_content - WHERE type = iv_type. "#EC CI_SUBRC - ENDMETHOD. - - METHOD list. - SELECT * FROM (c_tabname) - INTO TABLE rt_content. "#EC CI_SUBRC - ENDMETHOD. - - METHOD lock. - - CALL FUNCTION 'ENQUEUE_EZABAPGIT' - EXPORTING - mode_zabapgit = iv_mode - type = iv_type - value = iv_value - EXCEPTIONS - foreign_lock = 1 - system_failure = 2 - OTHERS = 3. - IF sy-subrc <> 0. - _raise 'Could not aquire lock'. - ENDIF. - -* trigger dummy update task to automatically release locks at commit - CALL FUNCTION 'BANK_OBJ_WORKL_RELEASE_LOCKS' - IN UPDATE TASK. - - ENDMETHOD. - - METHOD add. - - DATA ls_table TYPE ty_content. - - ls_table-type = iv_type. - ls_table-value = iv_value. - ls_table-data_str = iv_data. - - INSERT (c_tabname) FROM ls_table. "#EC CI_SUBRC - ASSERT sy-subrc = 0. - - ENDMETHOD. - - METHOD delete. - - lock( iv_type = iv_type - iv_value = iv_value ). - - DELETE FROM (c_tabname) - WHERE type = iv_type - AND value = iv_value. - IF sy-subrc <> 0. - _raise 'DB Delete failed'. - ENDIF. - - ENDMETHOD. - - METHOD update. - - lock( iv_type = iv_type - iv_value = iv_value ). - - UPDATE (c_tabname) SET data_str = iv_data - WHERE type = iv_type - AND value = iv_value. - IF sy-subrc <> 0. - _raise 'DB update failed'. - ENDIF. - - ENDMETHOD. - - METHOD modify. - - DATA: ls_content TYPE ty_content. - - lock( iv_type = iv_type - iv_value = iv_value ). - - ls_content-type = iv_type. - ls_content-value = iv_value. - ls_content-data_str = iv_data. - - MODIFY (c_tabname) FROM ls_content. - IF sy-subrc <> 0. - _raise 'DB modify failed'. - ENDIF. - - ENDMETHOD. - - METHOD read. - - SELECT SINGLE data_str FROM (c_tabname) INTO rv_data - WHERE type = iv_type - AND value = iv_value. "#EC CI_SUBRC - IF sy-subrc <> 0. - RAISE EXCEPTION TYPE lcx_not_found. - ENDIF. - - ENDMETHOD. - -ENDCLASS. - -CLASS lcl_persistence_repo IMPLEMENTATION. - - METHOD add. - - DATA: ls_repo TYPE ty_repo, - lv_repo_as_xml TYPE string. - - - ls_repo-url = iv_url. - ls_repo-branch_name = iv_branch_name. - ls_repo-sha1 = iv_branch. - ls_repo-package = iv_package. - ls_repo-offline = iv_offline. - ls_repo-master_language = sy-langu. - - lv_repo_as_xml = to_xml( ls_repo ). - - rv_key = get_next_id( ). - - mo_db->add( iv_type = c_type_repo - iv_value = rv_key - iv_data = lv_repo_as_xml ). - - ENDMETHOD. - - METHOD delete. - - DATA: lo_background TYPE REF TO lcl_persistence_background. - - CREATE OBJECT lo_background. - lo_background->delete( iv_key ). - - mo_db->delete( iv_type = c_type_repo - iv_value = iv_key ). - - ENDMETHOD. - - METHOD update_local_checksums. - - DATA: lt_content TYPE lcl_persistence_db=>tt_content, - ls_content LIKE LINE OF lt_content, - ls_repo TYPE ty_repo. - - - ASSERT NOT iv_key IS INITIAL. - - TRY. - ls_repo = read( iv_key ). - CATCH lcx_not_found. - _raise 'key not found'. - ENDTRY. - - ls_repo-local_checksums = it_checksums. - ls_content-data_str = to_xml( ls_repo ). - - mo_db->update( iv_type = c_type_repo - iv_value = iv_key - iv_data = ls_content-data_str ). - - ENDMETHOD. - - METHOD update_url. - - DATA: lt_content TYPE lcl_persistence_db=>tt_content, - ls_content LIKE LINE OF lt_content, - ls_repo TYPE ty_repo. - - - IF iv_url IS INITIAL. - _raise 'update, url empty'. - ENDIF. - - ASSERT NOT iv_key IS INITIAL. - - TRY. - ls_repo = read( iv_key ). - CATCH lcx_not_found. - _raise 'key not found'. - ENDTRY. - - ls_repo-url = iv_url. - ls_content-data_str = to_xml( ls_repo ). - - mo_db->update( iv_type = c_type_repo - iv_value = iv_key - iv_data = ls_content-data_str ). - - ENDMETHOD. - - METHOD update_branch_name. - - DATA: lt_content TYPE lcl_persistence_db=>tt_content, - ls_content LIKE LINE OF lt_content, - ls_repo TYPE ty_repo. - - - IF iv_branch_name IS INITIAL. - _raise 'update, branch name empty'. - ENDIF. - - ASSERT NOT iv_key IS INITIAL. - - TRY. - ls_repo = read( iv_key ). - CATCH lcx_not_found. - _raise 'key not found'. - ENDTRY. - - ls_repo-branch_name = iv_branch_name. - ls_content-data_str = to_xml( ls_repo ). - - mo_db->update( iv_type = c_type_repo - iv_value = iv_key - iv_data = ls_content-data_str ). - - ENDMETHOD. - - METHOD update_sha1. - - DATA: lt_content TYPE lcl_persistence_db=>tt_content, - ls_content LIKE LINE OF lt_content, - ls_repo TYPE ty_repo. - - - IF iv_branch_sha1 IS INITIAL. - _raise 'update, sha empty'. - ENDIF. - - ASSERT NOT iv_key IS INITIAL. - - TRY. - ls_repo = read( iv_key ). - CATCH lcx_not_found. - _raise 'key not found'. - ENDTRY. - - ls_repo-sha1 = iv_branch_sha1. - ls_content-data_str = to_xml( ls_repo ). - - mo_db->update( iv_type = c_type_repo - iv_value = iv_key - iv_data = ls_content-data_str ). - - ENDMETHOD. - - METHOD read. - - DATA lt_repo TYPE tt_repo. - - lt_repo = list( ). - - READ TABLE lt_repo INTO rs_repo WITH KEY key = iv_key. - IF sy-subrc <> 0. - RAISE EXCEPTION TYPE lcx_not_found. - ENDIF. - - ENDMETHOD. - - METHOD get_next_id. - -* todo: Lock the complete persistence in order to prevent concurrent repo-creation -* however the current approach will most likely work in almost all cases - - DATA: lt_content TYPE lcl_persistence_db=>tt_content. - - FIELD-SYMBOLS: LIKE LINE OF lt_content. - - - rv_next_repo_id = 1. - - lt_content = mo_db->list_by_type( c_type_repo ). - LOOP AT lt_content ASSIGNING . - IF -value >= rv_next_repo_id. - rv_next_repo_id = -value + 1. - ENDIF. - ENDLOOP. - - CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT' - EXPORTING - input = rv_next_repo_id - IMPORTING - output = rv_next_repo_id. - - ENDMETHOD. - - METHOD list. - - DATA: lt_content TYPE lcl_persistence_db=>tt_content, - ls_content LIKE LINE OF lt_content, - ls_repo LIKE LINE OF rt_repos. - - - lt_content = mo_db->list_by_type( c_type_repo ). - - LOOP AT lt_content INTO ls_content. - MOVE-CORRESPONDING from_xml( ls_content-data_str ) TO ls_repo. - ls_repo-key = ls_content-value. - INSERT ls_repo INTO TABLE rt_repos. - ENDLOOP. - - ENDMETHOD. - - METHOD from_xml. - - DATA: lv_xml TYPE string. - - lv_xml = iv_repo_xml_string. - -* fix downward compatibility - REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_REPO_--29>' IN lv_xml WITH ''. - REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. - - CALL TRANSFORMATION id - OPTIONS value_handling = 'accept_data_loss' - SOURCE XML lv_xml - RESULT repo = rs_repo ##NO_TEXT. - - IF rs_repo IS INITIAL. - _raise 'Inconsistent repo metadata'. - ENDIF. - -* field master_language is new, so default it for old repositories - IF rs_repo-master_language IS INITIAL. - rs_repo-master_language = sy-langu. - ENDIF. - ENDMETHOD. - - METHOD to_xml. - - DATA: ls_xml TYPE ty_repo_xml. - - - MOVE-CORRESPONDING is_repo TO ls_xml. - - CALL TRANSFORMATION id - SOURCE repo = ls_xml - RESULT XML rv_repo_xml_string. - ENDMETHOD. - - METHOD constructor. - mo_db = lcl_app=>db( ). - ENDMETHOD. - - METHOD lock. - - mo_db->lock( iv_mode = iv_mode - iv_type = c_type_repo - iv_value = iv_key ). - - ENDMETHOD. - -ENDCLASS. - -CLASS lcl_persistence_migrate IMPLEMENTATION. - - METHOD run. - - IF table_exists( ) = abap_false. - table_create( ). - ENDIF. - - IF lock_exists( ) = abap_false. - lock_create( ). - - migrate_repo( ). - migrate_user( ). - ENDIF. - - ENDMETHOD. - - METHOD migrate_repo. - - DATA: lt_repo TYPE lcl_persistence=>ty_repos_persi_tt, - lo_repo TYPE REF TO lcl_persistence, - lo_new TYPE REF TO lcl_persistence_repo, - ls_repo LIKE LINE OF lt_repo. - - - CREATE OBJECT lo_repo. - CREATE OBJECT lo_new. - - lt_repo = lo_repo->list( ). - - LOOP AT lt_repo INTO ls_repo. - lo_new->add( iv_url = ls_repo-url - iv_branch_name = ls_repo-branch_name - iv_branch = ls_repo-sha1 - iv_package = ls_repo-package - iv_offline = ls_repo-offline ). - ENDLOOP. - ENDMETHOD. - - METHOD migrate_user. - - DATA: lo_user TYPE REF TO lcl_persistence_user, - lt_users TYPE lcl_user=>ty_user_tt. - - FIELD-SYMBOLS: LIKE LINE OF lt_users. - - - lt_users = lcl_user=>list( ). - LOOP AT lt_users ASSIGNING . - lo_user = lcl_app=>user( -user ). - lo_user->set_username( -username ). - lo_user->set_email( -email ). - ENDLOOP. - - ENDMETHOD. - - METHOD lock_exists. - - DATA: lv_viewname TYPE dd25l-viewname. - - - SELECT SINGLE viewname FROM dd25l INTO lv_viewname - WHERE viewname = lcl_persistence_db=>c_lock. - rv_exists = boolc( sy-subrc = 0 ). - - ENDMETHOD. - - METHOD lock_create. - - DATA: lv_obj_name TYPE tadir-obj_name, - ls_dd25v TYPE dd25v, - lt_dd26e TYPE STANDARD TABLE OF dd26e WITH DEFAULT KEY, - lt_dd27p TYPE STANDARD TABLE OF dd27p WITH DEFAULT KEY. - - FIELD-SYMBOLS: LIKE LINE OF lt_dd26e, - LIKE LINE OF lt_dd27p. - - - ls_dd25v-viewname = lcl_persistence_db=>c_lock. - ls_dd25v-aggtype = 'E'. - ls_dd25v-roottab = lcl_persistence_db=>c_tabname. - ls_dd25v-ddlanguage = gc_english. - ls_dd25v-ddtext = c_text. - - APPEND INITIAL LINE TO lt_dd26e ASSIGNING . - -viewname = lcl_persistence_db=>c_lock. - -tabname = lcl_persistence_db=>c_tabname. - -tabpos = '0001'. - -fortabname = lcl_persistence_db=>c_tabname. - -enqmode = 'E'. - - APPEND INITIAL LINE TO lt_dd27p ASSIGNING . - -viewname = lcl_persistence_db=>c_lock. - -objpos = '0001'. - -viewfield = 'TYPE'. - -tabname = lcl_persistence_db=>c_tabname. - -fieldname = 'TYPE'. - -keyflag = abap_true. - - APPEND INITIAL LINE TO lt_dd27p ASSIGNING . - -viewname = lcl_persistence_db=>c_lock. - -objpos = '0002'. - -viewfield = 'VALUE'. - -tabname = lcl_persistence_db=>c_tabname. - -fieldname = 'VALUE'. - -keyflag = abap_true. - - CALL FUNCTION 'DDIF_ENQU_PUT' - EXPORTING - name = lcl_persistence_db=>c_lock - dd25v_wa = ls_dd25v - TABLES - dd26e_tab = lt_dd26e - dd27p_tab = lt_dd27p - EXCEPTIONS - enqu_not_found = 1 - name_inconsistent = 2 - enqu_inconsistent = 3 - put_failure = 4 - put_refused = 5 - OTHERS = 6. - IF sy-subrc <> 0. - _raise 'migrate, error from DDIF_ENQU_PUT'. - ENDIF. - - lv_obj_name = lcl_persistence_db=>c_lock. - CALL FUNCTION 'TR_TADIR_INTERFACE' - EXPORTING - wi_tadir_pgmid = 'R3TR' - wi_tadir_object = 'ENQU' - wi_tadir_obj_name = lv_obj_name - wi_set_genflag = abap_true - wi_test_modus = abap_false - wi_tadir_devclass = '$TMP' - EXCEPTIONS - OTHERS = 1. - IF sy-subrc <> 0. - _raise 'migrate, error from TR_TADIR_INTERFACE'. - ENDIF. - - CALL FUNCTION 'DDIF_ENQU_ACTIVATE' - EXPORTING - name = lcl_persistence_db=>c_lock - EXCEPTIONS - not_found = 1 - put_failure = 2 - OTHERS = 3. - IF sy-subrc <> 0. - _raise 'migrate, error from DDIF_ENQU_ACTIVATE'. - ENDIF. - - ENDMETHOD. - - METHOD table_exists. - - DATA: lv_tabname TYPE dd02l-tabname. - - SELECT SINGLE tabname FROM dd02l INTO lv_tabname - WHERE tabname = lcl_persistence_db=>c_tabname. - rv_exists = boolc( sy-subrc = 0 ). - - ENDMETHOD. - - METHOD table_create. - - DATA: lv_obj_name TYPE tadir-obj_name, - ls_dd02v TYPE dd02v, - ls_dd09l TYPE dd09l, - lt_dd03p TYPE STANDARD TABLE OF dd03p WITH DEFAULT KEY. - - FIELD-SYMBOLS: LIKE LINE OF lt_dd03p. - - ls_dd02v-tabname = lcl_persistence_db=>c_tabname. - ls_dd02v-ddlanguage = gc_english. - ls_dd02v-tabclass = 'TRANSP'. - ls_dd02v-ddtext = c_text. - ls_dd02v-contflag = 'A'. - ls_dd02v-exclass = '1'. - - ls_dd09l-tabname = lcl_persistence_db=>c_tabname. - ls_dd09l-as4local = 'A'. - ls_dd09l-tabkat = '1'. - ls_dd09l-tabart = 'APPL1'. - ls_dd09l-bufallow = 'N'. - - APPEND INITIAL LINE TO lt_dd03p ASSIGNING . - -tabname = lcl_persistence_db=>c_tabname. - -fieldname = 'TYPE'. - -position = '0001'. - -keyflag = 'X'. - -datatype = 'CHAR'. - -leng = '000012'. - - APPEND INITIAL LINE TO lt_dd03p ASSIGNING . - -tabname = lcl_persistence_db=>c_tabname. - -fieldname = 'VALUE'. - -position = '0002'. - -keyflag = 'X'. - -datatype = 'CHAR'. - -leng = '000012'. - - APPEND INITIAL LINE TO lt_dd03p ASSIGNING . - -tabname = lcl_persistence_db=>c_tabname. - -fieldname = 'DATA_STR'. - -position = '0003'. - -datatype = 'STRG'. - - CALL FUNCTION 'DDIF_TABL_PUT' - EXPORTING - name = lcl_persistence_db=>c_tabname - dd02v_wa = ls_dd02v - dd09l_wa = ls_dd09l - TABLES - dd03p_tab = lt_dd03p - EXCEPTIONS - tabl_not_found = 1 - name_inconsistent = 2 - tabl_inconsistent = 3 - put_failure = 4 - put_refused = 5 - OTHERS = 6. - IF sy-subrc <> 0. - _raise 'migrate, error from DDIF_TABL_PUT'. - ENDIF. - - lv_obj_name = lcl_persistence_db=>c_tabname. - CALL FUNCTION 'TR_TADIR_INTERFACE' - EXPORTING - wi_tadir_pgmid = 'R3TR' - wi_tadir_object = 'TABL' - wi_tadir_obj_name = lv_obj_name - wi_set_genflag = abap_true - wi_test_modus = abap_false - wi_tadir_devclass = '$TMP' - EXCEPTIONS - OTHERS = 1. - IF sy-subrc <> 0. - _raise 'migrate, error from TR_TADIR_INTERFACE'. - ENDIF. - - CALL FUNCTION 'DDIF_TABL_ACTIVATE' - EXPORTING - name = lcl_persistence_db=>c_tabname - EXCEPTIONS - not_found = 1 - put_failure = 2 - OTHERS = 3. - IF sy-subrc <> 0. - _raise 'migrate, error from DDIF_TABL_ACTIVATE'. - ENDIF. - - ENDMETHOD. - -ENDCLASS. - CLASS lcl_gui_page_db_display DEFINITION FINAL INHERITING FROM lcl_gui_page_super. PUBLIC SECTION. diff --git a/src/zabapgit.prog.xml b/src/zabapgit.prog.xml index 9a4cd671b..c45af12c8 100644 --- a/src/zabapgit.prog.xml +++ b/src/zabapgit.prog.xml @@ -61,7 +61,7 @@ R abapGit - 54 + 7 diff --git a/src/zabapgit_dot_abapgit.prog.abap b/src/zabapgit_dot_abapgit.prog.abap new file mode 100644 index 000000000..db822941c --- /dev/null +++ b/src/zabapgit_dot_abapgit.prog.abap @@ -0,0 +1,208 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_DOT_ABAPGIT +*&---------------------------------------------------------------------* + +CLASS ltcl_dot_abapgit DEFINITION DEFERRED. + +CLASS lcl_dot_abapgit DEFINITION CREATE PRIVATE FINAL FRIENDS ltcl_dot_abapgit. + + PUBLIC SECTION. + CLASS-METHODS: + build_default + IMPORTING iv_master_language TYPE spras + RETURNING VALUE(ro_dot_abapgit) TYPE REF TO lcl_dot_abapgit, + deserialize + IMPORTING iv_xstr TYPE xstring + RETURNING VALUE(ro_dot_abapgit) TYPE REF TO lcl_dot_abapgit + RAISING lcx_exception. + + METHODS: + serialize + RETURNING VALUE(rv_xstr) TYPE xstring, + add_ignore + IMPORTING iv_path TYPE string + iv_filename TYPE string, + is_ignored + IMPORTING iv_path TYPE string + iv_filename TYPE string + RETURNING VALUE(rv_ignored) TYPE abap_bool, + remove_ignore + IMPORTING iv_path TYPE string + iv_filename TYPE string, + get_starting_folder + RETURNING VALUE(rv_path) TYPE string, +* set_starting_folder +* IMPORTING iv_path TYPE string, + get_master_language + RETURNING VALUE(rv_language) TYPE spras. +* set_master_language +* IMPORTING iv_language TYPE spras. + + PRIVATE SECTION. + TYPES: BEGIN OF ty_dot_abapgit, + master_language TYPE spras, + starting_folder TYPE string, + ignore TYPE STANDARD TABLE OF string WITH DEFAULT KEY, + END OF ty_dot_abapgit. + + DATA: ms_data TYPE ty_dot_abapgit. + + METHODS: + constructor + IMPORTING is_data TYPE ty_dot_abapgit. + + CLASS-METHODS: + to_xml + IMPORTING is_data TYPE ty_dot_abapgit + RETURNING VALUE(rv_xml) TYPE string, + from_xml + IMPORTING iv_xml TYPE string + RETURNING VALUE(rs_data) TYPE ty_dot_abapgit. + +ENDCLASS. + +CLASS lcl_dot_abapgit IMPLEMENTATION. + + METHOD constructor. + ms_data = is_data. + ENDMETHOD. + + METHOD deserialize. + + DATA: lv_xml TYPE string, + ls_data TYPE ty_dot_abapgit. + + + lv_xml = lcl_convert=>xstring_to_string_utf8( iv_xstr ). + + ls_data = from_xml( lv_xml ). + + CREATE OBJECT ro_dot_abapgit + EXPORTING + is_data = ls_data. + + ENDMETHOD. + + METHOD serialize. + + DATA: lv_xml TYPE string. + + lv_xml = to_xml( ms_data ). + + rv_xstr = lcl_convert=>string_to_xstring_utf8( lv_xml ). + + ENDMETHOD. + + METHOD build_default. + + DATA: ls_data TYPE ty_dot_abapgit. + + + ls_data-master_language = iv_master_language. + ls_data-starting_folder = '/'. + APPEND '/.gitignore' TO ls_data-ignore. + APPEND '/LICENSE' TO ls_data-ignore. + APPEND '/README.md' TO ls_data-ignore. + APPEND '/package.json' TO ls_data-ignore. + APPEND '/.travis.yml' TO ls_data-ignore. + + CREATE OBJECT ro_dot_abapgit + EXPORTING + is_data = ls_data. + + ENDMETHOD. + + METHOD to_xml. + CALL TRANSFORMATION id + SOURCE data = is_data + RESULT XML rv_xml. + + rv_xml = lcl_xml_pretty=>print( rv_xml ). + + REPLACE FIRST OCCURRENCE + OF '' + IN rv_xml + WITH ''. + ASSERT sy-subrc = 0. + ENDMETHOD. + + METHOD from_xml. + + DATA: lv_xml TYPE string. + + lv_xml = iv_xml. + +* fix downward compatibility + REPLACE ALL OCCURRENCES OF '<_--28C_DATA_--29>' IN lv_xml WITH ''. + REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. + + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML lv_xml + RESULT data = rs_data ##NO_TEXT. + ENDMETHOD. + + METHOD add_ignore. + + DATA: lv_name TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF ms_data-ignore. + + + lv_name = iv_path && iv_filename. + + READ TABLE ms_data-ignore FROM lv_name TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + RETURN. + ENDIF. + + APPEND INITIAL LINE TO ms_data-ignore ASSIGNING . + = lv_name. + + ENDMETHOD. + + METHOD is_ignored. + + DATA: lv_name TYPE string, + lv_ignore TYPE string. + + + lv_name = iv_path && iv_filename. + + LOOP AT ms_data-ignore INTO lv_ignore. + IF lv_name CP lv_ignore. + rv_ignored = abap_true. + RETURN. + ENDIF. + ENDLOOP. + + ENDMETHOD. + + METHOD remove_ignore. + + DATA: lv_name TYPE string. + + + lv_name = iv_path && iv_filename. + + DELETE TABLE ms_data-ignore FROM lv_name. + + ENDMETHOD. + + METHOD get_starting_folder. + rv_path = ms_data-starting_folder. + ENDMETHOD. + +* METHOD set_starting_folder. +* ms_data-starting_folder = iv_path. +* ENDMETHOD. + + METHOD get_master_language. + rv_language = ms_data-master_language. + ENDMETHOD. + +* METHOD set_master_language. +* ms_data-master_language = iv_language. +* ENDMETHOD. + +ENDCLASS. \ No newline at end of file diff --git a/src/zabapgit_dot_abapgit.prog.xml b/src/zabapgit_dot_abapgit.prog.xml new file mode 100644 index 000000000..4225cb8d0 --- /dev/null +++ b/src/zabapgit_dot_abapgit.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_DOT_ABAPGIT + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_DOT_ABAPGIT + 28 + + + + + + diff --git a/src/zabapgit_file_status.prog.abap b/src/zabapgit_file_status.prog.abap new file mode 100644 index 000000000..2e74538ae --- /dev/null +++ b/src/zabapgit_file_status.prog.abap @@ -0,0 +1,190 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_FILE_STATUS +*&---------------------------------------------------------------------* + +*----------------------------------------------------------------------* +* CLASS lcl_file_status DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_file_status DEFINITION FINAL. + + PUBLIC SECTION. + + CLASS-METHODS status + IMPORTING io_repo TYPE REF TO lcl_repo + io_log TYPE REF TO lcl_log OPTIONAL + RETURNING VALUE(rt_results) TYPE ty_results_tt + RAISING lcx_exception. + + PRIVATE SECTION. + + CLASS-METHODS compare_files + IMPORTING it_repo TYPE ty_files_tt + is_gen TYPE ty_file + RETURNING VALUE(rv_match) TYPE sap_bool + RAISING lcx_exception. + +ENDCLASS. "lcl_file_status DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_file_status IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_file_status IMPLEMENTATION. + + METHOD compare_files. + + READ TABLE it_repo WITH KEY + path = is_gen-path + filename = is_gen-filename + data = is_gen-data + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + rv_match = abap_false. + ELSE. + rv_match = abap_true. + ENDIF. + + ENDMETHOD. "compare_files + + METHOD status. + + DATA: lv_pre TYPE tadir-obj_name, + lt_files TYPE ty_files_tt, + ls_result LIKE LINE OF rt_results, + lv_type TYPE string, + ls_item TYPE ty_item, + lt_tadir TYPE lcl_tadir=>ty_tadir_tt, + lt_local TYPE ty_files_item_tt, + ls_tadir TYPE tadir, + lt_remote TYPE ty_files_tt, + lv_ext TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF lt_remote, + LIKE LINE OF lt_tadir, + LIKE LINE OF rt_results, + LIKE LINE OF lt_local, + LIKE LINE OF lt_files. + + + lt_remote = io_repo->get_files_remote( ). + lt_local = io_repo->get_files_local( io_log ). + + LOOP AT lt_remote ASSIGNING . + lcl_progress=>show( iv_key = 'Status' + iv_current = sy-tabix + iv_total = lines( lt_remote ) + iv_text = -filename ) ##NO_TEXT. + + SPLIT -filename AT '.' INTO lv_pre lv_type lv_ext. + TRANSLATE lv_pre TO UPPER CASE. + TRANSLATE lv_type TO UPPER CASE. + + IF lv_ext <> 'xml' OR strlen( lv_type ) <> 4. + CONTINUE. " current loop + ENDIF. + +* handle namespaces + REPLACE ALL OCCURRENCES OF '#' IN lv_pre WITH '/'. + + CLEAR ls_result. + ls_result-obj_type = lv_type. + ls_result-obj_name = lv_pre. + + CLEAR ls_item. + ls_item-obj_type = lv_type. + ls_item-obj_name = lv_pre. + + CLEAR lt_files. + LOOP AT lt_local ASSIGNING WHERE item = ls_item. + APPEND -file TO lt_files. + ENDLOOP. + + IF lt_files[] IS INITIAL. +* item does not exist locally + ls_result-filename = -filename. + APPEND ls_result TO rt_results. + CONTINUE. " current loop + ENDIF. + + LOOP AT lt_files ASSIGNING . + ls_result-filename = -filename. + ls_result-match = compare_files( it_repo = lt_remote + is_gen = ). + APPEND ls_result TO rt_results. + ENDLOOP. + ENDLOOP. + +* find files only existing remotely, including non abapGit related + LOOP AT lt_remote ASSIGNING . + READ TABLE rt_results WITH KEY filename = -filename + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + IF io_repo->get_dot_abapgit( )->is_ignored( + iv_path = -path + iv_filename = -filename ) = abap_true. + CONTINUE. + ENDIF. + + CLEAR ls_result. + ls_result-match = abap_true. + ls_result-filename = -filename. + APPEND ls_result TO rt_results. + ENDIF. + ENDLOOP. + +* find objects only existing locally + lt_tadir = lcl_tadir=>read( io_repo->get_package( ) ). + LOOP AT lt_tadir ASSIGNING . + READ TABLE rt_results + WITH KEY obj_type = -object + obj_name = -obj_name + TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + ls_item-obj_type = -object. + ls_item-obj_name = -obj_name. + IF lcl_objects=>is_supported( ls_item ) = abap_false. + CONTINUE. + ENDIF. + + CLEAR ls_result. + ls_result-match = abap_true. + ls_result-obj_type = -object. + ls_result-obj_name = -obj_name. + APPEND ls_result TO rt_results. + ENDIF. + ENDLOOP. + +* add path information for files + LOOP AT lt_remote ASSIGNING . + READ TABLE rt_results ASSIGNING WITH KEY filename = -filename. + IF sy-subrc = 0. + -path = -path. + ENDIF. + ENDLOOP. + +* add package information + LOOP AT rt_results ASSIGNING WHERE NOT obj_type IS INITIAL. + ls_tadir = lcl_tadir=>read_single( iv_object = -obj_type + iv_obj_name = -obj_name ). + -package = ls_tadir-devclass. + ENDLOOP. + + SORT rt_results BY + obj_type ASCENDING + obj_name ASCENDING + filename ASCENDING. + DELETE ADJACENT DUPLICATES FROM rt_results + COMPARING obj_type obj_name filename. + + lcl_sap_package=>check( + io_log = io_log + it_results = rt_results + iv_start = io_repo->get_dot_abapgit( )->get_starting_folder( ) + iv_top = io_repo->get_package( ) ). + + ENDMETHOD. "status + +ENDCLASS. "lcl_file_status IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_file_status.prog.xml b/src/zabapgit_file_status.prog.xml new file mode 100644 index 000000000..d4e829924 --- /dev/null +++ b/src/zabapgit_file_status.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_FILE_STATUS + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_FILE_STATUS + 28 + + + + + + diff --git a/src/zabapgit_git.prog.abap b/src/zabapgit_git.prog.abap new file mode 100644 index 000000000..4e92108b7 --- /dev/null +++ b/src/zabapgit_git.prog.abap @@ -0,0 +1,1773 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_GIT +*&---------------------------------------------------------------------* + +CLASS ltcl_git_pack DEFINITION DEFERRED. + +*----------------------------------------------------------------------* +* CLASS lcl_transport DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_git_transport DEFINITION FINAL. + + PUBLIC SECTION. + TYPES: BEGIN OF ty_branch_list, + sha1 TYPE ty_sha1, + name TYPE string, + END OF ty_branch_list. + TYPES: ty_branch_list_tt TYPE STANDARD TABLE OF ty_branch_list WITH DEFAULT KEY. + +* remote to local + CLASS-METHODS upload_pack + IMPORTING io_repo TYPE REF TO lcl_repo_online + EXPORTING ev_pack TYPE xstring + ev_branch TYPE ty_sha1 + RAISING lcx_exception. + +* local to remote + CLASS-METHODS receive_pack + IMPORTING io_repo TYPE REF TO lcl_repo_online + iv_old TYPE ty_sha1 + iv_new TYPE ty_sha1 + iv_branch_name TYPE string + iv_pack TYPE xstring + RAISING lcx_exception. + + CLASS-METHODS branches + IMPORTING iv_url TYPE string + RETURNING VALUE(rt_branch_list) TYPE ty_branch_list_tt + RAISING lcx_exception. + + CLASS-METHODS class_constructor. + + PRIVATE SECTION. + CLASS-DATA: gv_agent TYPE string. + + CONSTANTS: BEGIN OF c_service, + receive TYPE string VALUE 'receive', "#EC NOTEXT + upload TYPE string VALUE 'upload', "#EC NOTEXT + END OF c_service. + + CLASS-METHODS branch_list + IMPORTING iv_url TYPE string + iv_service TYPE string + EXPORTING ei_client TYPE REF TO if_http_client + et_branch_list TYPE ty_branch_list_tt + RAISING lcx_exception. + + CLASS-METHODS pkt_string + IMPORTING iv_string TYPE string + RETURNING VALUE(rv_pkt) TYPE string + RAISING lcx_exception. + + CLASS-METHODS find_branch + IMPORTING io_repo TYPE REF TO lcl_repo_online + iv_service TYPE string + EXPORTING ei_client TYPE REF TO if_http_client + ev_branch TYPE ty_sha1 + RAISING lcx_exception. + + CLASS-METHODS parse + EXPORTING ev_pack TYPE xstring + CHANGING cv_data TYPE xstring + RAISING lcx_exception. + + CLASS-METHODS length_utf8_hex + IMPORTING iv_data TYPE xstring + RETURNING VALUE(rv_len) TYPE i + RAISING lcx_exception. + + CLASS-METHODS parse_branch_list + IMPORTING iv_data TYPE string + RETURNING VALUE(rt_list) TYPE ty_branch_list_tt + RAISING lcx_exception. + + CLASS-METHODS set_headers + IMPORTING io_repo TYPE REF TO lcl_repo_online + iv_service TYPE string + ii_client TYPE REF TO if_http_client + RAISING lcx_exception. + + CLASS-METHODS check_http_200 + IMPORTING ii_client TYPE REF TO if_http_client + RAISING lcx_exception. + + CLASS-METHODS get_null + RETURNING VALUE(rv_c) TYPE char1. + +ENDCLASS. "lcl_transport DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_transport IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_git_transport IMPLEMENTATION. + + METHOD class_constructor. + +* bitbucket require agent prefix = "git/" + gv_agent = 'git/abapGit ' && gc_abap_version. + + ENDMETHOD. "class_constructor + + METHOD set_headers. + + DATA: lv_value TYPE string. + + + ii_client->request->set_header_field( + name = '~request_method' + value = 'POST' ). + + lv_value = lcl_url=>path_name( io_repo->get_url( ) ) && + '.git/git-' && + iv_service && + '-pack'. + ii_client->request->set_header_field( + name = '~request_uri' + value = lv_value ). + + lv_value = 'application/x-git-' + && iv_service && '-pack-request'. "#EC NOTEXT + ii_client->request->set_header_field( + name = 'Content-Type' + value = lv_value ). "#EC NOTEXT + + lv_value = 'application/x-git-' + && iv_service && '-pack-result'. "#EC NOTEXT + ii_client->request->set_header_field( + name = 'Accept' + value = lv_value ). "#EC NOTEXT + + ENDMETHOD. "set_headers + + METHOD get_null. + + DATA: lv_x(4) TYPE x VALUE '00000000', + lv_z(2) TYPE c. + + FIELD-SYMBOLS TYPE c. + + + ASSIGN lv_x TO CASTING. + lv_z = . + rv_c = lv_z(1). + + ENDMETHOD. "get_null + + METHOD check_http_200. + + DATA: lv_code TYPE i. + + + ii_client->response->get_status( + IMPORTING + code = lv_code ). + CASE lv_code. + WHEN 200. + RETURN. + WHEN 302. + _raise 'HTTP redirect, check URL'. + WHEN 401. + _raise 'HTTP 401, unauthorized'. + WHEN 403. + _raise 'HTTP 403, forbidden'. + WHEN 404. + _raise 'HTTP 404, not found'. + WHEN 415. + _raise 'HTTP 415, unsupported media type'. + WHEN OTHERS. + _raise 'HTTP error code'. + ENDCASE. + + ENDMETHOD. "http_200 + + METHOD parse_branch_list. + + DATA: lt_result TYPE TABLE OF string, + lv_hash TYPE ty_sha1, + lv_name TYPE string, + lv_foo TYPE string ##needed, + lv_char TYPE c, + lv_data LIKE LINE OF lt_result. + + FIELD-SYMBOLS: LIKE LINE OF rt_list. + + + SPLIT iv_data AT gc_newline INTO TABLE lt_result. + LOOP AT lt_result INTO lv_data. + IF sy-tabix = 1. + CONTINUE. " current loop + ELSEIF sy-tabix = 2 AND strlen( lv_data ) > 49. + lv_hash = lv_data+8. + lv_name = lv_data+49. + lv_char = get_null( ). + SPLIT lv_name AT lv_char INTO lv_name lv_foo. + ELSEIF sy-tabix > 2 AND strlen( lv_data ) > 45. + lv_hash = lv_data+4. + lv_name = lv_data+45. + ELSEIF sy-tabix = 2 AND strlen( lv_data ) = 8 AND lv_data(8) = '00000000'. + _raise 'No branches, create branch manually by adding file'. + ELSE. + CONTINUE. + ENDIF. + + IF lv_name CP 'refs/pull/*'. + CONTINUE. + ENDIF. + + APPEND INITIAL LINE TO rt_list ASSIGNING . + -sha1 = lv_hash. + -name = lv_name. + ENDLOOP. + + ENDMETHOD. "parse_branch_list + + METHOD find_branch. + + DATA: lt_branch_list TYPE ty_branch_list_tt, + ls_branch_list LIKE LINE OF lt_branch_list. + + + branch_list( + EXPORTING + iv_url = io_repo->get_url( ) + iv_service = iv_service + IMPORTING + ei_client = ei_client + et_branch_list = lt_branch_list ). + + IF io_repo->get_branch_name( ) IS INITIAL. + _raise 'branch empty'. + ENDIF. + + READ TABLE lt_branch_list INTO ls_branch_list + WITH KEY name = io_repo->get_branch_name( ). + IF sy-subrc <> 0. + _raise 'Branch not found'. + ENDIF. + + ev_branch = ls_branch_list-sha1. + + ENDMETHOD. "find_branch + + METHOD branches. + + DATA: li_client TYPE REF TO if_http_client. + + + lcl_git_transport=>branch_list( + EXPORTING + iv_url = iv_url + iv_service = c_service-upload + IMPORTING + ei_client = li_client + et_branch_list = rt_branch_list ). + li_client->close( ). + + ENDMETHOD. "branches + + METHOD branch_list. + + DATA: lv_data TYPE string, + lv_uri TYPE string, + lv_text TYPE string. + + + cl_http_client=>create_by_url( + EXPORTING + url = lcl_url=>host( iv_url ) + ssl_id = 'ANONYM' + IMPORTING + client = ei_client ). + + ei_client->request->set_cdata( '' ). + ei_client->request->set_header_field( + name = '~request_method' + value = 'GET' ). + ei_client->request->set_header_field( + name = 'user-agent' + value = gv_agent ). "#EC NOTEXT + lv_uri = lcl_url=>path_name( iv_url ) && + '.git/info/refs?service=git-' && + iv_service && + '-pack'. + ei_client->request->set_header_field( + name = '~request_uri' + value = lv_uri ). + + lcl_login_manager=>load( iv_uri = iv_url + ii_client = ei_client ). + + ei_client->send( ). + ei_client->receive( + EXCEPTIONS + http_communication_failure = 1 + http_invalid_state = 2 + http_processing_failed = 3 + OTHERS = 4 ). + IF sy-subrc <> 0. + CASE sy-subrc. + WHEN 1. +* make sure: +* a) SSL is setup properly in STRUST +* b) no firewalls +* check trace file in transaction SMICM + lv_text = 'HTTP Communication Failure'. "#EC NOTEXT + WHEN 2. + lv_text = 'HTTP Invalid State'. "#EC NOTEXT + WHEN 3. + lv_text = 'HTTP Processing failed'. "#EC NOTEXT + WHEN OTHERS. + lv_text = 'Another error occured'. "#EC NOTEXT + ENDCASE. + RAISE EXCEPTION TYPE lcx_exception + EXPORTING + iv_text = lv_text. + ENDIF. + + check_http_200( ei_client ). + + lcl_login_manager=>save( iv_uri = iv_url + ii_client = ei_client ). + + lv_data = ei_client->response->get_cdata( ). + et_branch_list = parse_branch_list( lv_data ). + + ENDMETHOD. "ref_discovery + + METHOD receive_pack. + + DATA: li_client TYPE REF TO if_http_client, + lv_cmd_pkt TYPE string, + lv_line TYPE string, + lv_tmp TYPE xstring, + lv_xstring TYPE xstring, + lv_string TYPE string, + lv_cap_list TYPE string, + lv_buffer TYPE string. + + + find_branch( + EXPORTING + io_repo = io_repo + iv_service = c_service-receive + IMPORTING + ei_client = li_client ). + + set_headers( + io_repo = io_repo + iv_service = c_service-receive + ii_client = li_client ). + + lv_cap_list = 'report-status agent=' && gv_agent. + + lv_line = iv_old && + ` ` && + iv_new && + ` ` && + iv_branch_name && + get_null( ) && + ` ` && + lv_cap_list && + gc_newline. "#EC NOTEXT + lv_cmd_pkt = pkt_string( lv_line ). + + lv_buffer = lv_cmd_pkt && '0000'. + lv_tmp = lcl_convert=>string_to_xstring_utf8( lv_buffer ). + + CONCATENATE lv_tmp iv_pack INTO lv_xstring IN BYTE MODE. + + li_client->request->set_data( lv_xstring ). + + li_client->send( ). + li_client->receive( ). + check_http_200( li_client ). + + lv_xstring = li_client->response->get_data( ). + li_client->close( ). + + lv_string = lcl_convert=>xstring_to_string_utf8( lv_xstring ). + IF NOT lv_string CP '*unpack ok*'. + _raise 'unpack not ok'. + ELSEIF lv_string CP '*pre-receive hook declined*'. + _raise 'pre-receive hook declined'. + ENDIF. + + ENDMETHOD. "receive_pack + + METHOD length_utf8_hex. + + DATA: lv_xstring TYPE xstring, + lv_string TYPE string, + lv_char4 TYPE c LENGTH 4, + lv_x TYPE x LENGTH 2, + lo_obj TYPE REF TO cl_abap_conv_in_ce, + lv_len TYPE int4. + +* hmm, can this be done easier? + + lv_xstring = iv_data(4). + + lo_obj = cl_abap_conv_in_ce=>create( + input = lv_xstring + encoding = 'UTF-8' ). + lv_len = xstrlen( lv_xstring ). + + TRY. + lo_obj->read( EXPORTING n = lv_len + IMPORTING data = lv_string ). + CATCH cx_sy_conversion_codepage. + _raise 'error converting to hex, LENGTH_UTF8_HEX'. + ENDTRY. + + lv_char4 = lv_string. + TRANSLATE lv_char4 TO UPPER CASE. + lv_x = lv_char4. + rv_len = lv_x. + + ENDMETHOD. "length_utf8_hex + + METHOD parse. + + CONSTANTS: lc_band1 TYPE x VALUE '01'. + + DATA: lv_len TYPE i, + lv_contents TYPE xstring, + lv_pack TYPE xstring. + + + WHILE xstrlen( cv_data ) >= 4. + lv_len = length_utf8_hex( cv_data ). + + IF lv_len > xstrlen( cv_data ). + _raise 'parse, string length too large'. + ENDIF. + + lv_contents = cv_data(lv_len). + IF lv_len = 0. + cv_data = cv_data+4. + CONTINUE. + ELSE. + cv_data = cv_data+lv_len. + ENDIF. + + lv_contents = lv_contents+4. + + IF xstrlen( lv_contents ) > 1 AND lv_contents(1) = lc_band1. + CONCATENATE lv_pack lv_contents+1 INTO lv_pack IN BYTE MODE. + ENDIF. + + ENDWHILE. + + ev_pack = lv_pack. + + ENDMETHOD. "parse + + METHOD upload_pack. + + DATA: li_client TYPE REF TO if_http_client, + lv_buffer TYPE string, + lv_xstring TYPE xstring, + lv_line TYPE string, + lv_pkt1 TYPE string, + lv_pkt2 TYPE string. + + + find_branch( + EXPORTING + io_repo = io_repo + iv_service = c_service-upload + IMPORTING + ei_client = li_client + ev_branch = ev_branch ). + + set_headers( + io_repo = io_repo + iv_service = c_service-upload + ii_client = li_client ). + + lv_line = 'want' && + ` ` && + ev_branch && + ` ` && + 'side-band-64k no-progress agent=' && gv_agent + && gc_newline. "#EC NOTEXT + lv_pkt1 = pkt_string( lv_line ). + + lv_pkt2 = pkt_string( 'deepen 1' && gc_newline ). "#EC NOTEXT + + lv_buffer = lv_pkt1 + && lv_pkt2 + && '0000' + && '0009done' && gc_newline. + +* do not use set_cdata as it modifies the Content-Type header field + li_client->request->set_data( lcl_convert=>string_to_xstring_utf8( lv_buffer ) ). + li_client->send( ). + li_client->receive( ). + check_http_200( li_client ). + lv_xstring = li_client->response->get_data( ). + li_client->close( ). + + parse( IMPORTING ev_pack = ev_pack + CHANGING cv_data = lv_xstring ). + + ENDMETHOD. "upload_pack + + METHOD pkt_string. + + DATA: lv_x TYPE x, + lv_len TYPE i. + + + lv_len = strlen( iv_string ). + + IF lv_len >= 255. + _raise 'PKT, todo'. + ENDIF. + + lv_x = lv_len + 4. + + rv_pkt = rv_pkt && '00' && lv_x && iv_string. + + ENDMETHOD. "pkt + +ENDCLASS. "lcl_transport IMPLEMENTATION + +*----------------------------------------------------------------------* +* CLASS lcl_pack DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_git_pack DEFINITION FINAL FRIENDS ltcl_git_pack. + + PUBLIC SECTION. + TYPES: BEGIN OF ty_node, + chmod TYPE ty_chmod, + name TYPE string, + sha1 TYPE ty_sha1, + END OF ty_node. + TYPES: ty_nodes_tt TYPE STANDARD TABLE OF ty_node WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_commit, + tree TYPE ty_sha1, + parent TYPE ty_sha1, + author TYPE string, + committer TYPE string, + body TYPE string, + END OF ty_commit. + + CLASS-METHODS decode + IMPORTING iv_data TYPE xstring + RETURNING VALUE(rt_objects) TYPE ty_objects_tt + RAISING lcx_exception. + + CLASS-METHODS decode_tree + IMPORTING iv_data TYPE xstring + RETURNING VALUE(rt_nodes) TYPE ty_nodes_tt + RAISING lcx_exception. + + CLASS-METHODS decode_deltas + CHANGING ct_objects TYPE ty_objects_tt + RAISING lcx_exception. + + CLASS-METHODS decode_commit + IMPORTING iv_data TYPE xstring + RETURNING VALUE(rs_commit) TYPE ty_commit + RAISING lcx_exception. + + CLASS-METHODS encode + IMPORTING it_objects TYPE ty_objects_tt + RETURNING VALUE(rv_data) TYPE xstring + RAISING lcx_exception. + + CLASS-METHODS encode_tree + IMPORTING it_nodes TYPE ty_nodes_tt + RETURNING VALUE(rv_data) TYPE xstring. + + CLASS-METHODS encode_commit + IMPORTING is_commit TYPE ty_commit + RETURNING VALUE(rv_data) TYPE xstring. + + PRIVATE SECTION. + CONSTANTS: c_pack_start TYPE x LENGTH 4 VALUE '5041434B', " PACK + c_zlib TYPE x LENGTH 2 VALUE '789C', + c_zlib_hmm TYPE x LENGTH 2 VALUE '7801', + c_version TYPE x LENGTH 4 VALUE '00000002'. + + CLASS-METHODS type_and_length + IMPORTING is_object TYPE ty_object + RETURNING VALUE(rv_xstring) TYPE xstring + RAISING lcx_exception. + + CLASS-METHODS delta + IMPORTING is_object TYPE ty_object + CHANGING ct_objects TYPE ty_objects_tt + RAISING lcx_exception. + + CLASS-METHODS delta_header + EXPORTING ev_header TYPE i + CHANGING cv_delta TYPE xstring. + + CLASS-METHODS sort_tree + IMPORTING it_nodes TYPE ty_nodes_tt + RETURNING VALUE(rt_nodes) TYPE ty_nodes_tt. + + CLASS-METHODS get_type + IMPORTING iv_x TYPE x + RETURNING VALUE(rv_type) TYPE ty_type + RAISING lcx_exception. + + CLASS-METHODS get_length + EXPORTING ev_length TYPE i + CHANGING cv_data TYPE xstring. + +ENDCLASS. "lcl_pack DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_pack IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_git_pack IMPLEMENTATION. + + METHOD sort_tree. + + TYPES: BEGIN OF ty_sort, + sort TYPE string, + node TYPE ty_node, + END OF ty_sort. + + DATA: lt_sort TYPE STANDARD TABLE OF ty_sort WITH DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF lt_sort, + LIKE LINE OF it_nodes. + + + LOOP AT it_nodes ASSIGNING . + APPEND INITIAL LINE TO lt_sort ASSIGNING . + IF -chmod = gc_chmod-dir. + CONCATENATE -name '/' INTO -sort. + ELSE. + -sort = -name. + ENDIF. + -node = . + ENDLOOP. + +* following has to be done, or unpack will fail on server side + SORT lt_sort BY sort ASCENDING. + + LOOP AT lt_sort ASSIGNING . + APPEND -node TO rt_nodes. + ENDLOOP. + + ENDMETHOD. + + METHOD type_and_length. + + DATA: lv_bits TYPE string, + lv_type TYPE string, + lv_result TYPE string, + lv_c TYPE c, + lv_offset TYPE i, + lv_x4 TYPE x LENGTH 4, + lv_x TYPE x LENGTH 1. + + + CASE is_object-type. + WHEN gc_type-commit. + lv_type = '001'. + WHEN gc_type-tree. + lv_type = '010'. + WHEN gc_type-blob. + lv_type = '011'. + WHEN gc_type-ref_d. + lv_type = '111'. + WHEN OTHERS. + _raise 'Unexpected object type while encoding pack'. + ENDCASE. + + lv_x4 = xstrlen( is_object-data ). + DO 32 TIMES. + GET BIT sy-index OF lv_x4 INTO lv_c. + CONCATENATE lv_bits lv_c INTO lv_bits. + ENDDO. + + IF lv_bits(28) = '0000000000000000000000000000'. + CONCATENATE '0' lv_type lv_bits+28(4) INTO lv_result. + ELSEIF lv_bits(21) = '000000000000000000000'. + CONCATENATE '1' lv_type lv_bits+28(4) INTO lv_result. + CONCATENATE lv_result '0' lv_bits+21(7) INTO lv_result. + ELSEIF lv_bits(14) = '00000000000000'. + CONCATENATE '1' lv_type lv_bits+28(4) INTO lv_result. + CONCATENATE lv_result '1' lv_bits+21(7) INTO lv_result. + CONCATENATE lv_result '0' lv_bits+14(7) INTO lv_result. + ELSEIF lv_bits(7) = '0000000'. + CONCATENATE '1' lv_type lv_bits+28(4) INTO lv_result. + CONCATENATE lv_result '1' lv_bits+21(7) INTO lv_result. + CONCATENATE lv_result '1' lv_bits+14(7) INTO lv_result. + CONCATENATE lv_result '0' lv_bits+7(7) INTO lv_result. + ELSE. +* this IF can be refactored, use shifting? + _raise 'Todo, encoding length'. + ENDIF. + +* convert bit string to xstring + CLEAR lv_x. + DO strlen( lv_result ) TIMES. + lv_offset = sy-index - 1. + IF lv_result+lv_offset(1) = '1'. + SET BIT ( lv_offset MOD 8 ) + 1 OF lv_x. + ENDIF. + IF ( lv_offset + 1 ) MOD 8 = 0. + CONCATENATE rv_xstring lv_x INTO rv_xstring IN BYTE MODE. + CLEAR lv_x. + ENDIF. + ENDDO. + + ENDMETHOD. "type_and_length + + METHOD get_length. + + DATA: lv_x TYPE x, + lv_length_bits TYPE string, + lv_bitbyte TYPE ty_bitbyte. + + + lv_x = cv_data(1). + lv_bitbyte = lcl_convert=>x_to_bitbyte( lv_x ). + + cv_data = cv_data+1. + lv_length_bits = lv_bitbyte+4. + + WHILE lv_bitbyte(1) <> '0'. + lv_x = cv_data(1). + lv_bitbyte = lcl_convert=>x_to_bitbyte( lv_x ). + cv_data = cv_data+1. + CONCATENATE lv_bitbyte+1 lv_length_bits INTO lv_length_bits. + ENDWHILE. + + ev_length = lcl_convert=>bitbyte_to_int( lv_length_bits ). + + ENDMETHOD. "get_length + + METHOD encode_tree. + + CONSTANTS: lc_null TYPE x VALUE '00'. + + DATA: lv_string TYPE string, + lt_nodes LIKE it_nodes, + lv_hex20 TYPE x LENGTH 20, + lv_xstring TYPE xstring. + + FIELD-SYMBOLS: LIKE LINE OF it_nodes. + + + lt_nodes = sort_tree( it_nodes ). + + LOOP AT lt_nodes ASSIGNING . + ASSERT NOT -chmod IS INITIAL. + ASSERT NOT -name IS INITIAL. + ASSERT NOT -sha1 IS INITIAL. + + CONCATENATE -chmod -name INTO lv_string SEPARATED BY space. + lv_xstring = lcl_convert=>string_to_xstring_utf8( lv_string ). + + lv_hex20 = to_upper( -sha1 ). + CONCATENATE rv_data lv_xstring lc_null lv_hex20 INTO rv_data IN BYTE MODE. + ENDLOOP. + + ENDMETHOD. "encode_tree + + METHOD encode_commit. + + DATA: lv_string TYPE string, + lv_tmp TYPE string, + lv_tree_lower TYPE string, + lv_parent_lower TYPE string. + + + lv_tree_lower = is_commit-tree. + TRANSLATE lv_tree_lower TO LOWER CASE. + + lv_parent_lower = is_commit-parent. + TRANSLATE lv_parent_lower TO LOWER CASE. + + lv_string = ''. + + CONCATENATE 'tree' lv_tree_lower INTO lv_tmp SEPARATED BY space. "#EC NOTEXT + CONCATENATE lv_string lv_tmp gc_newline INTO lv_string. + + IF NOT is_commit-parent IS INITIAL. + CONCATENATE 'parent' lv_parent_lower + INTO lv_tmp SEPARATED BY space. "#EC NOTEXT + CONCATENATE lv_string lv_tmp gc_newline INTO lv_string. + ENDIF. + + CONCATENATE 'author' is_commit-author + INTO lv_tmp SEPARATED BY space. "#EC NOTEXT + CONCATENATE lv_string lv_tmp gc_newline INTO lv_string. + + CONCATENATE 'committer' is_commit-committer + INTO lv_tmp SEPARATED BY space. "#EC NOTEXT + CONCATENATE lv_string lv_tmp gc_newline INTO lv_string. + + CONCATENATE lv_string gc_newline is_commit-body INTO lv_string. + + rv_data = lcl_convert=>string_to_xstring_utf8( lv_string ). + + ENDMETHOD. "encode_commit + + METHOD get_type. + + DATA: lv_char3 TYPE c LENGTH 3, + lv_bitbyte TYPE ty_bitbyte. + + + lv_bitbyte = lcl_convert=>x_to_bitbyte( iv_x ). + lv_char3 = lv_bitbyte+1. + + CASE lv_char3. + WHEN '001'. + rv_type = gc_type-commit. + WHEN '010'. + rv_type = gc_type-tree. + WHEN '011'. + rv_type = gc_type-blob. + WHEN '111'. + rv_type = gc_type-ref_d. + WHEN OTHERS. + _raise 'Todo, unknown type'. + ENDCASE. + + ENDMETHOD. "get_type + + METHOD decode_commit. + + DATA: lv_string TYPE string, + lv_mode TYPE string, + lv_len TYPE i, + lt_string TYPE TABLE OF string. + + FIELD-SYMBOLS: LIKE LINE OF lt_string. + + + lv_string = lcl_convert=>xstring_to_string_utf8( iv_data ). + + SPLIT lv_string AT gc_newline INTO TABLE lt_string. + + lv_mode = 'tree'. "#EC NOTEXT + LOOP AT lt_string ASSIGNING . + lv_len = strlen( lv_mode ). + + IF NOT lv_mode IS INITIAL AND (lv_len) = lv_mode. + CASE lv_mode. + WHEN 'tree'. + rs_commit-tree = +5. + lv_mode = 'parent'. "#EC NOTEXT + WHEN 'parent'. + rs_commit-parent = +7. + lv_mode = 'author'. "#EC NOTEXT + WHEN 'author'. + rs_commit-author = +7. + lv_mode = 'committer'. "#EC NOTEXT + WHEN 'committer'. + rs_commit-committer = +10. + CLEAR lv_mode. + ENDCASE. + ELSEIF lv_mode = 'parent' AND (6) = 'author'. "#EC NOTEXT +* first commit doesnt have parent + rs_commit-author = +7. + lv_mode = 'committer'. "#EC NOTEXT + ELSE. +* body + CONCATENATE rs_commit-body INTO rs_commit-body + SEPARATED BY gc_newline. + ENDIF. + ENDLOOP. + +* strip first newline + IF strlen( rs_commit-body ) >= 2. + rs_commit-body = rs_commit-body+2. + ENDIF. + + IF rs_commit-author IS INITIAL + OR rs_commit-committer IS INITIAL + OR rs_commit-tree IS INITIAL. + _raise 'multiple parents? not supported'. + ENDIF. + + ENDMETHOD. "decode_commit + + METHOD delta_header. + + DATA: lv_bitbyte TYPE ty_bitbyte, + lv_bits TYPE string, + lv_x TYPE x. + + + lv_bits = ''. + DO. + lv_x = cv_delta(1). + cv_delta = cv_delta+1. + lv_bitbyte = lcl_convert=>x_to_bitbyte( lv_x ). + CONCATENATE lv_bitbyte+1 lv_bits INTO lv_bits. + IF lv_bitbyte(1) = '0'. + EXIT. " current loop + ENDIF. + ENDDO. + ev_header = lcl_convert=>bitbyte_to_int( lv_bits ). + + ENDMETHOD. "delta_header + + METHOD delta. + + DATA: lv_delta TYPE xstring, + lv_base TYPE xstring, + lv_result TYPE xstring, + lv_bitbyte TYPE ty_bitbyte, + lv_offset TYPE i, + lv_message TYPE string, + lv_sha1 TYPE ty_sha1, + ls_object LIKE LINE OF ct_objects, + lv_len TYPE i, + lv_x TYPE x. + + FIELD-SYMBOLS: LIKE LINE OF ct_objects. + + + lv_delta = is_object-data. + +* find base + READ TABLE ct_objects ASSIGNING WITH KEY sha1 = is_object-sha1. + IF sy-subrc <> 0. + CONCATENATE 'Base not found,' is_object-sha1 INTO lv_message + SEPARATED BY space. "#EC NOTEXT + _raise lv_message. + ELSE. + lv_base = -data. + ENDIF. + +* sanity check + IF -type = gc_type-ref_d. + _raise 'Delta, base eq delta'. + ENDIF. + +* skip the 2 headers + delta_header( CHANGING cv_delta = lv_delta ). + delta_header( CHANGING cv_delta = lv_delta ). + + WHILE xstrlen( lv_delta ) > 0. + + lv_x = lv_delta(1). + lv_delta = lv_delta+1. + lv_bitbyte = lcl_convert=>x_to_bitbyte( lv_x ). + + IF lv_bitbyte(1) = '1'. " MSB + + lv_offset = 0. + IF lv_bitbyte+7(1) = '1'. + lv_x = lv_delta(1). + lv_delta = lv_delta+1. + lv_offset = lv_x. + ENDIF. + IF lv_bitbyte+6(1) = '1'. + lv_x = lv_delta(1). + lv_delta = lv_delta+1. + lv_offset = lv_offset + lv_x * 256. + ENDIF. + IF lv_bitbyte+5(1) = '1'. + lv_x = lv_delta(1). + lv_delta = lv_delta+1. + lv_offset = lv_offset + lv_x * 65536. + ENDIF. + IF lv_bitbyte+4(1) = '1'. + lv_x = lv_delta(1). + lv_delta = lv_delta+1. + lv_offset = lv_offset + lv_x * 16777216. " hmm, overflow? + ENDIF. + + lv_len = 0. + IF lv_bitbyte+3(1) = '1'. + lv_x = lv_delta(1). + lv_delta = lv_delta+1. + lv_len = lv_x. + ENDIF. + IF lv_bitbyte+2(1) = '1'. + lv_x = lv_delta(1). + lv_delta = lv_delta+1. + lv_len = lv_len + lv_x * 256. + ENDIF. + IF lv_bitbyte+1(1) = '1'. + lv_x = lv_delta(1). + lv_delta = lv_delta+1. + lv_len = lv_len + lv_x * 65536. + ENDIF. + + IF lv_len = 0. + lv_len = 65536. + ENDIF. + + CONCATENATE lv_result lv_base+lv_offset(lv_len) + INTO lv_result IN BYTE MODE. + ELSE. " lv_bitbyte(1) = '0' +* insert from delta + lv_len = lv_x. + CONCATENATE lv_result lv_delta(lv_len) INTO lv_result IN BYTE MODE. + lv_delta = lv_delta+lv_len. + ENDIF. + + ENDWHILE. + + lv_sha1 = lcl_hash=>sha1( iv_type = -type iv_data = lv_result ). + + CLEAR ls_object. + ls_object-sha1 = lv_sha1. + ls_object-type = -type. + ls_object-data = lv_result. + APPEND ls_object TO ct_objects. + + ENDMETHOD. "delta + + METHOD decode_deltas. + + DATA: ls_object LIKE LINE OF ct_objects, + lt_deltas LIKE ct_objects. + + + LOOP AT ct_objects INTO ls_object WHERE type = gc_type-ref_d. + DELETE ct_objects INDEX sy-tabix. + APPEND ls_object TO lt_deltas. + ENDLOOP. + + LOOP AT lt_deltas INTO ls_object. + delta( EXPORTING is_object = ls_object + CHANGING ct_objects = ct_objects ). + ENDLOOP. + + ENDMETHOD. "decode_deltas + + METHOD decode_tree. + + CONSTANTS: lc_sha_length TYPE i VALUE 20, + lc_null TYPE x VALUE '00'. + + DATA: lv_xstring TYPE xstring, + lv_chmod TYPE ty_chmod, + lv_name TYPE string, + lv_string TYPE string, + lv_len TYPE i, + lv_offset TYPE i, + lv_cursor TYPE i, + ls_node TYPE ty_node, + lv_start TYPE i. + + + DO. + IF lv_cursor >= xstrlen( iv_data ). + EXIT. " current loop + ENDIF. + + IF iv_data+lv_cursor(1) = lc_null. + lv_len = lv_cursor - lv_start. + lv_xstring = iv_data+lv_start(lv_len). + + lv_string = lcl_convert=>xstring_to_string_utf8( lv_xstring ). + SPLIT lv_string AT space INTO lv_chmod lv_name. + + lv_offset = lv_cursor + 1. + + CLEAR ls_node. + ls_node-chmod = lv_chmod. + IF ls_node-chmod <> gc_chmod-dir + AND ls_node-chmod <> gc_chmod-file + AND ls_node-chmod <> gc_chmod-executable. + _raise 'Unknown chmod'. + ENDIF. + + ls_node-name = lv_name. + ls_node-sha1 = iv_data+lv_offset(lc_sha_length). + TRANSLATE ls_node-sha1 TO LOWER CASE. + APPEND ls_node TO rt_nodes. + + lv_start = lv_cursor + 1 + lc_sha_length. + lv_cursor = lv_start. + ELSE. + lv_cursor = lv_cursor + 1. + ENDIF. + ENDDO. + + ENDMETHOD. "decode_tree + + METHOD decode. + + DATA: lv_x TYPE x, + lv_data TYPE xstring, + lv_type TYPE c LENGTH 6, + lv_zlib TYPE x LENGTH 2, + lv_objects TYPE i, + lv_len TYPE i, + lv_sha1 TYPE ty_sha1, + lv_ref_delta TYPE ty_sha1, + lv_adler32 TYPE lcl_hash=>ty_adler32, + lv_compressed TYPE xstring, + lv_compressed_len TYPE i, + lv_decompress_len TYPE i, + lv_decompressed TYPE xstring, + lv_xstring TYPE xstring, + lv_expected TYPE i, + ls_object LIKE LINE OF rt_objects, + ls_data TYPE lcl_zlib=>ty_decompress. + + + lv_data = iv_data. + +* header + IF NOT xstrlen( lv_data ) > 4 OR lv_data(4) <> c_pack_start. + _raise 'Unexpected pack header'. + ENDIF. + lv_data = lv_data+4. + +* version + IF lv_data(4) <> c_version. + _raise 'Version not supported'. + ENDIF. + lv_data = lv_data+4. + +* number of objects + lv_xstring = lv_data(4). + lv_objects = lcl_convert=>xstring_to_int( lv_xstring ). + lv_data = lv_data+4. + + + DO lv_objects TIMES. + + lv_x = lv_data(1). + lv_type = get_type( lv_x ). + + get_length( IMPORTING ev_length = lv_expected + CHANGING cv_data = lv_data ). + + IF lv_type = gc_type-ref_d. + lv_ref_delta = lv_data(20). + lv_data = lv_data+20. + ENDIF. + +* strip header, '789C', CMF + FLG + lv_zlib = lv_data(2). + IF lv_zlib <> c_zlib AND lv_zlib <> c_zlib_hmm. + _raise 'Unexpected zlib header'. + ENDIF. + lv_data = lv_data+2. + +******************************* + + IF lv_zlib = c_zlib. + cl_abap_gzip=>decompress_binary( + EXPORTING + gzip_in = lv_data + IMPORTING + raw_out = lv_decompressed + raw_out_len = lv_decompress_len ). + + IF lv_expected <> lv_decompress_len. + _raise 'Decompression falied'. + ENDIF. + + cl_abap_gzip=>compress_binary( + EXPORTING + raw_in = lv_decompressed + IMPORTING + gzip_out = lv_compressed + gzip_out_len = lv_compressed_len ). + + IF lv_compressed(lv_compressed_len) <> lv_data(lv_compressed_len). + _raise 'Compressed data doesnt match'. + ENDIF. + + lv_data = lv_data+lv_compressed_len. + + ELSEIF lv_zlib = c_zlib_hmm. +* cl_abap_gzip copmression works for header '789C', but does not work for +* '7801', call custom implementation of DEFLATE algorithm. +* The custom implementation could handle both, but most likely the kernel +* implementation runs faster than the custom ABAP. + ls_data = lcl_zlib=>decompress( lv_data ). + lv_compressed_len = ls_data-compressed_len. + lv_decompressed = ls_data-raw. + + IF lv_compressed_len IS INITIAL. + _raise 'Decompression falied :o/'. + ENDIF. + + lv_data = lv_data+lv_compressed_len. + + lv_adler32 = lcl_hash=>adler32( lv_decompressed ). + IF lv_data(4) <> lv_adler32. + lv_data = lv_data+1. + ENDIF. + IF lv_data(4) <> lv_adler32. + lv_data = lv_data+1. + ENDIF. + IF lv_data(4) <> lv_adler32. + _raise 'Wrong Adler checksum'. + ENDIF. + + ENDIF. + + lv_data = lv_data+4. " skip adler checksum + +************************* + + CLEAR ls_object. + IF lv_type = gc_type-ref_d. + ls_object-sha1 = lv_ref_delta. + TRANSLATE ls_object-sha1 TO LOWER CASE. + ELSE. + ls_object-sha1 = lcl_hash=>sha1( + iv_type = lv_type + iv_data = lv_decompressed ). + ENDIF. + ls_object-type = lv_type. + ls_object-data = lv_decompressed. + APPEND ls_object TO rt_objects. + ENDDO. + +* check SHA1 at end of pack + lv_len = xstrlen( iv_data ) - 20. + lv_xstring = iv_data(lv_len). + lv_sha1 = lcl_hash=>sha1_raw( lv_xstring ). + IF to_upper( lv_sha1 ) <> lv_data. + _raise 'SHA1 at end of pack doesnt match'. + ENDIF. + + ENDMETHOD. "decode + + METHOD encode. + + DATA: lv_sha1 TYPE x LENGTH 20, + lv_adler32 TYPE lcl_hash=>ty_adler32, + lv_len TYPE i, + lv_compressed TYPE xstring, + lv_xstring TYPE xstring. + + FIELD-SYMBOLS: LIKE LINE OF it_objects. + + + rv_data = c_pack_start. + + CONCATENATE rv_data c_version INTO rv_data IN BYTE MODE. + + lv_len = lines( it_objects ). + lv_xstring = lcl_convert=>int_to_xstring( iv_i = lv_len + iv_length = 4 ). + CONCATENATE rv_data lv_xstring INTO rv_data IN BYTE MODE. + + LOOP AT it_objects ASSIGNING . + lv_xstring = type_and_length( ). + CONCATENATE rv_data lv_xstring INTO rv_data IN BYTE MODE. + + cl_abap_gzip=>compress_binary( + EXPORTING + raw_in = -data + IMPORTING + gzip_out = lv_compressed ). + + CONCATENATE rv_data c_zlib lv_compressed INTO rv_data IN BYTE MODE. + + lv_adler32 = lcl_hash=>adler32( -data ). + CONCATENATE rv_data lv_adler32 INTO rv_data IN BYTE MODE. + + ENDLOOP. + + lv_sha1 = to_upper( lcl_hash=>sha1_raw( rv_data ) ). + CONCATENATE rv_data lv_sha1 INTO rv_data IN BYTE MODE. + + ENDMETHOD. "encode + +ENDCLASS. "lcl_pack IMPLEMENTATION + +CLASS ltcl_git_porcelain DEFINITION DEFERRED. + +*----------------------------------------------------------------------* +* CLASS lcl_porcelain DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_git_porcelain DEFINITION FINAL FRIENDS ltcl_git_porcelain. + + PUBLIC SECTION. + + CLASS-METHODS pull + IMPORTING io_repo TYPE REF TO lcl_repo_online + EXPORTING et_files TYPE ty_files_tt + et_objects TYPE ty_objects_tt + ev_branch TYPE ty_sha1 + RAISING lcx_exception. + + CLASS-METHODS push + IMPORTING io_repo TYPE REF TO lcl_repo_online + is_comment TYPE ty_comment + io_stage TYPE REF TO lcl_stage + RETURNING VALUE(rv_branch) TYPE ty_sha1 + RAISING lcx_exception. + + CLASS-METHODS create_branch + IMPORTING io_repo TYPE REF TO lcl_repo_online + iv_name TYPE string + iv_from TYPE ty_sha1 + RAISING lcx_exception. + + PRIVATE SECTION. + TYPES: BEGIN OF ty_expanded, + path TYPE string, + name TYPE string, + sha1 TYPE ty_sha1, + chmod TYPE ty_chmod, + END OF ty_expanded. + + TYPES: ty_expanded_tt TYPE STANDARD TABLE OF ty_expanded WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_tree, + path TYPE string, + data TYPE xstring, + sha1 TYPE ty_sha1, + END OF ty_tree. + + TYPES: ty_trees_tt TYPE STANDARD TABLE OF ty_tree WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_folder, + path TYPE string, + count TYPE i, + sha1 TYPE ty_sha1, + END OF ty_folder. + + TYPES: ty_folders_tt TYPE STANDARD TABLE OF ty_folder WITH DEFAULT KEY. + + CLASS-METHODS build_trees + IMPORTING it_expanded TYPE ty_expanded_tt + RETURNING VALUE(rt_trees) TYPE ty_trees_tt + RAISING lcx_exception. + + CLASS-METHODS find_folders + IMPORTING it_expanded TYPE ty_expanded_tt + RETURNING VALUE(rt_folders) TYPE ty_folders_tt. + + CLASS-METHODS walk + IMPORTING it_objects TYPE ty_objects_tt + iv_sha1 TYPE ty_sha1 + iv_path TYPE string + CHANGING ct_files TYPE ty_files_tt + RAISING lcx_exception. + + CLASS-METHODS walk_tree + IMPORTING it_objects TYPE ty_objects_tt + iv_tree TYPE ty_sha1 + iv_base TYPE string + RETURNING VALUE(rt_expanded) TYPE ty_expanded_tt + RAISING lcx_exception. + + CLASS-METHODS full_tree + IMPORTING it_objects TYPE ty_objects_tt + iv_branch TYPE ty_sha1 + RETURNING VALUE(rt_expanded) TYPE ty_expanded_tt + RAISING lcx_exception. + + CLASS-METHODS receive_pack + IMPORTING is_comment TYPE ty_comment + io_repo TYPE REF TO lcl_repo_online + it_trees TYPE ty_trees_tt + it_blobs TYPE ty_files_tt + iv_branch TYPE ty_sha1 + RETURNING VALUE(rv_branch) TYPE ty_sha1 + RAISING lcx_exception. + +ENDCLASS. "lcl_porcelain DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_porcelain IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_git_porcelain IMPLEMENTATION. + + METHOD receive_pack. + + DATA: lv_time TYPE lcl_time=>ty_unixtime, + lv_commit TYPE xstring, + lt_objects TYPE ty_objects_tt, + lv_pack TYPE xstring, + ls_object LIKE LINE OF lt_objects, + ls_commit TYPE lcl_git_pack=>ty_commit. + + FIELD-SYMBOLS: LIKE LINE OF it_trees, + LIKE LINE OF it_blobs. + + + lv_time = lcl_time=>get( ). + + READ TABLE it_trees ASSIGNING WITH KEY path = '/'. + ASSERT sy-subrc = 0. + +* new commit + ls_commit-tree = -sha1. + ls_commit-parent = iv_branch. + CONCATENATE is_comment-username space '<' is_comment-email '>' space lv_time + INTO ls_commit-author RESPECTING BLANKS. + ls_commit-committer = ls_commit-author. + ls_commit-body = is_comment-comment. + lv_commit = lcl_git_pack=>encode_commit( ls_commit ). + + CLEAR ls_object. + ls_object-sha1 = lcl_hash=>sha1( iv_type = gc_type-commit iv_data = lv_commit ). + ls_object-type = gc_type-commit. + ls_object-data = lv_commit. + APPEND ls_object TO lt_objects. + + LOOP AT it_trees ASSIGNING . + CLEAR ls_object. + ls_object-sha1 = -sha1. + ls_object-type = gc_type-tree. + ls_object-data = -data. + APPEND ls_object TO lt_objects. + ENDLOOP. + + LOOP AT it_blobs ASSIGNING . + CLEAR ls_object. + ls_object-sha1 = lcl_hash=>sha1( iv_type = gc_type-blob iv_data = -data ). + ls_object-type = gc_type-blob. + ls_object-data = -data. + APPEND ls_object TO lt_objects. + ENDLOOP. + + lv_pack = lcl_git_pack=>encode( lt_objects ). + + rv_branch = lcl_hash=>sha1( + iv_type = gc_type-commit + iv_data = lv_commit ). + + lcl_git_transport=>receive_pack( + io_repo = io_repo + iv_old = io_repo->get_sha1_local( ) + iv_new = rv_branch + iv_branch_name = io_repo->get_branch_name( ) + iv_pack = lv_pack ). + + ENDMETHOD. "receive_pack + + METHOD create_branch. + + DATA: lv_zero TYPE ty_sha1, + lt_objects TYPE ty_objects_tt, + lv_pack TYPE xstring. + + + lv_zero = '0000000000000000000000000000000000000000'. + +* "client MUST send an empty packfile" +* https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L514 + lv_pack = lcl_git_pack=>encode( lt_objects ). + + lcl_git_transport=>receive_pack( + io_repo = io_repo + iv_old = lv_zero + iv_new = iv_from + iv_branch_name = iv_name + iv_pack = lv_pack ). + + ENDMETHOD. + + METHOD push. + + DATA: lt_expanded TYPE ty_expanded_tt, + lt_blobs TYPE ty_files_tt, + lv_sha1 TYPE ty_sha1, + lt_trees TYPE ty_trees_tt, + lt_stage TYPE lcl_stage=>ty_stage_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_stage, + LIKE LINE OF lt_expanded. + + + lt_expanded = full_tree( it_objects = io_repo->get_objects( ) + iv_branch = io_repo->get_sha1_remote( ) ). + + lt_stage = io_stage->get_all( ). + LOOP AT lt_stage ASSIGNING . + CASE -method. + WHEN lcl_stage=>c_method-add. + APPEND -file TO lt_blobs. + + READ TABLE lt_expanded ASSIGNING WITH KEY + name = -file-filename + path = -file-path. + IF sy-subrc <> 0. " new files + APPEND INITIAL LINE TO lt_expanded ASSIGNING . + -name = -file-filename. + -path = -file-path. + -chmod = gc_chmod-file. + ENDIF. + + lv_sha1 = lcl_hash=>sha1( iv_type = gc_type-blob iv_data = -file-data ). + IF -sha1 <> lv_sha1. + -sha1 = lv_sha1. + ENDIF. + WHEN lcl_stage=>c_method-rm. + DELETE lt_expanded + WHERE name = -file-filename + AND path = -file-path. + ASSERT sy-subrc = 0. + WHEN OTHERS. + _raise 'stage method not supported, todo'. + ENDCASE. + ENDLOOP. + + lt_trees = build_trees( lt_expanded ). + + rv_branch = receive_pack( is_comment = is_comment + io_repo = io_repo + it_trees = lt_trees + it_blobs = lt_blobs + iv_branch = io_repo->get_sha1_remote( ) ). + + ENDMETHOD. "push + + METHOD walk_tree. + + DATA: ls_object LIKE LINE OF it_objects, + lt_expanded LIKE rt_expanded, + lt_nodes TYPE lcl_git_pack=>ty_nodes_tt. + + FIELD-SYMBOLS: LIKE LINE OF rt_expanded, + LIKE LINE OF lt_nodes. + + + READ TABLE it_objects INTO ls_object + WITH KEY sha1 = iv_tree + type = gc_type-tree. + IF sy-subrc <> 0. + _raise 'tree not found'. + ENDIF. + lt_nodes = lcl_git_pack=>decode_tree( ls_object-data ). + + LOOP AT lt_nodes ASSIGNING . + CASE -chmod. + WHEN gc_chmod-file + OR gc_chmod-executable. + APPEND INITIAL LINE TO rt_expanded ASSIGNING . + -path = iv_base. + -name = -name. + -sha1 = -sha1. + -chmod = -chmod. + WHEN gc_chmod-dir. + lt_expanded = walk_tree( + it_objects = it_objects + iv_tree = -sha1 + iv_base = iv_base && -name && '/' ). + APPEND LINES OF lt_expanded TO rt_expanded. + WHEN OTHERS. + _raise 'walk_tree: unknown chmod'. + ENDCASE. + ENDLOOP. + + ENDMETHOD. + + METHOD full_tree. + + DATA: ls_object LIKE LINE OF it_objects, + ls_commit TYPE lcl_git_pack=>ty_commit. + + + READ TABLE it_objects INTO ls_object WITH KEY sha1 = iv_branch type = gc_type-commit. + IF sy-subrc <> 0. + _raise 'commit not found'. + ENDIF. + ls_commit = lcl_git_pack=>decode_commit( ls_object-data ). + + rt_expanded = walk_tree( it_objects = it_objects + iv_tree = ls_commit-tree + iv_base = '/' ). + + ENDMETHOD. "root_tree + + METHOD pull. + + DATA: ls_object LIKE LINE OF et_objects, + ls_commit TYPE lcl_git_pack=>ty_commit, + lv_pack TYPE xstring. + + + CLEAR et_files. + CLEAR et_objects. + CLEAR ev_branch. + + lcl_git_transport=>upload_pack( EXPORTING io_repo = io_repo + IMPORTING ev_pack = lv_pack + ev_branch = ev_branch ). + + IF lv_pack IS INITIAL. + _raise 'empty pack'. + ENDIF. + + et_objects = lcl_git_pack=>decode( lv_pack ). + + lcl_git_pack=>decode_deltas( CHANGING ct_objects = et_objects ). + + READ TABLE et_objects INTO ls_object WITH KEY sha1 = ev_branch type = gc_type-commit. + IF sy-subrc <> 0. + _raise 'Commit/branch not found'. + ENDIF. + ls_commit = lcl_git_pack=>decode_commit( ls_object-data ). + + walk( EXPORTING it_objects = et_objects + iv_sha1 = ls_commit-tree + iv_path = '/' + CHANGING ct_files = et_files ). + + ENDMETHOD. "pull + + METHOD find_folders. + + DATA: lt_paths TYPE TABLE OF string, + lv_split TYPE string, + lv_path TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF rt_folders, + LIKE LINE OF rt_folders, + LIKE LINE OF it_expanded. + + + LOOP AT it_expanded ASSIGNING . + READ TABLE rt_folders WITH KEY path = -path TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO rt_folders ASSIGNING . + -path = -path. + ENDIF. + ENDLOOP. + +* add empty folders + LOOP AT rt_folders ASSIGNING . + SPLIT -path AT '/' INTO TABLE lt_paths. + + CLEAR lv_path. + LOOP AT lt_paths INTO lv_split. + CONCATENATE lv_path lv_split '/' INTO lv_path. + READ TABLE rt_folders WITH KEY path = lv_path TRANSPORTING NO FIELDS. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO rt_folders ASSIGNING . + -path = lv_path. + ENDIF. + ENDLOOP. + ENDLOOP. + + LOOP AT rt_folders ASSIGNING . + FIND ALL OCCURRENCES OF '/' IN -path MATCH COUNT -count. + ENDLOOP. + + ENDMETHOD. + + METHOD build_trees. + + DATA: lt_nodes TYPE lcl_git_pack=>ty_nodes_tt, + ls_tree LIKE LINE OF rt_trees, + lv_sub TYPE string, + lv_len TYPE i, + lt_folders TYPE ty_folders_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_folders, + LIKE LINE OF lt_nodes, + LIKE LINE OF lt_folders, + LIKE LINE OF it_expanded. + + + lt_folders = find_folders( it_expanded ). + +* start with the deepest folders + SORT lt_folders BY count DESCENDING. + + LOOP AT lt_folders ASSIGNING . + CLEAR lt_nodes. + +* files + LOOP AT it_expanded ASSIGNING WHERE path = -path. + APPEND INITIAL LINE TO lt_nodes ASSIGNING . + -chmod = -chmod. + -name = -name. + -sha1 = -sha1. + ENDLOOP. + +* folders + lv_sub = -path && '+*'. + LOOP AT lt_folders ASSIGNING + WHERE count = -count + 1 AND path CP lv_sub. + APPEND INITIAL LINE TO lt_nodes ASSIGNING . + -chmod = gc_chmod-dir. + +* extract folder name, this can probably be done easier using regular expressions + lv_len = strlen( -path ). + -name = -path+lv_len. + lv_len = strlen( -name ) - 1. + -name = -name(lv_len). + + -sha1 = -sha1. + ENDLOOP. + + CLEAR ls_tree. + ls_tree-path = -path. + ls_tree-data = lcl_git_pack=>encode_tree( lt_nodes ). + ls_tree-sha1 = lcl_hash=>sha1( iv_type = gc_type-tree iv_data = ls_tree-data ). + APPEND ls_tree TO rt_trees. + + -sha1 = ls_tree-sha1. + ENDLOOP. + + ENDMETHOD. + + METHOD walk. + + DATA: lv_path TYPE string, + ls_file LIKE LINE OF ct_files, + lt_nodes TYPE lcl_git_pack=>ty_nodes_tt. + + FIELD-SYMBOLS: LIKE LINE OF it_objects, + LIKE LINE OF it_objects, + LIKE LINE OF lt_nodes. + + + READ TABLE it_objects ASSIGNING WITH KEY sha1 = iv_sha1 type = gc_type-tree. + IF sy-subrc <> 0. + _raise 'Walk, tree not found'. + ENDIF. + + lt_nodes = lcl_git_pack=>decode_tree( -data ). + + LOOP AT lt_nodes ASSIGNING . + IF -chmod = gc_chmod-file. + READ TABLE it_objects ASSIGNING + WITH KEY sha1 = -sha1 type = gc_type-blob. + IF sy-subrc <> 0. + _raise 'Walk, blob not found'. + ENDIF. + + CLEAR ls_file. + ls_file-path = iv_path. + ls_file-filename = -name. + ls_file-data = -data. + APPEND ls_file TO ct_files. + ENDIF. + ENDLOOP. + + LOOP AT lt_nodes ASSIGNING WHERE chmod = gc_chmod-dir. + CONCATENATE iv_path -name '/' INTO lv_path. + walk( EXPORTING it_objects = it_objects + iv_sha1 = -sha1 + iv_path = lv_path + CHANGING ct_files = ct_files ). + ENDLOOP. + + ENDMETHOD. "walk + +ENDCLASS. "lcl_porcelain IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_git.prog.xml b/src/zabapgit_git.prog.xml new file mode 100644 index 000000000..8e3e91b43 --- /dev/null +++ b/src/zabapgit_git.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_GIT + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_GIT + 20 + + + + + + diff --git a/src/zabapgit_html.prog.abap b/src/zabapgit_html.prog.abap new file mode 100644 index 000000000..c017812ca --- /dev/null +++ b/src/zabapgit_html.prog.abap @@ -0,0 +1,543 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_HTML +*&---------------------------------------------------------------------* + +*----------------------------------------------------------------------* +* CLASS lcl_html_action_utils DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_html_action_utils DEFINITION FINAL. + PUBLIC SECTION. + + TYPES: BEGIN OF ty_commit_fields, "TODO refactor ! Move to normal place + repo_key TYPE lcl_persistence_repo=>ty_repo-key, + username TYPE string, + email TYPE string, + comment TYPE string, + body TYPE string, + END OF ty_commit_fields. + + CLASS-METHODS jump_encode + IMPORTING iv_obj_type TYPE tadir-object + iv_obj_name TYPE tadir-obj_name + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS jump_decode + IMPORTING iv_string TYPE clike + EXPORTING ev_obj_type TYPE tadir-object + ev_obj_name TYPE tadir-obj_name + RAISING lcx_exception. + + CLASS-METHODS file_encode + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + ig_file TYPE any "ty_repo_file + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS file_decode + IMPORTING iv_string TYPE clike + EXPORTING ev_key TYPE lcl_persistence_repo=>ty_repo-key + eg_file TYPE any "ty_repo_file + RAISING lcx_exception. + + CLASS-METHODS dbkey_encode + IMPORTING is_key TYPE lcl_persistence_db=>ty_content + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS dbkey_decode + IMPORTING iv_string TYPE clike + RETURNING VALUE(rs_key) TYPE lcl_persistence_db=>ty_content. + + CLASS-METHODS parse_commit_request + IMPORTING it_postdata TYPE cnht_post_data_tab + RETURNING VALUE(rs_fields) TYPE ty_commit_fields. + + CLASS-METHODS repo_key_encode + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS repo_key_decode + IMPORTING iv_string TYPE clike + RETURNING VALUE(rv_key) TYPE lcl_persistence_repo=>ty_repo-key. + +ENDCLASS. "lcl_html_action_utils DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_html_action_utils IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_html_action_utils IMPLEMENTATION. + + METHOD jump_encode. + + DATA: lt_fields TYPE tihttpnvp, + ls_field LIKE LINE OF lt_fields. + + + ls_field-name = 'TYPE'. + ls_field-value = iv_obj_type. + APPEND ls_field TO lt_fields. + + ls_field-name = 'NAME'. + ls_field-value = iv_obj_name. + APPEND ls_field TO lt_fields. + + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "jump_encode + + METHOD jump_decode. + + DATA: lt_fields TYPE tihttpnvp, + lv_string TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF lt_fields. + + + lv_string = iv_string. " type conversion + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'TYPE'. + IF sy-subrc = 0. + ev_obj_type = -value. + ELSE. + CLEAR ev_obj_type. + ENDIF. + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'NAME'. + IF sy-subrc = 0. + ev_obj_name = -value. + ELSE. + CLEAR ev_obj_name. + ENDIF. + + ENDMETHOD. "jump_decode + + METHOD file_encode. + + DATA: lt_fields TYPE tihttpnvp, + ls_field LIKE LINE OF lt_fields. + + FIELD-SYMBOLS TYPE string. + + ls_field-name = 'KEY'. + ls_field-value = iv_key. + APPEND ls_field TO lt_fields. + + ls_field-name = 'PATH'. + ASSIGN COMPONENT ls_field-name OF STRUCTURE ig_file TO . + ASSERT IS ASSIGNED. + ls_field-value = . + APPEND ls_field TO lt_fields. + + ls_field-name = 'FILENAME'. + ASSIGN COMPONENT ls_field-name OF STRUCTURE ig_file TO . + ASSERT IS ASSIGNED. + ls_field-value = . + APPEND ls_field TO lt_fields. + + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "file_encode + + METHOD file_decode. + + DATA: lt_fields TYPE tihttpnvp, + lv_string TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF lt_fields, + TYPE string. + + CLEAR: ev_key, eg_file. + lv_string = iv_string. " type conversion + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'KEY'. + IF sy-subrc = 0. + ev_key = -value. + ENDIF. + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'PATH'. + IF sy-subrc = 0. + ASSIGN COMPONENT 'PATH' OF STRUCTURE eg_file TO . + ASSERT IS ASSIGNED. + = -value. + ENDIF. + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'FILENAME'. + IF sy-subrc = 0. + ASSIGN COMPONENT 'FILENAME' OF STRUCTURE eg_file TO . + ASSERT IS ASSIGNED. + = -value. + ENDIF. + + ENDMETHOD. "file_decode + + METHOD dbkey_encode. + + DATA: lt_fields TYPE tihttpnvp, + ls_field LIKE LINE OF lt_fields. + + ls_field-name = 'TYPE'. + ls_field-value = is_key-type. + APPEND ls_field TO lt_fields. + + ls_field-name = 'VALUE'. + ls_field-value = is_key-value. + APPEND ls_field TO lt_fields. + + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "dbkey_encode + + METHOD dbkey_decode. + + DATA: lt_fields TYPE tihttpnvp, + lv_string TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF lt_fields. + + lv_string = iv_string. " type conversion + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'TYPE'. + IF sy-subrc = 0. + rs_key-type = -value. + ENDIF. + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'VALUE'. + IF sy-subrc = 0. + rs_key-value = -value. + ENDIF. + + ENDMETHOD. "dbkey_decode + + METHOD parse_commit_request. + + CONSTANTS: lc_replace TYPE string VALUE '<>'. + + DATA: lv_string TYPE string, + lt_fields TYPE tihttpnvp. + + FIELD-SYMBOLS: LIKE LINE OF lt_fields. + + + CONCATENATE LINES OF it_postdata INTO lv_string. + + REPLACE ALL OCCURRENCES OF gc_newline IN lv_string WITH lc_replace. + + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'key' ##NO_TEXT. + ASSERT sy-subrc = 0. + rs_fields-repo_key = -value. + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'username' ##NO_TEXT. + ASSERT sy-subrc = 0. + rs_fields-username = -value. + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'email' ##NO_TEXT. + ASSERT sy-subrc = 0. + rs_fields-email = -value. + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'comment' ##NO_TEXT. + ASSERT sy-subrc = 0. + rs_fields-comment = -value. + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'body' ##NO_TEXT. + ASSERT sy-subrc = 0. + rs_fields-body = -value. + REPLACE ALL OCCURRENCES OF lc_replace IN rs_fields-body WITH gc_newline. + + ENDMETHOD. "parse_commit_request + + METHOD repo_key_encode. + + DATA: lt_fields TYPE tihttpnvp, + ls_field LIKE LINE OF lt_fields. + + ls_field-name = 'KEY'. + ls_field-value = iv_key. + APPEND ls_field TO lt_fields. + + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "repo_key_encode + + METHOD repo_key_decode. + + DATA: lt_fields TYPE tihttpnvp, + lv_string TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF lt_fields. + + lv_string = iv_string. " type conversion + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( lv_string ). + + READ TABLE lt_fields ASSIGNING WITH KEY name = 'KEY'. + IF sy-subrc = 0. + rv_key = -value. + ENDIF. + + ENDMETHOD. "repo_key_decode + +ENDCLASS. "lcl_html_action_utils IMPLEMENTATION + +*----------------------------------------------------------------------* +* CLASS lcl_html_helper DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_html_helper DEFINITION FINAL. + PUBLIC SECTION. + CONSTANTS: c_indent_size TYPE i VALUE 2. + + DATA mv_html TYPE string READ-ONLY. + DATA mv_indent TYPE i READ-ONLY. + + METHODS add IMPORTING iv_chunk TYPE any. + METHODS reset. + + METHODS add_anchor IMPORTING iv_txt TYPE string + iv_act TYPE string + iv_opt TYPE char1 OPTIONAL + iv_typ TYPE char1 DEFAULT gc_action_type-sapevent + iv_class TYPE string OPTIONAL. + + PRIVATE SECTION. + METHODS _add_str IMPORTING iv_str TYPE csequence. + METHODS _add_htm IMPORTING io_html TYPE REF TO lcl_html_helper. + +ENDCLASS. "lcl_html_helper DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_html_helper IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_html_helper IMPLEMENTATION. + METHOD add. + DATA lo_type TYPE REF TO cl_abap_typedescr. + DATA lo_html TYPE REF TO lcl_html_helper. + + lo_type = cl_abap_typedescr=>describe_by_data( iv_chunk ). + + CASE lo_type->type_kind. + WHEN cl_abap_typedescr=>typekind_char + OR cl_abap_typedescr=>typekind_string. + IF strlen( iv_chunk ) = 0. + RETURN. + ENDIF. + _add_str( iv_chunk ). + WHEN cl_abap_typedescr=>typekind_oref. + ASSERT iv_chunk IS BOUND. " Dev mistake + TRY. + lo_html ?= iv_chunk. + CATCH cx_sy_move_cast_error. + ASSERT 1 = 0. " Dev mistake + ENDTRY. + _add_htm( lo_html ). + WHEN OTHERS. + ASSERT 1 = 0. " Dev mistake + ENDCASE. + + ENDMETHOD. " add + + METHOD reset. + CLEAR: me->mv_html, me->mv_indent. + ENDMETHOD. "reset + + METHOD _add_str. + CONSTANTS lc_single_tags_re TYPE string " HTML5 singleton tags + VALUE '<(area|base|br|col|command|embed|hr|img|input|link|meta|param|source|!)'. + + DATA lv_tags TYPE i. + DATA lv_tags_open TYPE i. + DATA lv_tags_close TYPE i. + DATA lv_tags_single TYPE i. + DATA lv_close_offs TYPE i. + DATA lv_shift_back TYPE i. + + FIND FIRST OCCURRENCE OF ' 0. " Found close tag @beginning + lv_shift_back = 1. + ENDIF. + + mv_html = mv_html + && repeat( val = ` ` occ = ( mv_indent - lv_shift_back ) * c_indent_size ) + && iv_str + && gc_newline. + + FIND ALL OCCURRENCES OF '<' IN iv_str MATCH COUNT lv_tags. + FIND ALL OCCURRENCES OF '' + IF lv_tags_open > lv_tags_close. + mv_indent = mv_indent + 1. + ELSEIF lv_tags_open < lv_tags_close AND mv_indent > 0. + mv_indent = mv_indent - 1. + ENDIF. + + ENDMETHOD. "_add_str + + METHOD _add_htm. + + DATA lt_strtab TYPE TABLE OF string. + DATA lv_str TYPE string. + + SPLIT io_html->mv_html AT gc_newline INTO TABLE lt_strtab. + LOOP AT lt_strtab INTO lv_str. + SHIFT lv_str LEFT DELETING LEADING space. + _add_str( lv_str ). + ENDLOOP. + + ENDMETHOD. "_add_htm + + METHOD add_anchor. + DATA: lv_class TYPE string, + lv_href TYPE string. + + lv_class = iv_class. + + IF iv_opt = gc_html_opt-emphas. + lv_class = lv_class && ' emphasis' ##NO_TEXT. + ENDIF. + IF iv_opt = gc_html_opt-cancel. + lv_class = lv_class && ' attention' ##NO_TEXT. + ENDIF. + IF lv_class IS NOT INITIAL. + SHIFT lv_class LEFT DELETING LEADING space. + lv_class = | class="{ lv_class }"|. + ENDIF. + + IF iv_act IS NOT INITIAL. + CASE iv_typ. + WHEN gc_action_type-url. + lv_href = | href="{ iv_act }"|. + WHEN gc_action_type-sapevent. + lv_href = | href="sapevent:{ iv_act }"|. + WHEN gc_action_type-onclick. + lv_href = | onclick="{ iv_act }"|. + WHEN OTHERS. + ENDCASE. + ENDIF. + + _add_str( |{ iv_txt }| ). + + ENDMETHOD. "add_action + +ENDCLASS. "lcl_html_helper IMPLEMENTATION + +*----------------------------------------------------------------------* +* CLASS lcl_html_toolbar DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_html_toolbar DEFINITION FINAL. + PUBLIC SECTION. + METHODS add IMPORTING iv_txt TYPE string + io_sub TYPE REF TO lcl_html_toolbar OPTIONAL + iv_act TYPE string OPTIONAL + iv_opt TYPE c OPTIONAL + iv_typ TYPE c DEFAULT gc_action_type-sapevent. + + METHODS render IMPORTING iv_as_droplist_with_label TYPE string OPTIONAL + iv_no_separator TYPE abap_bool OPTIONAL + iv_vertical TYPE abap_bool OPTIONAL + RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. + + METHODS reset. + + PRIVATE SECTION. + TYPES: BEGIN OF ty_item, + txt TYPE string, + act TYPE string, + sub TYPE REF TO lcl_html_toolbar, + opt TYPE char1, + typ TYPE char1, + END OF ty_item. + TYPES: tt_items TYPE STANDARD TABLE OF ty_item. + + DATA mt_items TYPE tt_items. + +ENDCLASS. "lcl_html_toolbar DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_html_toolbar IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_html_toolbar IMPLEMENTATION. + + METHOD reset. + CLEAR mt_items. + ENDMETHOD. "reset + + METHOD add. + DATA ls_item TYPE ty_item. + + ASSERT iv_act IS INITIAL AND io_sub IS NOT INITIAL + OR iv_act IS NOT INITIAL AND io_sub IS INITIAL. " Only one supplied + + ls_item-txt = iv_txt. + ls_item-act = iv_act. + ls_item-sub = io_sub. + ls_item-opt = iv_opt. + ls_item-typ = iv_typ. + APPEND ls_item TO mt_items. + ENDMETHOD. "add + + METHOD render. + DATA: + lv_class TYPE string, + lv_last TYPE abap_bool. + + FIELD-SYMBOLS LIKE LINE OF mt_items. + + CREATE OBJECT ro_html. + + IF iv_as_droplist_with_label IS INITIAL. + IF iv_vertical = abap_true. + lv_class = 'menu_vertical' ##NO_TEXT. + ELSE. + lv_class = 'menu' ##NO_TEXT. + ENDIF. + ELSE. + lv_class = 'dropdown' ##NO_TEXT. + ENDIF. + + ro_html->add( |
| ). + + IF iv_as_droplist_with_label IS NOT INITIAL. + lv_class = 'dropbtn'. + IF iv_no_separator = abap_true. + lv_class = lv_class && ' menu_end' ##NO_TEXT. + ENDIF. + ro_html->add( |{ iv_as_droplist_with_label }| ). + ro_html->add( '' ). + ENDIF. + + ro_html->add( '
' ). + + ENDMETHOD. "render + +ENDCLASS. "lcl_html_toolbar IMPLEMENTATION \ No newline at end of file diff --git a/src/zabapgit_html.prog.xml b/src/zabapgit_html.prog.xml new file mode 100644 index 000000000..60fedebc9 --- /dev/null +++ b/src/zabapgit_html.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_HTML + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_HTML + 21 + + + + + + diff --git a/src/zabapgit_persistence.prog.abap b/src/zabapgit_persistence.prog.abap new file mode 100644 index 000000000..5fb3800e5 --- /dev/null +++ b/src/zabapgit_persistence.prog.abap @@ -0,0 +1,1682 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_PERSISTENCE +*&---------------------------------------------------------------------* + +CLASS lcl_persistence_migrate DEFINITION FINAL. + + PUBLIC SECTION. + CLASS-METHODS: run RAISING lcx_exception. + + PRIVATE SECTION. + CONSTANTS: + c_text TYPE string VALUE 'Generated by abapGit' ##NO_TEXT. + + CLASS-METHODS: + migrate_repo RAISING lcx_exception, + migrate_user RAISING lcx_exception, + table_create RAISING lcx_exception, + table_exists + RETURNING VALUE(rv_exists) TYPE abap_bool, + lock_create RAISING lcx_exception, + lock_exists + RETURNING VALUE(rv_exists) TYPE abap_bool. + +ENDCLASS. + +CLASS lcl_persistence_db DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. + + PUBLIC SECTION. + CONSTANTS: + c_tabname TYPE tabname VALUE 'ZABAPGIT', + c_lock TYPE viewname VALUE 'EZABAPGIT'. + + TYPES: ty_type TYPE c LENGTH 12. + TYPES: ty_value TYPE c LENGTH 12. + + TYPES: BEGIN OF ty_content, + type TYPE ty_type, + value TYPE ty_value, + data_str TYPE string, + END OF ty_content, + tt_content TYPE SORTED TABLE OF ty_content WITH UNIQUE KEY type value. + + METHODS list_by_type + IMPORTING iv_type TYPE ty_type + RETURNING VALUE(rt_content) TYPE tt_content. + + METHODS list + RETURNING VALUE(rt_content) TYPE tt_content. + + METHODS add + IMPORTING iv_type TYPE ty_type + iv_value TYPE ty_content-value + iv_data TYPE ty_content-data_str + RAISING lcx_exception. + + METHODS delete + IMPORTING iv_type TYPE ty_type + iv_value TYPE ty_content-value + RAISING lcx_exception. + + METHODS update + IMPORTING iv_type TYPE ty_type + iv_value TYPE ty_content-value + iv_data TYPE ty_content-data_str + RAISING lcx_exception. + + METHODS modify + IMPORTING iv_type TYPE ty_type + iv_value TYPE ty_content-value + iv_data TYPE ty_content-data_str + RAISING lcx_exception. + + METHODS read + IMPORTING iv_type TYPE ty_type + iv_value TYPE ty_content-value + RETURNING VALUE(rv_data) TYPE ty_content-data_str + RAISING lcx_not_found. + + METHODS lock + IMPORTING iv_mode TYPE enqmode DEFAULT 'E' + iv_type TYPE ty_type + iv_value TYPE ty_content-value + RAISING lcx_exception. + +ENDCLASS. + +CLASS lcl_persistence_repo DEFINITION FINAL. + + PUBLIC SECTION. + TYPES: BEGIN OF ty_local_checksum, + item TYPE ty_item, + sha1 TYPE ty_sha1, + END OF ty_local_checksum. + + TYPES: ty_local_checksum_tt TYPE STANDARD TABLE OF ty_local_checksum WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_repo_xml, + url TYPE string, + branch_name TYPE string, + sha1 TYPE ty_sha1, + package TYPE devclass, + offline TYPE sap_bool, + local_checksums TYPE ty_local_checksum_tt, + master_language TYPE spras, + END OF ty_repo_xml. + + TYPES: BEGIN OF ty_repo, + key TYPE lcl_persistence_db=>ty_value. + INCLUDE TYPE ty_repo_xml. + TYPES: END OF ty_repo. + TYPES: tt_repo TYPE STANDARD TABLE OF ty_repo WITH DEFAULT KEY. + + METHODS constructor. + + METHODS list + RETURNING VALUE(rt_repos) TYPE tt_repo + RAISING lcx_exception. + + METHODS update_sha1 + IMPORTING iv_key TYPE ty_repo-key + iv_branch_sha1 TYPE ty_repo_xml-sha1 + RAISING lcx_exception. + + METHODS update_local_checksums + IMPORTING iv_key TYPE ty_repo-key + it_checksums TYPE ty_repo_xml-local_checksums + RAISING lcx_exception. + + METHODS update_url + IMPORTING iv_key TYPE ty_repo-key + iv_url TYPE ty_repo_xml-url + RAISING lcx_exception. + + METHODS update_branch_name + IMPORTING iv_key TYPE ty_repo-key + iv_branch_name TYPE ty_repo_xml-branch_name + RAISING lcx_exception. + + METHODS add + IMPORTING iv_url TYPE string + iv_branch_name TYPE string + iv_branch TYPE ty_sha1 OPTIONAL + iv_package TYPE devclass + iv_offline TYPE sap_bool DEFAULT abap_false + RETURNING VALUE(rv_key) TYPE ty_repo-key + RAISING lcx_exception. + + METHODS delete + IMPORTING iv_key TYPE ty_repo-key + RAISING lcx_exception. + + METHODS read + IMPORTING iv_key TYPE ty_repo-key + RETURNING VALUE(rs_repo) TYPE ty_repo + RAISING lcx_exception + lcx_not_found. + + METHODS lock + IMPORTING iv_mode TYPE enqmode + iv_key TYPE ty_repo-key + RAISING lcx_exception. + + PRIVATE SECTION. + CONSTANTS c_type_repo TYPE lcl_persistence_db=>ty_type VALUE 'REPO'. + + DATA: mo_db TYPE REF TO lcl_persistence_db. + + METHODS from_xml + IMPORTING iv_repo_xml_string TYPE string + RETURNING VALUE(rs_repo) TYPE ty_repo_xml + RAISING lcx_exception. + + METHODS to_xml + IMPORTING is_repo TYPE ty_repo + RETURNING VALUE(rv_repo_xml_string) TYPE string. + + METHODS get_next_id + RETURNING VALUE(rv_next_repo_id) TYPE lcl_persistence_db=>ty_content-value + RAISING lcx_exception. + +ENDCLASS. + +*----------------------------------------------------------------------* +* CLASS lcl_persistence DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_persistence DEFINITION FINAL FRIENDS lcl_persistence_migrate. + +* this class is obsolete, use LCL_PERSISTENCE_REPO instead + + PRIVATE SECTION. + TYPES: BEGIN OF ty_repo_persi, + url TYPE string, + branch_name TYPE string, + sha1 TYPE ty_sha1, + package TYPE devclass, + offline TYPE sap_bool, + END OF ty_repo_persi. + TYPES: ty_repos_persi_tt TYPE STANDARD TABLE OF ty_repo_persi WITH DEFAULT KEY. + + METHODS list + RETURNING VALUE(rt_repos) TYPE ty_repos_persi_tt + RAISING lcx_exception. + + METHODS update + IMPORTING iv_url TYPE ty_repo_persi-url + iv_branch_name TYPE ty_repo_persi-branch_name + iv_branch TYPE ty_sha1 + RAISING lcx_exception. + + METHODS add + IMPORTING iv_url TYPE string + iv_branch_name TYPE string + iv_branch TYPE ty_sha1 OPTIONAL + iv_package TYPE devclass + iv_offline TYPE sap_bool DEFAULT abap_false + RAISING lcx_exception. + + METHODS delete + IMPORTING iv_url TYPE ty_repo_persi-url + iv_branch_name TYPE ty_repo_persi-branch_name + RAISING lcx_exception. + + METHODS read_text_online + RETURNING VALUE(rt_repos) TYPE ty_repos_persi_tt + RAISING lcx_exception. + + METHODS save_text_online + IMPORTING it_repos TYPE ty_repos_persi_tt + RAISING lcx_exception. + + METHODS header_online + RETURNING VALUE(rs_header) TYPE thead. + + METHODS read_text_offline + RETURNING VALUE(rt_repos) TYPE ty_repos_persi_tt + RAISING lcx_exception. + + METHODS save_text_offline + IMPORTING it_repos TYPE ty_repos_persi_tt + RAISING lcx_exception. + + METHODS header_offline + RETURNING VALUE(rs_header) TYPE thead. + + METHODS read_text + IMPORTING is_header TYPE thead + RETURNING VALUE(rt_lines) TYPE tlinetab + RAISING lcx_exception. + + METHODS save_text + IMPORTING is_header TYPE thead + it_lines TYPE tlinetab + RAISING lcx_exception. + +ENDCLASS. "lcl_persistence DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_persistence IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_persistence IMPLEMENTATION. + + METHOD save_text. + + CALL FUNCTION 'SAVE_TEXT' + EXPORTING + header = is_header + TABLES + lines = it_lines + EXCEPTIONS + id = 1 + language = 2 + name = 3 + object = 4 + OTHERS = 5. + IF sy-subrc <> 0. + ROLLBACK WORK. "#EC CI_ROLLBACK + _raise 'error from SAVE_TEXT'. + ENDIF. + + ENDMETHOD. "save_text + + METHOD header_online. + rs_header-tdid = 'ST'. + rs_header-tdspras = gc_english. + rs_header-tdname = 'ZABAPGIT'. + rs_header-tdobject = 'TEXT'. + ENDMETHOD. "header + + METHOD header_offline. + rs_header-tdid = 'ST'. + rs_header-tdspras = gc_english. + rs_header-tdname = 'ZABAPGIT_OFFLINE'. + rs_header-tdobject = 'TEXT'. + ENDMETHOD. "header_offline + + METHOD delete. + + DATA: lt_repos TYPE ty_repos_persi_tt. + + + lt_repos = list( ). + + DELETE lt_repos WHERE url = iv_url AND branch_name = iv_branch_name. + IF sy-subrc <> 0. + _raise 'repo not found, delete'. + ENDIF. + + save_text_online( lt_repos ). + save_text_offline( lt_repos ). + + ENDMETHOD. "delete + + METHOD save_text_online. + + DATA: lt_lines TYPE TABLE OF tline. + + FIELD-SYMBOLS: LIKE LINE OF it_repos, + LIKE LINE OF lt_lines. + + + LOOP AT it_repos ASSIGNING WHERE offline = abap_false. + APPEND INITIAL LINE TO lt_lines ASSIGNING . + -tdformat = '*'. + -tdline = -url. + APPEND INITIAL LINE TO lt_lines ASSIGNING . + -tdformat = '*'. + -tdline = -branch_name. + APPEND INITIAL LINE TO lt_lines ASSIGNING . + -tdformat = '*'. + -tdline = -sha1. + APPEND INITIAL LINE TO lt_lines ASSIGNING . + -tdformat = '*'. + -tdline = -package. + ENDLOOP. + + save_text( is_header = header_online( ) + it_lines = lt_lines ). + + COMMIT WORK. + + ENDMETHOD. "save_text + + METHOD save_text_offline. + + DATA: lt_lines TYPE TABLE OF tline. + + FIELD-SYMBOLS: LIKE LINE OF it_repos, + LIKE LINE OF lt_lines. + + + LOOP AT it_repos ASSIGNING WHERE offline = abap_true. + APPEND INITIAL LINE TO lt_lines ASSIGNING . + -tdformat = '*'. + -tdline = -url. + APPEND INITIAL LINE TO lt_lines ASSIGNING . + -tdformat = '*'. + -tdline = -package. + ENDLOOP. + + save_text( is_header = header_offline( ) + it_lines = lt_lines ). + + COMMIT WORK. + + ENDMETHOD. "save_text_offline + + METHOD add. + + DATA: lt_repos TYPE ty_repos_persi_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_repos. + + + ASSERT NOT iv_url IS INITIAL. + ASSERT NOT iv_package IS INITIAL. + + lt_repos = list( ). + + READ TABLE lt_repos WITH KEY url = iv_url branch_name = iv_branch_name + TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + _raise 'already inserted'. + ENDIF. + + APPEND INITIAL LINE TO lt_repos ASSIGNING . + -url = iv_url. + -branch_name = iv_branch_name. + -sha1 = iv_branch. + -package = iv_package. + -offline = iv_offline. + + save_text_online( lt_repos ). + save_text_offline( lt_repos ). + + ENDMETHOD. "insert + + METHOD update. + + DATA: lt_repos TYPE ty_repos_persi_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_repos. + + + IF iv_branch IS INITIAL. + _raise 'update, sha empty'. + ENDIF. + + lt_repos = list( ). + + READ TABLE lt_repos ASSIGNING + WITH KEY url = iv_url branch_name = iv_branch_name. + IF sy-subrc <> 0. + _raise 'persist update, repo not found'. + ENDIF. + + -sha1 = iv_branch. + + save_text_online( lt_repos ). + + ENDMETHOD. "update + + METHOD list. + CLEAR rt_repos. + APPEND LINES OF read_text_online( ) TO rt_repos. + APPEND LINES OF read_text_offline( ) TO rt_repos. + ENDMETHOD. "list + + METHOD read_text. + + CALL FUNCTION 'READ_TEXT' + EXPORTING + id = is_header-tdid + language = is_header-tdspras + name = is_header-tdname + object = is_header-tdobject + TABLES + lines = rt_lines + EXCEPTIONS + id = 1 + language = 2 + name = 3 + not_found = 4 + object = 5 + reference_check = 6 + wrong_access_to_archive = 7 + OTHERS = 8. + IF sy-subrc = 4. + RETURN. + ELSEIF sy-subrc <> 0. + _raise 'Error from READ_TEXT'. + ENDIF. + + ENDMETHOD. "read_text + + METHOD read_text_online. + + DATA: lt_lines TYPE TABLE OF tline, + lv_step TYPE i, + ls_repo TYPE ty_repo_persi. + + FIELD-SYMBOLS: LIKE LINE OF lt_lines. + + + lt_lines = read_text( header_online( ) ). + IF lines( lt_lines ) = 0. + RETURN. + ENDIF. + + IF lines( lt_lines ) MOD 4 <> 0. +* if this happens, delete text ZABAPGIT in SO10 or edit the text +* manually, so it contains the right information + _raise 'Persistence, text broken'. + ENDIF. + + CLEAR ls_repo. + LOOP AT lt_lines ASSIGNING . + lv_step = lv_step + 1. + CASE lv_step. + WHEN 4. + ls_repo-package = -tdline. + + IF ls_repo-url IS INITIAL OR ls_repo-branch_name IS INITIAL. + _raise 'Persistence, text broken 2'. + ENDIF. + APPEND ls_repo TO rt_repos. + CLEAR ls_repo. + lv_step = 0. + WHEN 3. + ls_repo-sha1 = -tdline. + WHEN 2. + ls_repo-branch_name = -tdline. + WHEN 1. + ls_repo-url = -tdline. + WHEN OTHERS. + ASSERT 1 = 0. + ENDCASE. + ENDLOOP. + + ENDMETHOD. "list + + METHOD read_text_offline. + + DATA: lt_lines TYPE TABLE OF tline, + ls_repo TYPE ty_repo_persi. + + FIELD-SYMBOLS: LIKE LINE OF lt_lines. + + + lt_lines = read_text( header_offline( ) ). + IF lines( lt_lines ) = 0. + RETURN. + ENDIF. + + IF lines( lt_lines ) MOD 2 <> 0. +* if this happens, delete text ZABAPGIT in SO10 or edit the text +* manually, so it contains the right information + _raise 'Persistence, text broken'. + ENDIF. + + CLEAR ls_repo. + LOOP AT lt_lines ASSIGNING . + IF -tdline IS INITIAL. + _raise 'Persistence, text broken'. + ENDIF. + IF ls_repo-url IS INITIAL. + ls_repo-url = -tdline. + CONTINUE. " current loop + ENDIF. + + ls_repo-package = -tdline. + ls_repo-offline = abap_true. + APPEND ls_repo TO rt_repos. + CLEAR ls_repo. + ENDLOOP. + + ENDMETHOD. "list + +ENDCLASS. "lcl_persistence IMPLEMENTATION + +CLASS lcl_persistence_background DEFINITION FINAL. + + PUBLIC SECTION. + + CONSTANTS: BEGIN OF c_method, + nothing TYPE string VALUE 'nothing', + pull TYPE string VALUE 'pull', + push TYPE string VALUE 'push', + END OF c_method. + + TYPES: BEGIN OF ty_xml, + method TYPE string, + username TYPE string, + password TYPE string, + END OF ty_xml. + + TYPES: BEGIN OF ty_background, + key TYPE lcl_persistence_db=>ty_value. + INCLUDE TYPE ty_xml. + TYPES: END OF ty_background. + TYPES: tt_background TYPE STANDARD TABLE OF ty_background WITH DEFAULT KEY. + + METHODS constructor. + + METHODS list + RETURNING VALUE(rt_list) TYPE tt_background + RAISING lcx_exception. + + METHODS modify + IMPORTING is_data TYPE ty_background + RAISING lcx_exception. + + METHODS delete + IMPORTING iv_key TYPE ty_background-key + RAISING lcx_exception. + + PRIVATE SECTION. + CONSTANTS c_type TYPE lcl_persistence_db=>ty_type VALUE 'BACKGROUND'. + + DATA: mo_db TYPE REF TO lcl_persistence_db. + + METHODS from_xml + IMPORTING iv_string TYPE string + RETURNING VALUE(rs_xml) TYPE ty_xml + RAISING lcx_exception. + + METHODS to_xml + IMPORTING is_background TYPE ty_background + RETURNING VALUE(rv_string) TYPE string. + +ENDCLASS. "lcl_persistence_background DEFINITION + +CLASS lcl_persistence_background IMPLEMENTATION. + + METHOD constructor. + mo_db = lcl_app=>db( ). + ENDMETHOD. + + METHOD list. + + DATA: lt_list TYPE lcl_persistence_db=>tt_content, + ls_xml TYPE ty_xml. + + FIELD-SYMBOLS: LIKE LINE OF lt_list, + LIKE LINE OF rt_list. + + + lt_list = mo_db->list_by_type( c_type ). + + LOOP AT lt_list ASSIGNING . + ls_xml = from_xml( -data_str ). + + APPEND INITIAL LINE TO rt_list ASSIGNING . + MOVE-CORRESPONDING ls_xml TO . + -key = -value. + ENDLOOP. + + ENDMETHOD. + + METHOD modify. + mo_db->modify( + iv_type = c_type + iv_value = is_data-key + iv_data = to_xml( is_data ) ). + ENDMETHOD. + + METHOD delete. + TRY. + mo_db->read( iv_type = c_type + iv_value = iv_key ). + CATCH lcx_not_found. + RETURN. + ENDTRY. + + mo_db->delete( iv_type = c_type + iv_value = iv_key ). + ENDMETHOD. + + METHOD from_xml. + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML iv_string + RESULT data = rs_xml ##NO_TEXT. + ENDMETHOD. + + METHOD to_xml. + DATA: ls_xml TYPE ty_xml. + + MOVE-CORRESPONDING is_background TO ls_xml. + + CALL TRANSFORMATION id + SOURCE data = ls_xml + RESULT XML rv_string. + ENDMETHOD. + +ENDCLASS. " lcl_persistence_background IMPLEMENTATION + +*----------------------------------------------------------------------* +* CLASS lcl_persistence_user DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_persistence_user DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. + + PUBLIC SECTION. + + METHODS set_username + IMPORTING iv_username TYPE string + RAISING lcx_exception. + + METHODS get_username + RETURNING VALUE(rv_username) TYPE string + RAISING lcx_exception. + + METHODS set_email + IMPORTING iv_email TYPE string + RAISING lcx_exception. + + METHODS get_email + RETURNING VALUE(rv_email) TYPE string + RAISING lcx_exception. + + METHODS is_hidden + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + RETURNING VALUE(rv_hidden) TYPE abap_bool + RAISING lcx_exception. + + METHODS hide + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + RAISING lcx_exception. + + METHODS unhide + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + RAISING lcx_exception. + + PRIVATE SECTION. + CONSTANTS c_type_user TYPE lcl_persistence_db=>ty_type VALUE 'USER'. + + DATA: mv_user TYPE xubname. + + TYPES: + ty_repo_hidden_tt + TYPE STANDARD TABLE OF lcl_persistence_repo=>ty_repo-key + WITH DEFAULT KEY. + + TYPES: BEGIN OF ty_user, + username TYPE string, + email TYPE string, + repo_hidden TYPE ty_repo_hidden_tt, + END OF ty_user. + + METHODS constructor + IMPORTING iv_user TYPE xubname DEFAULT sy-uname. + + METHODS from_xml + IMPORTING iv_xml TYPE string + RETURNING VALUE(rs_user) TYPE ty_user + RAISING lcx_exception. + + METHODS to_xml + IMPORTING is_user TYPE ty_user + RETURNING VALUE(rv_xml) TYPE string. + + METHODS read + RETURNING VALUE(rs_user) TYPE ty_user + RAISING lcx_exception. + + METHODS update + IMPORTING is_user TYPE ty_user + RAISING lcx_exception. + +ENDCLASS. "lcl_persistence_user DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_user DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_user DEFINITION FINAL FRIENDS lcl_persistence_migrate. + +* this class is obsolete, use LCL_PERSISTENCE_USER instead + + PRIVATE SECTION. + TYPES: BEGIN OF ty_user, + user LIKE sy-uname, + username TYPE string, + email TYPE string, + END OF ty_user. + + TYPES: ty_user_tt TYPE STANDARD TABLE OF ty_user WITH DEFAULT KEY. + + CLASS-METHODS set_username + IMPORTING iv_user TYPE xubname DEFAULT sy-uname + iv_username TYPE string + RAISING lcx_exception. + + CLASS-METHODS get_username + IMPORTING iv_user TYPE xubname DEFAULT sy-uname + RETURNING VALUE(rv_username) TYPE string + RAISING lcx_exception. + + CLASS-METHODS set_email + IMPORTING iv_user TYPE xubname DEFAULT sy-uname + iv_email TYPE string + RAISING lcx_exception. + + CLASS-METHODS get_email + IMPORTING iv_user TYPE xubname DEFAULT sy-uname + RETURNING VALUE(rv_email) TYPE string + RAISING lcx_exception. + + CLASS-METHODS list + RETURNING VALUE(rt_data) TYPE ty_user_tt + RAISING lcx_exception. + + CLASS-METHODS read + IMPORTING iv_name TYPE tdobname + RETURNING VALUE(rv_value) TYPE string + RAISING lcx_exception. + + CLASS-METHODS save + IMPORTING iv_name TYPE tdobname + iv_value TYPE string + RAISING lcx_exception. + +ENDCLASS. "lcl_user DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_user IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_user IMPLEMENTATION. + +* this class is obsolete, use LCL_PERSISTENCE_USER instead + + METHOD read. + + DATA: lt_lines TYPE TABLE OF tline, + ls_line LIKE LINE OF lt_lines. + + + CALL FUNCTION 'READ_TEXT' + EXPORTING + id = 'ST' + language = gc_english + name = iv_name + object = 'TEXT' + TABLES + lines = lt_lines + EXCEPTIONS + id = 1 + language = 2 + name = 3 + not_found = 4 + object = 5 + reference_check = 6 + wrong_access_to_archive = 7 + OTHERS = 8. + IF sy-subrc <> 4 AND sy-subrc <> 0. + _raise 'error from READ_TEXT'. + ENDIF. + + READ TABLE lt_lines INTO ls_line INDEX 1. + IF sy-subrc = 0. + rv_value = ls_line-tdline. + ENDIF. + + ENDMETHOD. "get_details + + METHOD save. + + DATA: ls_header TYPE thead, + lt_lines TYPE TABLE OF tline, + ls_line LIKE LINE OF lt_lines. + + + ls_line-tdformat = '*'. + ls_line-tdline = iv_value. + APPEND ls_line TO lt_lines. + + ls_header-tdid = 'ST'. + ls_header-tdspras = gc_english. + ls_header-tdname = iv_name. + ls_header-tdobject = 'TEXT'. + + CALL FUNCTION 'SAVE_TEXT' + EXPORTING + header = ls_header + TABLES + lines = lt_lines + EXCEPTIONS + id = 1 + language = 2 + name = 3 + object = 4 + OTHERS = 5. + IF sy-subrc <> 0. + ROLLBACK WORK. "#EC CI_ROLLBACK + _raise 'error from SAVE_TEXT'. + ENDIF. + + COMMIT WORK. + + ENDMETHOD. "change + + METHOD set_username. + + DATA: lv_name TYPE tdobname. + + + CONCATENATE 'ZABAPGIT_USERNAME_' iv_user INTO lv_name. + + save( iv_name = lv_name + iv_value = iv_username ). + + ENDMETHOD. "set_username + + METHOD get_username. + + DATA: lv_name TYPE tdobname. + + + CONCATENATE 'ZABAPGIT_USERNAME_' iv_user INTO lv_name. + + rv_username = read( lv_name ). + + ENDMETHOD. "get_username + + METHOD set_email. + + DATA: lv_name TYPE tdobname. + + + CONCATENATE 'ZABAPGIT_EMAIL_' iv_user INTO lv_name. + + save( iv_name = lv_name + iv_value = iv_email ). + + ENDMETHOD. "set_email + + METHOD list. + + DATA: lt_stxh TYPE STANDARD TABLE OF stxh WITH DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF rt_data, + LIKE LINE OF lt_stxh. + + + SELECT * FROM stxh INTO TABLE lt_stxh + WHERE tdobject = 'TEXT' + AND tdname LIKE 'ZABAPGIT_USERNAME_%'. + + LOOP AT lt_stxh ASSIGNING . + APPEND INITIAL LINE TO rt_data ASSIGNING . + + -user = -tdname+18. + -username = get_username( -user ). + -email = get_email( -user ). + ENDLOOP. + + ENDMETHOD. + + METHOD get_email. + + DATA: lv_name TYPE tdobname. + + + CONCATENATE 'ZABAPGIT_EMAIL_' iv_user INTO lv_name. + + rv_email = read( lv_name ). + + ENDMETHOD. "get_email + +ENDCLASS. "lcl_user IMPLEMENTATION + +CLASS lcl_persistence_user IMPLEMENTATION. + + METHOD constructor. + mv_user = iv_user. + ENDMETHOD. + + METHOD from_xml. + + DATA: lv_xml TYPE string. + + lv_xml = iv_xml. + +* fix downward compatibility + REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_USER_--29>' IN lv_xml WITH ''. + REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. + + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML lv_xml + RESULT user = rs_user ##NO_TEXT. + ENDMETHOD. + + METHOD to_xml. + CALL TRANSFORMATION id + SOURCE user = is_user + RESULT XML rv_xml. + ENDMETHOD. + + METHOD read. + + DATA: lv_xml TYPE string. + + TRY. + lv_xml = lcl_app=>db( )->read( + iv_type = c_type_user + iv_value = mv_user ). + CATCH lcx_not_found. + RETURN. + ENDTRY. + + rs_user = from_xml( lv_xml ). + + ENDMETHOD. + + METHOD update. + + DATA: lv_xml TYPE string. + + lv_xml = to_xml( is_user ). + + lcl_app=>db( )->modify( + iv_type = c_type_user + iv_value = mv_user + iv_data = lv_xml ). + + ENDMETHOD. + + METHOD set_username. + + DATA: ls_user TYPE ty_user. + + + ls_user = read( ). + + ls_user-username = iv_username. + + update( ls_user ). + + ENDMETHOD. + + METHOD get_username. + + rv_username = read( )-username. + + ENDMETHOD. + + METHOD is_hidden. + + DATA: lt_hidden TYPE ty_repo_hidden_tt. + + + lt_hidden = read( )-repo_hidden. + READ TABLE lt_hidden FROM iv_key TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + rv_hidden = abap_true. + ELSE. + rv_hidden = abap_false. + ENDIF. + + ENDMETHOD. + + METHOD hide. + + DATA: ls_user TYPE ty_user. + + + ls_user = read( ). + APPEND iv_key TO ls_user-repo_hidden. + update( ls_user ). + + ENDMETHOD. + + METHOD unhide. + + DATA: ls_user TYPE ty_user. + + + ls_user = read( ). + DELETE TABLE ls_user-repo_hidden FROM iv_key. + update( ls_user ). + + ENDMETHOD. + + METHOD set_email. + + DATA: ls_user TYPE ty_user. + + + ls_user = read( ). + ls_user-email = iv_email. + update( ls_user ). + + ENDMETHOD. + + METHOD get_email. + + rv_email = read( )-email. + + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_persistence_db IMPLEMENTATION. + + METHOD list_by_type. + SELECT * FROM (c_tabname) + INTO TABLE rt_content + WHERE type = iv_type. "#EC CI_SUBRC + ENDMETHOD. + + METHOD list. + SELECT * FROM (c_tabname) + INTO TABLE rt_content. "#EC CI_SUBRC + ENDMETHOD. + + METHOD lock. + + CALL FUNCTION 'ENQUEUE_EZABAPGIT' + EXPORTING + mode_zabapgit = iv_mode + type = iv_type + value = iv_value + EXCEPTIONS + foreign_lock = 1 + system_failure = 2 + OTHERS = 3. + IF sy-subrc <> 0. + _raise 'Could not aquire lock'. + ENDIF. + +* trigger dummy update task to automatically release locks at commit + CALL FUNCTION 'BANK_OBJ_WORKL_RELEASE_LOCKS' + IN UPDATE TASK. + + ENDMETHOD. + + METHOD add. + + DATA ls_table TYPE ty_content. + + ls_table-type = iv_type. + ls_table-value = iv_value. + ls_table-data_str = iv_data. + + INSERT (c_tabname) FROM ls_table. "#EC CI_SUBRC + ASSERT sy-subrc = 0. + + ENDMETHOD. + + METHOD delete. + + lock( iv_type = iv_type + iv_value = iv_value ). + + DELETE FROM (c_tabname) + WHERE type = iv_type + AND value = iv_value. + IF sy-subrc <> 0. + _raise 'DB Delete failed'. + ENDIF. + + ENDMETHOD. + + METHOD update. + + lock( iv_type = iv_type + iv_value = iv_value ). + + UPDATE (c_tabname) SET data_str = iv_data + WHERE type = iv_type + AND value = iv_value. + IF sy-subrc <> 0. + _raise 'DB update failed'. + ENDIF. + + ENDMETHOD. + + METHOD modify. + + DATA: ls_content TYPE ty_content. + + lock( iv_type = iv_type + iv_value = iv_value ). + + ls_content-type = iv_type. + ls_content-value = iv_value. + ls_content-data_str = iv_data. + + MODIFY (c_tabname) FROM ls_content. + IF sy-subrc <> 0. + _raise 'DB modify failed'. + ENDIF. + + ENDMETHOD. + + METHOD read. + + SELECT SINGLE data_str FROM (c_tabname) INTO rv_data + WHERE type = iv_type + AND value = iv_value. "#EC CI_SUBRC + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE lcx_not_found. + ENDIF. + + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_persistence_repo IMPLEMENTATION. + + METHOD add. + + DATA: ls_repo TYPE ty_repo, + lv_repo_as_xml TYPE string. + + + ls_repo-url = iv_url. + ls_repo-branch_name = iv_branch_name. + ls_repo-sha1 = iv_branch. + ls_repo-package = iv_package. + ls_repo-offline = iv_offline. + ls_repo-master_language = sy-langu. + + lv_repo_as_xml = to_xml( ls_repo ). + + rv_key = get_next_id( ). + + mo_db->add( iv_type = c_type_repo + iv_value = rv_key + iv_data = lv_repo_as_xml ). + + ENDMETHOD. + + METHOD delete. + + DATA: lo_background TYPE REF TO lcl_persistence_background. + + CREATE OBJECT lo_background. + lo_background->delete( iv_key ). + + mo_db->delete( iv_type = c_type_repo + iv_value = iv_key ). + + ENDMETHOD. + + METHOD update_local_checksums. + + DATA: lt_content TYPE lcl_persistence_db=>tt_content, + ls_content LIKE LINE OF lt_content, + ls_repo TYPE ty_repo. + + + ASSERT NOT iv_key IS INITIAL. + + TRY. + ls_repo = read( iv_key ). + CATCH lcx_not_found. + _raise 'key not found'. + ENDTRY. + + ls_repo-local_checksums = it_checksums. + ls_content-data_str = to_xml( ls_repo ). + + mo_db->update( iv_type = c_type_repo + iv_value = iv_key + iv_data = ls_content-data_str ). + + ENDMETHOD. + + METHOD update_url. + + DATA: lt_content TYPE lcl_persistence_db=>tt_content, + ls_content LIKE LINE OF lt_content, + ls_repo TYPE ty_repo. + + + IF iv_url IS INITIAL. + _raise 'update, url empty'. + ENDIF. + + ASSERT NOT iv_key IS INITIAL. + + TRY. + ls_repo = read( iv_key ). + CATCH lcx_not_found. + _raise 'key not found'. + ENDTRY. + + ls_repo-url = iv_url. + ls_content-data_str = to_xml( ls_repo ). + + mo_db->update( iv_type = c_type_repo + iv_value = iv_key + iv_data = ls_content-data_str ). + + ENDMETHOD. + + METHOD update_branch_name. + + DATA: lt_content TYPE lcl_persistence_db=>tt_content, + ls_content LIKE LINE OF lt_content, + ls_repo TYPE ty_repo. + + + IF iv_branch_name IS INITIAL. + _raise 'update, branch name empty'. + ENDIF. + + ASSERT NOT iv_key IS INITIAL. + + TRY. + ls_repo = read( iv_key ). + CATCH lcx_not_found. + _raise 'key not found'. + ENDTRY. + + ls_repo-branch_name = iv_branch_name. + ls_content-data_str = to_xml( ls_repo ). + + mo_db->update( iv_type = c_type_repo + iv_value = iv_key + iv_data = ls_content-data_str ). + + ENDMETHOD. + + METHOD update_sha1. + + DATA: lt_content TYPE lcl_persistence_db=>tt_content, + ls_content LIKE LINE OF lt_content, + ls_repo TYPE ty_repo. + + + IF iv_branch_sha1 IS INITIAL. + _raise 'update, sha empty'. + ENDIF. + + ASSERT NOT iv_key IS INITIAL. + + TRY. + ls_repo = read( iv_key ). + CATCH lcx_not_found. + _raise 'key not found'. + ENDTRY. + + ls_repo-sha1 = iv_branch_sha1. + ls_content-data_str = to_xml( ls_repo ). + + mo_db->update( iv_type = c_type_repo + iv_value = iv_key + iv_data = ls_content-data_str ). + + ENDMETHOD. + + METHOD read. + + DATA lt_repo TYPE tt_repo. + + lt_repo = list( ). + + READ TABLE lt_repo INTO rs_repo WITH KEY key = iv_key. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE lcx_not_found. + ENDIF. + + ENDMETHOD. + + METHOD get_next_id. + +* todo: Lock the complete persistence in order to prevent concurrent repo-creation +* however the current approach will most likely work in almost all cases + + DATA: lt_content TYPE lcl_persistence_db=>tt_content. + + FIELD-SYMBOLS: LIKE LINE OF lt_content. + + + rv_next_repo_id = 1. + + lt_content = mo_db->list_by_type( c_type_repo ). + LOOP AT lt_content ASSIGNING . + IF -value >= rv_next_repo_id. + rv_next_repo_id = -value + 1. + ENDIF. + ENDLOOP. + + CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT' + EXPORTING + input = rv_next_repo_id + IMPORTING + output = rv_next_repo_id. + + ENDMETHOD. + + METHOD list. + + DATA: lt_content TYPE lcl_persistence_db=>tt_content, + ls_content LIKE LINE OF lt_content, + ls_repo LIKE LINE OF rt_repos. + + + lt_content = mo_db->list_by_type( c_type_repo ). + + LOOP AT lt_content INTO ls_content. + MOVE-CORRESPONDING from_xml( ls_content-data_str ) TO ls_repo. + ls_repo-key = ls_content-value. + INSERT ls_repo INTO TABLE rt_repos. + ENDLOOP. + + ENDMETHOD. + + METHOD from_xml. + + DATA: lv_xml TYPE string. + + lv_xml = iv_repo_xml_string. + +* fix downward compatibility + REPLACE ALL OCCURRENCES OF '<_--28C_TYPE_REPO_--29>' IN lv_xml WITH ''. + REPLACE ALL OCCURRENCES OF '' IN lv_xml WITH ''. + + CALL TRANSFORMATION id + OPTIONS value_handling = 'accept_data_loss' + SOURCE XML lv_xml + RESULT repo = rs_repo ##NO_TEXT. + + IF rs_repo IS INITIAL. + _raise 'Inconsistent repo metadata'. + ENDIF. + +* field master_language is new, so default it for old repositories + IF rs_repo-master_language IS INITIAL. + rs_repo-master_language = sy-langu. + ENDIF. + ENDMETHOD. + + METHOD to_xml. + + DATA: ls_xml TYPE ty_repo_xml. + + + MOVE-CORRESPONDING is_repo TO ls_xml. + + CALL TRANSFORMATION id + SOURCE repo = ls_xml + RESULT XML rv_repo_xml_string. + ENDMETHOD. + + METHOD constructor. + mo_db = lcl_app=>db( ). + ENDMETHOD. + + METHOD lock. + + mo_db->lock( iv_mode = iv_mode + iv_type = c_type_repo + iv_value = iv_key ). + + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_persistence_migrate IMPLEMENTATION. + + METHOD run. + + IF table_exists( ) = abap_false. + table_create( ). + ENDIF. + + IF lock_exists( ) = abap_false. + lock_create( ). + + migrate_repo( ). + migrate_user( ). + ENDIF. + + ENDMETHOD. + + METHOD migrate_repo. + + DATA: lt_repo TYPE lcl_persistence=>ty_repos_persi_tt, + lo_repo TYPE REF TO lcl_persistence, + lo_new TYPE REF TO lcl_persistence_repo, + ls_repo LIKE LINE OF lt_repo. + + + CREATE OBJECT lo_repo. + CREATE OBJECT lo_new. + + lt_repo = lo_repo->list( ). + + LOOP AT lt_repo INTO ls_repo. + lo_new->add( iv_url = ls_repo-url + iv_branch_name = ls_repo-branch_name + iv_branch = ls_repo-sha1 + iv_package = ls_repo-package + iv_offline = ls_repo-offline ). + ENDLOOP. + ENDMETHOD. + + METHOD migrate_user. + + DATA: lo_user TYPE REF TO lcl_persistence_user, + lt_users TYPE lcl_user=>ty_user_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_users. + + + lt_users = lcl_user=>list( ). + LOOP AT lt_users ASSIGNING . + lo_user = lcl_app=>user( -user ). + lo_user->set_username( -username ). + lo_user->set_email( -email ). + ENDLOOP. + + ENDMETHOD. + + METHOD lock_exists. + + DATA: lv_viewname TYPE dd25l-viewname. + + + SELECT SINGLE viewname FROM dd25l INTO lv_viewname + WHERE viewname = lcl_persistence_db=>c_lock. + rv_exists = boolc( sy-subrc = 0 ). + + ENDMETHOD. + + METHOD lock_create. + + DATA: lv_obj_name TYPE tadir-obj_name, + ls_dd25v TYPE dd25v, + lt_dd26e TYPE STANDARD TABLE OF dd26e WITH DEFAULT KEY, + lt_dd27p TYPE STANDARD TABLE OF dd27p WITH DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF lt_dd26e, + LIKE LINE OF lt_dd27p. + + + ls_dd25v-viewname = lcl_persistence_db=>c_lock. + ls_dd25v-aggtype = 'E'. + ls_dd25v-roottab = lcl_persistence_db=>c_tabname. + ls_dd25v-ddlanguage = gc_english. + ls_dd25v-ddtext = c_text. + + APPEND INITIAL LINE TO lt_dd26e ASSIGNING . + -viewname = lcl_persistence_db=>c_lock. + -tabname = lcl_persistence_db=>c_tabname. + -tabpos = '0001'. + -fortabname = lcl_persistence_db=>c_tabname. + -enqmode = 'E'. + + APPEND INITIAL LINE TO lt_dd27p ASSIGNING . + -viewname = lcl_persistence_db=>c_lock. + -objpos = '0001'. + -viewfield = 'TYPE'. + -tabname = lcl_persistence_db=>c_tabname. + -fieldname = 'TYPE'. + -keyflag = abap_true. + + APPEND INITIAL LINE TO lt_dd27p ASSIGNING . + -viewname = lcl_persistence_db=>c_lock. + -objpos = '0002'. + -viewfield = 'VALUE'. + -tabname = lcl_persistence_db=>c_tabname. + -fieldname = 'VALUE'. + -keyflag = abap_true. + + CALL FUNCTION 'DDIF_ENQU_PUT' + EXPORTING + name = lcl_persistence_db=>c_lock + dd25v_wa = ls_dd25v + TABLES + dd26e_tab = lt_dd26e + dd27p_tab = lt_dd27p + EXCEPTIONS + enqu_not_found = 1 + name_inconsistent = 2 + enqu_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + _raise 'migrate, error from DDIF_ENQU_PUT'. + ENDIF. + + lv_obj_name = lcl_persistence_db=>c_lock. + CALL FUNCTION 'TR_TADIR_INTERFACE' + EXPORTING + wi_tadir_pgmid = 'R3TR' + wi_tadir_object = 'ENQU' + wi_tadir_obj_name = lv_obj_name + wi_set_genflag = abap_true + wi_test_modus = abap_false + wi_tadir_devclass = '$TMP' + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. + _raise 'migrate, error from TR_TADIR_INTERFACE'. + ENDIF. + + CALL FUNCTION 'DDIF_ENQU_ACTIVATE' + EXPORTING + name = lcl_persistence_db=>c_lock + EXCEPTIONS + not_found = 1 + put_failure = 2 + OTHERS = 3. + IF sy-subrc <> 0. + _raise 'migrate, error from DDIF_ENQU_ACTIVATE'. + ENDIF. + + ENDMETHOD. + + METHOD table_exists. + + DATA: lv_tabname TYPE dd02l-tabname. + + SELECT SINGLE tabname FROM dd02l INTO lv_tabname + WHERE tabname = lcl_persistence_db=>c_tabname. + rv_exists = boolc( sy-subrc = 0 ). + + ENDMETHOD. + + METHOD table_create. + + DATA: lv_obj_name TYPE tadir-obj_name, + ls_dd02v TYPE dd02v, + ls_dd09l TYPE dd09l, + lt_dd03p TYPE STANDARD TABLE OF dd03p WITH DEFAULT KEY. + + FIELD-SYMBOLS: LIKE LINE OF lt_dd03p. + + ls_dd02v-tabname = lcl_persistence_db=>c_tabname. + ls_dd02v-ddlanguage = gc_english. + ls_dd02v-tabclass = 'TRANSP'. + ls_dd02v-ddtext = c_text. + ls_dd02v-contflag = 'A'. + ls_dd02v-exclass = '1'. + + ls_dd09l-tabname = lcl_persistence_db=>c_tabname. + ls_dd09l-as4local = 'A'. + ls_dd09l-tabkat = '1'. + ls_dd09l-tabart = 'APPL1'. + ls_dd09l-bufallow = 'N'. + + APPEND INITIAL LINE TO lt_dd03p ASSIGNING . + -tabname = lcl_persistence_db=>c_tabname. + -fieldname = 'TYPE'. + -position = '0001'. + -keyflag = 'X'. + -datatype = 'CHAR'. + -leng = '000012'. + + APPEND INITIAL LINE TO lt_dd03p ASSIGNING . + -tabname = lcl_persistence_db=>c_tabname. + -fieldname = 'VALUE'. + -position = '0002'. + -keyflag = 'X'. + -datatype = 'CHAR'. + -leng = '000012'. + + APPEND INITIAL LINE TO lt_dd03p ASSIGNING . + -tabname = lcl_persistence_db=>c_tabname. + -fieldname = 'DATA_STR'. + -position = '0003'. + -datatype = 'STRG'. + + CALL FUNCTION 'DDIF_TABL_PUT' + EXPORTING + name = lcl_persistence_db=>c_tabname + dd02v_wa = ls_dd02v + dd09l_wa = ls_dd09l + TABLES + dd03p_tab = lt_dd03p + EXCEPTIONS + tabl_not_found = 1 + name_inconsistent = 2 + tabl_inconsistent = 3 + put_failure = 4 + put_refused = 5 + OTHERS = 6. + IF sy-subrc <> 0. + _raise 'migrate, error from DDIF_TABL_PUT'. + ENDIF. + + lv_obj_name = lcl_persistence_db=>c_tabname. + CALL FUNCTION 'TR_TADIR_INTERFACE' + EXPORTING + wi_tadir_pgmid = 'R3TR' + wi_tadir_object = 'TABL' + wi_tadir_obj_name = lv_obj_name + wi_set_genflag = abap_true + wi_test_modus = abap_false + wi_tadir_devclass = '$TMP' + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. + _raise 'migrate, error from TR_TADIR_INTERFACE'. + ENDIF. + + CALL FUNCTION 'DDIF_TABL_ACTIVATE' + EXPORTING + name = lcl_persistence_db=>c_tabname + EXCEPTIONS + not_found = 1 + put_failure = 2 + OTHERS = 3. + IF sy-subrc <> 0. + _raise 'migrate, error from DDIF_TABL_ACTIVATE'. + ENDIF. + + ENDMETHOD. + +ENDCLASS. \ No newline at end of file diff --git a/src/zabapgit_persistence.prog.xml b/src/zabapgit_persistence.prog.xml new file mode 100644 index 000000000..49f6b180a --- /dev/null +++ b/src/zabapgit_persistence.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_PERSISTENCE + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_PERSISTENCE + 28 + + + + + + diff --git a/src/zabapgit_repo.prog.abap b/src/zabapgit_repo.prog.abap new file mode 100644 index 000000000..d56254f5b --- /dev/null +++ b/src/zabapgit_repo.prog.abap @@ -0,0 +1,213 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_REPO +*&---------------------------------------------------------------------* + +*----------------------------------------------------------------------* +* CLASS lcl_repo DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_repo DEFINITION ABSTRACT. + + PUBLIC SECTION. + METHODS: + constructor + IMPORTING is_data TYPE lcl_persistence_repo=>ty_repo, + get_key + RETURNING VALUE(rv_key) TYPE lcl_persistence_db=>ty_value, + get_name + RETURNING VALUE(rv_name) TYPE string + RAISING lcx_exception, + get_files_local + IMPORTING io_log TYPE REF TO lcl_log OPTIONAL + RETURNING VALUE(rt_files) TYPE ty_files_item_tt + RAISING lcx_exception, + get_local_checksums + RETURNING VALUE(rt_checksums) TYPE lcl_persistence_repo=>ty_local_checksum_tt, + get_files_remote + RETURNING VALUE(rt_files) TYPE ty_files_tt + RAISING lcx_exception, + get_package + RETURNING VALUE(rv_package) TYPE lcl_persistence_repo=>ty_repo-package, + get_master_language + RETURNING VALUE(rv_language) TYPE spras, + delete + RAISING lcx_exception, + get_dot_abapgit + RETURNING VALUE(ro_dot_abapgit) TYPE REF TO lcl_dot_abapgit, + deserialize + RAISING lcx_exception, + refresh + RAISING lcx_exception, + build_local_checksums + RETURNING VALUE(rt_checksums) TYPE lcl_persistence_repo=>ty_local_checksum_tt + RAISING lcx_exception, + is_offline + RETURNING VALUE(rv_offline) TYPE abap_bool + RAISING lcx_exception. + + PROTECTED SECTION. + + DATA: mt_local TYPE ty_files_item_tt, + mt_remote TYPE ty_files_tt, + mo_dot_abapgit TYPE REF TO lcl_dot_abapgit, + ms_data TYPE lcl_persistence_repo=>ty_repo. + + METHODS: + find_dot_abapgit + RAISING lcx_exception, + set + IMPORTING iv_sha1 TYPE ty_sha1 OPTIONAL + it_checksums TYPE lcl_persistence_repo=>ty_local_checksum_tt OPTIONAL + iv_url TYPE lcl_persistence_repo=>ty_repo-url OPTIONAL + iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name OPTIONAL + RAISING lcx_exception. + +ENDCLASS. "lcl_repo DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_repo_online DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_repo_online DEFINITION INHERITING FROM lcl_repo FINAL. + + PUBLIC SECTION. + METHODS: + refresh REDEFINITION, + constructor + IMPORTING is_data TYPE lcl_persistence_repo=>ty_repo + RAISING lcx_exception, + get_url + RETURNING VALUE(rv_url) TYPE lcl_persistence_repo=>ty_repo-url, + get_branch_name + RETURNING VALUE(rv_name) TYPE lcl_persistence_repo=>ty_repo-branch_name, + set_url + IMPORTING iv_url TYPE lcl_persistence_repo=>ty_repo-url + RAISING lcx_exception, + set_branch_name + IMPORTING iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name + RAISING lcx_exception, + get_sha1_local + RETURNING VALUE(rv_sha1) TYPE lcl_persistence_repo=>ty_repo-sha1, + get_sha1_remote + RETURNING VALUE(rv_sha1) TYPE lcl_persistence_repo=>ty_repo-sha1 + RAISING lcx_exception, + get_files_remote REDEFINITION, + get_objects + RETURNING VALUE(rt_objects) TYPE ty_objects_tt + RAISING lcx_exception, + deserialize REDEFINITION, + status + IMPORTING io_log TYPE REF TO lcl_log OPTIONAL + RETURNING VALUE(rt_results) TYPE ty_results_tt + RAISING lcx_exception, + push + IMPORTING is_comment TYPE ty_comment + io_stage TYPE REF TO lcl_stage + RAISING lcx_exception. + + PRIVATE SECTION. + DATA: + mt_objects TYPE ty_objects_tt, + mv_branch TYPE ty_sha1, + mv_initialized TYPE abap_bool. + + METHODS: + handle_stage_ignore + IMPORTING io_stage TYPE REF TO lcl_stage + RAISING lcx_exception, + initialize + RAISING lcx_exception. + +ENDCLASS. "lcl_repo_online DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_repo_offline DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_repo_offline DEFINITION INHERITING FROM lcl_repo FINAL. + + PUBLIC SECTION. + METHODS: + set_files_remote + IMPORTING it_files TYPE ty_files_tt + RAISING lcx_exception. + +ENDCLASS. "lcl_repo_offline DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_repo_srv DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_repo_srv DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. + + PUBLIC SECTION. + + TYPES: ty_repo_tt TYPE STANDARD TABLE OF REF TO lcl_repo WITH DEFAULT KEY. + + METHODS list + RETURNING VALUE(rt_list) TYPE ty_repo_tt + RAISING lcx_exception. + + METHODS refresh + RAISING lcx_exception. + + METHODS new_online + IMPORTING iv_url TYPE string + iv_branch_name TYPE string + iv_package TYPE devclass + RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo_online + RAISING lcx_exception. + + METHODS new_offline + IMPORTING iv_url TYPE string + iv_package TYPE devclass + RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo_offline + RAISING lcx_exception. + + METHODS delete + IMPORTING io_repo TYPE REF TO lcl_repo + RAISING lcx_exception. + + METHODS get + IMPORTING iv_key TYPE lcl_persistence_db=>ty_value + RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo + RAISING lcx_exception. + + METHODS is_repo_installed + IMPORTING iv_url TYPE string + iv_target_package TYPE devclass OPTIONAL + RETURNING VALUE(rv_installed) TYPE abap_bool + RAISING lcx_exception. + + METHODS get_stage + IMPORTING iv_repo_key TYPE lcl_persistence_db=>ty_value + iv_new TYPE abap_bool DEFAULT abap_false + RETURNING VALUE(ro_stage) TYPE REF TO lcl_stage + RAISING lcx_exception. + + METHODS free_stage + IMPORTING iv_repo_key TYPE lcl_persistence_db=>ty_value. + + PRIVATE SECTION. + + TYPES: BEGIN OF ty_stage_list, + repo_key TYPE lcl_persistence_db=>ty_value, + stage TYPE REF TO lcl_stage, + END OF ty_stage_list. + + METHODS constructor. + + DATA: mv_init TYPE abap_bool VALUE abap_false, + mo_persistence TYPE REF TO lcl_persistence_repo, + mt_stages TYPE TABLE OF ty_stage_list, + mt_list TYPE ty_repo_tt. + + METHODS add + IMPORTING io_repo TYPE REF TO lcl_repo + RAISING lcx_exception. + + METHODS validate_package + IMPORTING iv_package TYPE devclass + RAISING lcx_exception. + +ENDCLASS. "lcl_repo_srv DEFINITION \ No newline at end of file diff --git a/src/zabapgit_repo.prog.xml b/src/zabapgit_repo.prog.xml new file mode 100644 index 000000000..ee25763d5 --- /dev/null +++ b/src/zabapgit_repo.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_REPO + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_REPO + 21 + + + + + + diff --git a/src/zabapgit_stage.prog.abap b/src/zabapgit_stage.prog.abap new file mode 100644 index 000000000..6e35e40f5 --- /dev/null +++ b/src/zabapgit_stage.prog.abap @@ -0,0 +1,96 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_STAGE +*&---------------------------------------------------------------------* + +CLASS lcl_stage_logic DEFINITION FINAL. + + PUBLIC SECTION. + TYPES: BEGIN OF ty_stage_files, + local TYPE ty_files_item_tt, + remote TYPE ty_files_tt, + END OF ty_stage_files. + + CLASS-METHODS: + get + IMPORTING io_repo TYPE REF TO lcl_repo_online + RETURNING VALUE(rs_files) TYPE ty_stage_files + RAISING lcx_exception, + count + IMPORTING io_repo TYPE REF TO lcl_repo_online + RETURNING VALUE(rv_count) TYPE i + RAISING lcx_exception. + + PRIVATE SECTION. + CLASS-METHODS: + remove_ignored + IMPORTING io_repo TYPE REF TO lcl_repo_online + CHANGING cs_files TYPE ty_stage_files, + remove_identical + CHANGING cs_files TYPE ty_stage_files. + +ENDCLASS. + +CLASS lcl_stage_logic IMPLEMENTATION. + + METHOD get. + rs_files-local = io_repo->get_files_local( ). + rs_files-remote = io_repo->get_files_remote( ). + remove_identical( CHANGING cs_files = rs_files ). + remove_ignored( EXPORTING io_repo = io_repo + CHANGING cs_files = rs_files ). + ENDMETHOD. + + METHOD count. + + DATA: ls_files TYPE ty_stage_files. + + ls_files = get( io_repo ). + + rv_count = lines( ls_files-remote ) + lines( ls_files-local ). + + ENDMETHOD. + + METHOD remove_ignored. + + DATA: lv_index TYPE i. + + FIELD-SYMBOLS: LIKE LINE OF cs_files-remote. + + + LOOP AT cs_files-remote ASSIGNING . + lv_index = sy-tabix. + + IF io_repo->get_dot_abapgit( )->is_ignored( + iv_path = -path + iv_filename = -filename ) = abap_true. + DELETE cs_files-remote INDEX lv_index. + ENDIF. + ENDLOOP. + + ENDMETHOD. + + METHOD remove_identical. + + DATA: lv_index TYPE i, + ls_remote LIKE LINE OF cs_files-remote. + + FIELD-SYMBOLS: LIKE LINE OF cs_files-local. + + + LOOP AT cs_files-local ASSIGNING . + lv_index = sy-tabix. + + READ TABLE cs_files-remote INTO ls_remote + WITH KEY path = -file-path + filename = -file-filename. + IF sy-subrc = 0. + DELETE cs_files-remote INDEX sy-tabix. + IF ls_remote-data = -file-data. + DELETE cs_files-local INDEX lv_index. + ENDIF. + ENDIF. + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. \ No newline at end of file diff --git a/src/zabapgit_stage.prog.xml b/src/zabapgit_stage.prog.xml new file mode 100644 index 000000000..7dc0d55d1 --- /dev/null +++ b/src/zabapgit_stage.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_STAGE + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_STAGE + 22 + + + + + + diff --git a/src/zabapgit_unit_test.prog.abap b/src/zabapgit_unit_test.prog.abap index 722c441ba..5df6ad9cf 100644 --- a/src/zabapgit_unit_test.prog.abap +++ b/src/zabapgit_unit_test.prog.abap @@ -118,7 +118,7 @@ CLASS ltcl_dangerous IMPLEMENTATION. DATA: lo_repo TYPE REF TO lcl_repo_online, lt_tadir TYPE lcl_tadir=>ty_tadir_tt, lv_msg TYPE string, - lt_results TYPE lcl_file_status=>ty_results_tt, + lt_results TYPE ty_results_tt, lt_types TYPE lcl_objects=>ty_types_tt. FIELD-SYMBOLS: LIKE LINE OF lt_results, @@ -788,7 +788,7 @@ CLASS ltcl_git_pack DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FI METHODS: object_blob IMPORTING iv_data TYPE xstring - RETURNING VALUE(rs_object) TYPE lcl_git_pack=>ty_object + RETURNING VALUE(rs_object) TYPE ty_object RAISING lcx_exception. ENDCLASS. "test DEFINITION @@ -861,12 +861,12 @@ CLASS ltcl_git_pack IMPLEMENTATION. CONSTANTS: lc_data TYPE x LENGTH 15 VALUE '123456789ABCDEF545794254754554', lc_sha TYPE ty_sha1 VALUE '5f46cb3c4b7f0b3600b64f744cde614a283a88dc'. - DATA: lt_objects TYPE lcl_git_pack=>ty_objects_tt, + DATA: lt_objects TYPE ty_objects_tt, ls_object LIKE LINE OF lt_objects, lt_nodes TYPE lcl_git_pack=>ty_nodes_tt, ls_node LIKE LINE OF lt_nodes, ls_commit TYPE lcl_git_pack=>ty_commit, - lt_result TYPE lcl_git_pack=>ty_objects_tt, + lt_result TYPE ty_objects_tt, lv_data TYPE xstring. @@ -929,9 +929,9 @@ CLASS ltcl_git_pack IMPLEMENTATION. CONSTANTS: lc_data TYPE x LENGTH 8 VALUE '0123456789ABCDEF'. - DATA: lt_objects TYPE lcl_git_pack=>ty_objects_tt, + DATA: lt_objects TYPE ty_objects_tt, ls_object LIKE LINE OF lt_objects, - lt_result TYPE lcl_git_pack=>ty_objects_tt, + lt_result TYPE ty_objects_tt, lv_data TYPE xstring. @@ -954,10 +954,10 @@ CLASS ltcl_git_pack IMPLEMENTATION. CONSTANTS: lc_data TYPE x LENGTH 8 VALUE '0123456789ABCDEF'. - DATA: lt_objects TYPE lcl_git_pack=>ty_objects_tt, + DATA: lt_objects TYPE ty_objects_tt, ls_object LIKE LINE OF lt_objects, lv_xstring TYPE xstring, - lt_result TYPE lcl_git_pack=>ty_objects_tt, + lt_result TYPE ty_objects_tt, lv_data TYPE xstring. diff --git a/src/zabapgit_util.prog.abap b/src/zabapgit_util.prog.abap index 1f225c569..7bb739479 100644 --- a/src/zabapgit_util.prog.abap +++ b/src/zabapgit_util.prog.abap @@ -851,4 +851,111 @@ CLASS lcl_login_manager IMPLEMENTATION. ENDMETHOD. +ENDCLASS. + +CLASS lcl_progress DEFINITION FINAL. + + PUBLIC SECTION. + CLASS-METHODS: + show + IMPORTING + iv_key TYPE string + VALUE(iv_current) TYPE i + iv_total TYPE i + iv_text TYPE csequence. + + PRIVATE SECTION. + TYPES: BEGIN OF ty_stack, + key TYPE string, + current TYPE i, + total TYPE i, + text TYPE string, + END OF ty_stack. + + CLASS-DATA: + gt_stack TYPE STANDARD TABLE OF ty_stack WITH DEFAULT KEY. + + CLASS-METHODS: + calc_pct + RETURNING VALUE(rv_pct) TYPE i, + build_text + RETURNING VALUE(rv_text) TYPE string. + +ENDCLASS. + +CLASS lcl_progress IMPLEMENTATION. + + METHOD show. + + DATA: lv_pct TYPE i, + lv_text TYPE string. + + FIELD-SYMBOLS: LIKE LINE OF gt_stack. + +* assumption: +* all callers must end with calling this method with iv_current = iv_total +* to clear the progress of that sub element + ASSERT lines( gt_stack ) < 10. + + READ TABLE gt_stack INDEX lines( gt_stack ) ASSIGNING . + IF sy-subrc <> 0 OR -key <> iv_key. + APPEND INITIAL LINE TO gt_stack ASSIGNING . + ENDIF. + -key = iv_key. + -current = iv_current. + -total = iv_total. + -text = iv_text. + + lv_pct = calc_pct( ). + lv_text = build_text( ). + + CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR' + EXPORTING + percentage = lv_pct + text = lv_text. + + IF iv_current = iv_total. + DELETE gt_stack INDEX lines( gt_stack ). + ENDIF. + + ENDMETHOD. + + METHOD build_text. + + FIELD-SYMBOLS: LIKE LINE OF gt_stack. + + + LOOP AT gt_stack ASSIGNING . + IF sy-tabix = 1. + rv_text = |{ -key } { -text }|. + ELSE. + rv_text = |{ rv_text } - { -key } { -text }|. + + IF -current <> 1 AND -total <> 1. + rv_text = |{ rv_text } ({ -current }/{ -total })|. + ENDIF. + ENDIF. + ENDLOOP. + + ENDMETHOD. + + METHOD calc_pct. + + DATA: lv_f TYPE f. + + FIELD-SYMBOLS: LIKE LINE OF gt_stack. + + + READ TABLE gt_stack ASSIGNING INDEX 1. + ASSERT sy-subrc = 0. + + lv_f = ( -current / -total ) * 100. + rv_pct = lv_f. + + IF rv_pct = 100. + rv_pct = 99. + ENDIF. + + ENDMETHOD. + ENDCLASS. \ No newline at end of file