abapGit/src/zabapgit_zip.prog.abap
2016-07-02 12:43:40 +00:00

488 lines
14 KiB
ABAP

*&---------------------------------------------------------------------*
*& Include ZABAPGIT_ZIP
*&---------------------------------------------------------------------*
*----------------------------------------------------------------------*
* CLASS lcl_zip DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_zip DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS import
IMPORTING iv_key TYPE lcl_persistence_db=>ty_value
RAISING lcx_exception.
CLASS-METHODS export
IMPORTING io_repo TYPE REF TO lcl_repo
iv_zip TYPE abap_bool DEFAULT abap_true
RAISING lcx_exception.
PRIVATE SECTION.
CLASS-METHODS file_upload
RETURNING VALUE(rv_xstr) TYPE xstring
RAISING lcx_exception.
CLASS-METHODS unzip_file
IMPORTING iv_xstr TYPE xstring
RETURNING VALUE(rt_files) TYPE ty_files_tt
RAISING lcx_exception.
CLASS-METHODS filename
IMPORTING iv_str TYPE string
RETURNING VALUE(rv_filename) TYPE string
RAISING lcx_exception.
CLASS-METHODS file_download
IMPORTING iv_package TYPE devclass
iv_xstr TYPE xstring
RAISING lcx_exception.
CLASS-METHODS files_commit
IMPORTING it_files TYPE ty_files_item_tt
RAISING lcx_exception.
CLASS-METHODS encode_files
IMPORTING it_files TYPE ty_files_item_tt
RETURNING VALUE(rv_xstr) TYPE xstring
RAISING lcx_exception.
CLASS-METHODS get_message
RETURNING VALUE(rv_message) TYPE string
RAISING lcx_exception.
ENDCLASS. "lcl_zip DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_zip IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_zip IMPLEMENTATION.
METHOD get_message.
DATA: lv_returncode TYPE c,
lt_fields TYPE TABLE OF sval.
FIELD-SYMBOLS: <ls_field> LIKE LINE OF lt_fields.
APPEND INITIAL LINE TO lt_fields ASSIGNING <ls_field>.
<ls_field>-tabname = 'ABAPTXT255'.
<ls_field>-fieldname = 'LINE'.
<ls_field>-fieldtext = 'Commit message'. "#EC NOTEXT
<ls_field>-field_obl = abap_true.
CALL FUNCTION 'POPUP_GET_VALUES'
EXPORTING
no_value_check = abap_true
popup_title = 'Enter commit message' "#EC NOTEXT
IMPORTING
returncode = lv_returncode
TABLES
fields = lt_fields
EXCEPTIONS
error_in_fields = 1
OTHERS = 2.
IF sy-subrc <> 0.
_raise 'Error from POPUP_GET_VALUES'.
ENDIF.
IF lv_returncode = 'A'.
_raise 'cancelled'.
ENDIF.
READ TABLE lt_fields INDEX 1 ASSIGNING <ls_field>.
ASSERT sy-subrc = 0.
rv_message = <ls_field>-value.
ENDMETHOD. "get_message
METHOD file_download.
DATA: lt_rawdata TYPE solix_tab,
lv_action TYPE i,
lv_filename TYPE string,
lv_default TYPE string,
lv_path TYPE string,
lv_fullpath TYPE string.
CONCATENATE iv_package '_' sy-datlo '_' sy-timlo INTO lv_default.
cl_gui_frontend_services=>file_save_dialog(
EXPORTING
window_title = 'Export ZIP'
default_extension = 'zip'
default_file_name = lv_default
CHANGING
filename = lv_filename
path = lv_path
fullpath = lv_fullpath
user_action = lv_action
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
not_supported_by_gui = 3
OTHERS = 4 ). "#EC NOTEXT
IF sy-subrc <> 0.
_raise 'error from file_save_dialog'.
ENDIF.
IF lv_action = cl_gui_frontend_services=>action_cancel.
_raise 'cancelled'.
ENDIF.
lt_rawdata = cl_bcs_convert=>xstring_to_solix( iv_xstr ).
cl_gui_frontend_services=>gui_download(
EXPORTING
bin_filesize = xstrlen( iv_xstr )
filename = lv_fullpath
filetype = 'BIN'
CHANGING
data_tab = lt_rawdata
EXCEPTIONS
file_write_error = 1
no_batch = 2
gui_refuse_filetransfer = 3
invalid_type = 4
no_authority = 5
unknown_error = 6
header_not_allowed = 7
separator_not_allowed = 8
filesize_not_allowed = 9
header_too_long = 10
dp_error_create = 11
dp_error_send = 12
dp_error_write = 13
unknown_dp_error = 14
access_denied = 15
dp_out_of_memory = 16
disk_full = 17
dp_timeout = 18
file_not_found = 19
dataprovider_exception = 20
control_flush_error = 21
not_supported_by_gui = 22
error_no_gui = 23
OTHERS = 24 ).
IF sy-subrc <> 0.
_raise 'error from gui_download'.
ENDIF.
ENDMETHOD. "file_download
METHOD encode_files.
DATA: lo_zip TYPE REF TO cl_abap_zip,
lv_filename TYPE string.
FIELD-SYMBOLS: <ls_file> LIKE LINE OF it_files.
CREATE OBJECT lo_zip.
LOOP AT it_files ASSIGNING <ls_file>.
CONCATENATE <ls_file>-file-path+1 <ls_file>-file-filename INTO lv_filename.
lo_zip->add( name = lv_filename
content = <ls_file>-file-data ).
ENDLOOP.
rv_xstr = lo_zip->save( ).
ENDMETHOD. "encode_files
METHOD filename.
DATA: lv_path TYPE string. "#EC NEEDED
IF iv_str CA '/'.
FIND REGEX '(.*/)(.*)' IN iv_str
SUBMATCHES lv_path rv_filename.
IF sy-subrc <> 0.
_raise 'Malformed path'.
ENDIF.
ELSE.
rv_filename = iv_str.
ENDIF.
TRANSLATE rv_filename TO LOWER CASE.
ENDMETHOD. "filename
METHOD file_upload.
DATA: lt_data TYPE TABLE OF x255,
lt_file_table TYPE filetable,
ls_file_table LIKE LINE OF lt_file_table,
lv_action TYPE i,
lv_string TYPE string,
lv_rc TYPE i,
lv_length TYPE i.
cl_gui_frontend_services=>file_open_dialog(
EXPORTING
window_title = 'Import ZIP'
default_extension = 'ZIP'
CHANGING
file_table = lt_file_table
rc = lv_rc
user_action = lv_action
EXCEPTIONS
file_open_dialog_failed = 1
cntl_error = 2
error_no_gui = 3
not_supported_by_gui = 4
OTHERS = 5 ). "#EC NOTEXT
IF sy-subrc <> 0.
_raise 'error from file_open_dialog'.
ENDIF.
IF lv_action = cl_gui_frontend_services=>action_cancel.
_raise 'cancelled'.
ENDIF.
READ TABLE lt_file_table INDEX 1 INTO ls_file_table.
ASSERT sy-subrc = 0.
lv_string = ls_file_table-filename.
cl_gui_frontend_services=>gui_upload(
EXPORTING
filename = lv_string
filetype = 'BIN'
IMPORTING
filelength = lv_length
CHANGING
data_tab = lt_data
EXCEPTIONS
file_open_error = 1
file_read_error = 2
no_batch = 3
gui_refuse_filetransfer = 4
invalid_type = 5
no_authority = 6
unknown_error = 7
bad_data_format = 8
header_not_allowed = 9
separator_not_allowed = 10
header_too_long = 11
unknown_dp_error = 12
access_denied = 13
dp_out_of_memory = 14
disk_full = 15
dp_timeout = 16
not_supported_by_gui = 17
error_no_gui = 18
OTHERS = 19 ).
IF sy-subrc <> 0.
_raise 'error from gui_upload'.
ENDIF.
CONCATENATE LINES OF lt_data INTO rv_xstr IN BYTE MODE.
rv_xstr = rv_xstr(lv_length).
ENDMETHOD. "file_upload
METHOD unzip_file.
DATA: lo_zip TYPE REF TO cl_abap_zip,
lv_xstr TYPE xstring,
lt_splice TYPE cl_abap_zip=>t_splice_entries.
FIELD-SYMBOLS: <ls_splice> LIKE LINE OF lt_splice,
<ls_file> LIKE LINE OF rt_files.
CREATE OBJECT lo_zip.
lo_zip->load( EXPORTING
zip = iv_xstr
EXCEPTIONS
zip_parse_error = 1
OTHERS = 2 ).
IF sy-subrc <> 0.
_raise 'error from zip'.
ENDIF.
lt_splice = cl_abap_zip=>splice( iv_xstr ).
LOOP AT lt_splice ASSIGNING <ls_splice>.
lo_zip->get(
EXPORTING
name = <ls_splice>-name
IMPORTING
content = lv_xstr
EXCEPTIONS
zip_index_error = 1
zip_decompression_error = 2
OTHERS = 3 ).
IF sy-subrc <> 0.
_raise 'error from zip get'.
ENDIF.
APPEND INITIAL LINE TO rt_files ASSIGNING <ls_file>.
<ls_file>-path = '/'.
<ls_file>-filename = filename( <ls_splice>-name ).
<ls_file>-data = lv_xstr.
ENDLOOP.
ENDMETHOD. "decode_files
METHOD export.
DATA: lo_log TYPE REF TO lcl_log,
lt_zip TYPE ty_files_item_tt.
CREATE OBJECT lo_log.
lt_zip = io_repo->get_files_local( lo_log ).
IF lo_log->count( ) > 0.
lo_log->show( ).
ENDIF.
IF iv_zip = abap_true.
file_download( iv_package = io_repo->get_package( )
iv_xstr = encode_files( lt_zip ) ).
ELSE.
files_commit( lt_zip ).
ENDIF.
ENDMETHOD. "export_key
METHOD import.
DATA: lo_repo TYPE REF TO lcl_repo_offline.
lo_repo ?= lcl_app=>repo_srv( )->get( iv_key ).
lo_repo->set_files_remote( unzip_file( file_upload( ) ) ).
lo_repo->deserialize( ).
ENDMETHOD. "import
METHOD files_commit.
DATA: lv_folder TYPE string,
lv_filename TYPE string,
lv_par TYPE string,
lv_message TYPE string,
lt_rawdata TYPE solix_tab.
FIELD-SYMBOLS: <ls_file> LIKE LINE OF it_files.
cl_gui_frontend_services=>directory_browse(
EXPORTING
window_title = 'Select folder'
CHANGING
selected_folder = lv_folder
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
not_supported_by_gui = 3
OTHERS = 4 ). "#EC NOTEXT
IF sy-subrc <> 0.
_raise 'error from directory_browser'.
ENDIF.
IF lv_folder IS INITIAL.
RETURN.
ENDIF.
lv_message = get_message( ).
LOOP AT it_files ASSIGNING <ls_file>.
lt_rawdata = cl_bcs_convert=>xstring_to_solix( <ls_file>-file-data ).
CONCATENATE lv_folder <ls_file>-file-path <ls_file>-file-filename INTO lv_filename.
cl_gui_frontend_services=>gui_download(
EXPORTING
bin_filesize = xstrlen( <ls_file>-file-data )
filename = lv_filename
filetype = 'BIN'
CHANGING
data_tab = lt_rawdata
EXCEPTIONS
file_write_error = 1
no_batch = 2
gui_refuse_filetransfer = 3
invalid_type = 4
no_authority = 5
unknown_error = 6
header_not_allowed = 7
separator_not_allowed = 8
filesize_not_allowed = 9
header_too_long = 10
dp_error_create = 11
dp_error_send = 12
dp_error_write = 13
unknown_dp_error = 14
access_denied = 15
dp_out_of_memory = 16
disk_full = 17
dp_timeout = 18
file_not_found = 19
dataprovider_exception = 20
control_flush_error = 21
not_supported_by_gui = 22
error_no_gui = 23
OTHERS = 24 ).
IF sy-subrc <> 0.
_raise 'error from gui_download'.
ENDIF.
ENDLOOP.
* assumption: git command is in PATH
cl_gui_frontend_services=>execute(
EXPORTING
application = 'git'
default_directory = lv_folder
synchronous = 'X'
parameter = 'add *'
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
bad_parameter = 3
file_not_found = 4
path_not_found = 5
file_extension_unknown = 6
error_execute_failed = 7
synchronous_failed = 8
not_supported_by_gui = 9
OTHERS = 10 ). "#EC NOTEXT
IF sy-subrc <> 0.
_raise 'error from execute'.
ENDIF.
* make sure to set git user.email and user.name manually
lv_par = 'commit -m "' && lv_message && '"'. "#EC NOTEXT
cl_gui_frontend_services=>execute(
EXPORTING
application = 'git'
default_directory = lv_folder
synchronous = 'X'
parameter = lv_par
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
bad_parameter = 3
file_not_found = 4
path_not_found = 5
file_extension_unknown = 6
error_execute_failed = 7
synchronous_failed = 8
not_supported_by_gui = 9
OTHERS = 10 ).
IF sy-subrc <> 0.
_raise 'error from execute'.
ENDIF.
ENDMETHOD. "files_commit
ENDCLASS. "lcl_zip IMPLEMENTATION