<commit_before>using Gtk;
using Ginko.IO;
using Ginko.Util;
using Ginko.Dialogs;
using Ginko.Operations;


namespace Ginko.Actions {

class CopyFileAction : AbstractFileAction {
    
    private CopyFileConfig m_config;
    
    private uint64 m_bytes_processed;
    private uint64 m_bytes_total;
    
    private CopyFileOperation m_copy_op;
    private uint64 m_bytes_processed_before;
    
    private bool m_overwrite_all;
    private bool m_skip_all;
    
    protected CopyFileAction(ActionDescriptor p_action_descriptor) {
        base(p_action_descriptor);
    }
    
    protected override bool verify(ActionContext p_context) {
        if (p_context.source_selected_files.length == 0) {
            show_error("You must select at least one file.");
            return false;
        }
        
        return true;
    }
    
    protected override bool configure(ActionContext p_context) {
        var config_dialog = new CopyFileConfigureDialog(p_context);
        
        int return_code = config_dialog.run();
        m_config = config_dialog.get_config();
        set_follow_symlinks(m_config.follow_symlinks);
        
        config_dialog.close();
        
        return return_code == CopyFileConfigureDialog.Response.OK;
    }
    
    protected override bool prepare_t(ActionContext p_context) {
        foreach (var infile in p_context.source_selected_files) {
            m_bytes_total += Files.calculate_space_recurse(infile, m_config.follow_symlinks);
        }
        
        return true;
    }
    
    protected override bool on_file_found_t(ActionContext p_context,
        File p_file, FileInfo p_fileinfo,
        AbstractFileAction.ProgressCallback p_callback) {
    
        
        File dest_dir;
        if (!Files.is_relative(m_config.destination)) {
            dest_dir = File.new_for_path(m_config.destination);
        } else {
            dest_dir = p_context.source_dir.resolve_relative_path(m_config.destination);
        }
        
        if (!dest_dir.query_exists()) {
            try {
                dest_dir.make_directory_with_parents();
            } catch (Error e) {
                show_error(e.message + "\n" + dest_dir.get_path());
                set_status(Status.ERROR);
                return false;
            }
        }
    
        var dst_file = Files.rebase(p_file,
            p_context.source_dir, dest_dir);
        
        create_copy_file_operation_t(p_file, dst_file, p_callback);
        
        p_callback(get_progress_percent(), "Copying %s".printf(p_file.get_path()));
        
        var file_type = p_fileinfo.get_file_type();
        
        do {
            if (file_type == FileType.DIRECTORY) {
                try {
                    dst_file.make_directory();
                    set_status(Status.SUCCESS);
                } catch (IOError e) {
                    show_error(e.message + "\n" + dst_file.get_path());
                    set_status(Status.ERROR);
                }
            } else {
                try {
                    m_copy_op.execute();
                    set_status(Status.SUCCESS);
                } catch (IOError e) {
                    if (e is IOError.CANCELLED) {
                        set_status(Status.CANCEL);
                    } else if (e is IOError.NOT_FOUND) {
                        show_error(e.message + "\n" + p_file.get_path());
                        set_status(Status.ERROR);
                    } else if (e is IOError.EXISTS) {
                        if (m_skip_all) {
                            set_status(Status.SKIP);
                        } else if (m_overwrite_all) {
                            m_copy_op.m_overwrite = true;
                            set_status(Status.TRY_AGAIN);
                        } else {
                            prompt_overwrite_t(p_context);
                        }
                    } else {
                        show_error(e.message + "\n" + p_file.get_path()
                            + " to " + dst_file.get_path());
                        set_status(Status.ERROR);
                    }
                }
            }
            
            if (Config.debug) {
                Posix.sleep(1);
            }
            
        } while (get_status() == Status.TRY_AGAIN); // retry until action is done
        
        return true;<commit_msg>Corrected behavior of copy destination<commit_after>using Gtk;
using Ginko.IO;
using Ginko.Util;
using Ginko.Dialogs;
using Ginko.Operations;


namespace Ginko.Actions {

class CopyFileAction : AbstractFileAction {
    
    private CopyFileConfig m_config;
    
    private uint64 m_bytes_processed;
    private uint64 m_bytes_total;
    
    private CopyFileOperation m_copy_op;
    private uint64 m_bytes_processed_before;
    
    private bool m_overwrite_all;
    private bool m_skip_all;
    
    private File m_rebase_base;
    
    protected CopyFileAction(ActionDescriptor p_action_descriptor) {
        base(p_action_descriptor);
    }
    
    protected override bool verify(ActionContext p_context) {
        if (p_context.source_selected_files.length == 0) {
            show_error("You must select at least one file.");
            return false;
        }
        
        return true;
    }
    
    protected override bool configure(ActionContext p_context) {
        var config_dialog = new CopyFileConfigureDialog(p_context);
        
        int return_code = config_dialog.run();
        m_config = config_dialog.get_config();
        set_follow_symlinks(m_config.follow_symlinks);
        
        config_dialog.close();
        
        return return_code == CopyFileConfigureDialog.Response.OK;
    }
    
    protected override bool prepare_t(ActionContext p_context) {
        foreach (var infile in p_context.source_selected_files) {
            m_bytes_total += Files.calculate_space_recurse(infile, m_config.follow_symlinks);
        }
        
        return true;
    }
    
    protected override bool on_file_found_t(ActionContext p_context,
        File p_file, FileInfo p_fileinfo,
        AbstractFileAction.ProgressCallback p_callback) {
    
        
        // if source is only one file/directory:
        //   if destination exists copy source to destination/source
        //   if destination doesn't exists copy and rename source to .../destination
        // if source are many files/directories:
        //   always copy to destination/source even if it doesn't exists
        
        File dest_file;
        if (!Files.is_relative(m_config.destination)) {
            dest_file = File.new_for_path(m_config.destination);
        } else {
            dest_file = p_context.source_dir.resolve_relative_path(m_config.destination);
        }
        
        int source_files_count = p_context.source_selected_files.length;
        if (source_files_count == 1) {
            
            // if this is first file in process treat is spiecially
            if (p_file == p_context.source_selected_files[0]) {
                if (dest_file.query_exists()) {
                    dest_file = Files.rebase(p_file, p_context.source_dir, dest_file);
                    m_rebase_base = p_context.source_dir;
                } else {
                    // write to .../destination directly
                    // rebase one level down
                    m_rebase_base = p_file;
                }
            } else {
                dest_file = Files.rebase(p_file, m_rebase_base, dest_file);
            }
            
        } else {
            if (!dest_file.query_exists()) {
                try {
                    dest_file.make_directory_with_parents();
                    m_rebase_base = p_context.source_dir;
                } catch (Error e) {
                    show_error(e.message + "\n" + dest_file.get_path());
                    set_status(Status.ERROR);
                    return false;
                }
            }
            
            dest_file = Files.rebase(p_file, m_rebase_base, dest_file);
        }
        
        debug("dest: %s", dest_file.get_path());
        
        
        create_copy_file_operation_t(p_file, dest_file, p_callback);
        
        p_callback(get_progress_percent(), "Copying %s".printf(p_file.get_path()));
        
        var file_type = p_fileinfo.get_file_type();
        
        do {
            if (file_type == FileType.DIRECTORY) {
                try {
                    dest_file.make_directory();
                    set_status(Status.SUCCESS);
                } catch (IOError e) {
                    show_error(e.message + "\n" + dest_file.get_path());
                    set_status(Status.ERROR);
                }
            } else {
                try {
                    m_copy_op.execute();
                    set_status(Status.SUCCESS);
                } catch (IOError e) {
                    if (e is IOError.CANCELLED) {
                        set_status(Status.CANCEL);
                    } else if (e is IOError.NOT_FOUND) {
                        show_error(e.message + "\n" + p_file.get_path());
                        set_status(Status.ERROR);
                    } else if (e is IOError.EXISTS) {
                        if (m_skip_all) {
                            set_status(Status.SKIP);
                        } else if (m_overwrite_all) {
                            m_copy_op.m_overwrite = true;
                            set_status(Status.TRY_AGAIN);
                        } else {
                            prompt_overwrite_t(p_context);
                        }
                    } else {
                        show_error(e.message + "\n" + p_file.get_path()
                            + " to " + dest_file.get_path());
                        set_status(Status.ERROR);
                    }
                }
            }
            
            if (Config.debug) {
                Posix.sleep(1);
            }
            
        } while (get_status() == Status.TRY_AGAIN); // retry until action is done
        
        return true;
{'fraction_non_alphanumeric': 0.08081810961080223, 'fraction_numerical': 0.0017871326449563146, 'mean_word_length': 1.4628361858190708, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4219059', 'n_tokens_mistral': 2817, 'n_tokens_neox': 2721, 'n_words': 513}