static void test_disbalance(void) { static int undo_levels = 10; init_undo_list(&execute_fail, &undo_levels); reset_undo_list(); cmd_group_begin("msg0"); assert_int_equal(0, add_operation(OP_COPY, NULL, NULL, "do_msg0", "undo_msg0")); cmd_group_end(); cmd_group_begin("msg1"); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg1", "undo_msg1")); cmd_group_end(); assert_int_equal(0, undo_group()); assert_int_equal(-3, undo_group()); assert_int_equal(-1, undo_group()); assert_int_equal(-4, redo_group()); assert_int_equal(0, redo_group()); assert_int_equal(-1, redo_group()); }
static void setup(void) { static int undo_levels = 10; int ret_code; init_undo_list_for_tests(&exec_func, &undo_levels); cmd_group_begin("msg1"); ret_code = add_operation(OP_MOVE, NULL, NULL, "do_msg1", "undo_msg1"); assert(ret_code == 0); cmd_group_end(); cmd_group_begin("msg2"); ret_code = add_operation(OP_MOVE, NULL, NULL, "do_msg2_cmd1", "undo_msg2_cmd1"); assert(ret_code == 0); ret_code = add_operation(OP_MOVE, NULL, NULL, "do_msg2_cmd2", "undo_msg2_cmd2"); assert(ret_code == 0); cmd_group_end(); cmd_group_begin("msg3"); ret_code = add_operation(OP_MOVE, NULL, NULL, "do_msg3", "undo_msg3"); assert(ret_code == 0); cmd_group_end(); }
void files_chmod(FileView *view, const char *mode, int recurse_dirs) { int i; ui_cancellation_reset(); i = 0; while(i < view->list_rows && !view->dir_entry[i].selected) i++; if(i == view->list_rows) { char buf[COMMAND_GROUP_INFO_LEN]; char inv[16]; snprintf(buf, sizeof(buf), "chmod in %s: %s", replace_home_part(flist_get_dir(view)), view->dir_entry[view->list_pos].name); cmd_group_begin(buf); snprintf(inv, sizeof(inv), "0%o", view->dir_entry[view->list_pos].mode & 0xff); chmod_file_in_list(view, view->list_pos, mode, inv, recurse_dirs); } else { char buf[COMMAND_GROUP_INFO_LEN]; size_t len; int j = i; len = snprintf(buf, sizeof(buf), "chmod in %s: ", replace_home_part(flist_get_dir(view))); while(i < view->list_rows && len < sizeof(buf)) { if(view->dir_entry[i].selected) { if(len >= 2 && buf[len - 2] != ':') { strncat(buf + len, ", ", sizeof(buf) - len - 1); len += strlen(buf + len); } strncat(buf + len, view->dir_entry[i].name, sizeof(buf) - len - 1); len += strlen(buf + len); } i++; } cmd_group_begin(buf); while(j < view->list_rows && !ui_cancellation_requested()) { if(view->dir_entry[j].selected) { char inv[16]; snprintf(inv, sizeof(inv), "0%o", view->dir_entry[j].mode & 0xff); chmod_file_in_list(view, j, mode, inv, recurse_dirs); } j++; } } cmd_group_end(); }
/* changes attributes of files in the view */ static void files_attrib(FileView *view, DWORD add, DWORD sub, int recurse_dirs) { int i; ui_cancellation_reset(); i = 0; while(i < view->list_rows && !view->dir_entry[i].selected) i++; if(i == view->list_rows) { char buf[COMMAND_GROUP_INFO_LEN]; snprintf(buf, sizeof(buf), "chmod in %s: %s", replace_home_part(view->curr_dir), view->dir_entry[view->list_pos].name); cmd_group_begin(buf); attrib_file_in_list(view, view->list_pos, add, sub, recurse_dirs); } else { char buf[COMMAND_GROUP_INFO_LEN]; size_t len; int j = i; len = snprintf(buf, sizeof(buf), "chmod in %s: ", replace_home_part(view->curr_dir)); while(i < view->list_rows && len < sizeof(buf)) { if(view->dir_entry[i].selected) { if(len >= 2 && buf[len - 2] != ':') { strncat(buf + len, ", ", sizeof(buf) - len - 1); len += strlen(buf + len); } strncat(buf + len, view->dir_entry[i].name, sizeof(buf) - len - 1); len += strlen(buf + len); } i++; } cmd_group_begin(buf); while(j < view->list_rows && !ui_cancellation_requested()) { if(view->dir_entry[j].selected) { attrib_file_in_list(view, j, add, sub, recurse_dirs); } j++; } } cmd_group_end(); }
static void test_to_many_commands_and_continue(void) { static int undo_levels = 3; init_undo_list(&exec_skip, &undo_levels); cmd_group_begin("msg0"); cmd_group_end(); cmd_group_continue(); free(replace_group_msg("HI")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg0", "undo_msg0")); cmd_group_end(); cmd_group_continue(); free(replace_group_msg("HI")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg0", "undo_msg0")); cmd_group_end(); cmd_group_continue(); free(replace_group_msg("HI")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg0", "undo_msg0")); cmd_group_end(); cmd_group_continue(); free(replace_group_msg("HI")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg0", "undo_msg0")); cmd_group_end(); cmd_group_continue(); free(replace_group_msg("HI")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg0", "undo_msg0")); cmd_group_end(); }
/* Restores current item from the trash. */ static KHandlerResponse restore_current(menu_data_t *m) { char *trash_path; int err; cmd_group_begin("restore: "); cmd_group_end(); /* The string is freed in restore_from_trash(), thus must be cloned. */ trash_path = strdup(trash_list[m->pos].trash_name); err = restore_from_trash(trash_path); free(trash_path); if(err != 0) { const char *const orig_path = m->items[m->pos]; status_bar_errorf("Failed to restore %s", orig_path); curr_stats.save_msg = 1; return KHR_UNHANDLED; } remove_current_item(m->state); return KHR_REFRESH_WINDOW; }
static void test_too_many_commands(void) { cmd_group_begin("msg4"); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg40", "undo_msg40")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg41", "undo_msg41")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg42", "undo_msg42")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg43", "undo_msg43")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg44", "undo_msg44")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg45", "undo_msg45")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg46", "undo_msg46")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg47", "undo_msg47")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg48", "undo_msg48")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg49", "undo_msg49")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg4a", "undo_msg4a")); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg4b", "undo_msg4b")); cmd_group_end(); }
static void test_cannot_be_undone(void) { cmd_group_begin("msg0"); assert_int_equal(0, add_operation(OP_REMOVE, NULL, NULL, "do_msg0", "")); cmd_group_end(); assert_int_equal(-5, undo_group()); }
static void test_removing_of_incomplete_groups(void) { static int undo_levels = 10; int i; init_undo_list(&exec_dummy, &undo_levels); cmd_group_begin("msg0"); for(i = 0; i < 10; i++) assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg0", "undo_msg0")); cmd_group_end(); cmd_group_begin("msg1"); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg1", "undo_msg1")); cmd_group_end(); assert_int_equal(0, undo_group()); assert_int_equal(-1, undo_group()); }
static void test_negative_undolevel(void) { static int undo_levels = -1; init_undo_list_for_tests(&execute_dummy, &undo_levels); cmd_group_begin("msg4"); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg4", "undo_msg4")); cmd_group_end(); assert_int_equal(-1, undo_group()); }
static void test_skipping(void) { static int undo_levels = 10; init_undo_list(&exec_skip, &undo_levels); cmd_group_begin("msg0"); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg0", "undo_msg0")); cmd_group_end(); assert_int_equal(-6, undo_group()); assert_int_equal(-4, redo_group()); }
static void test_cmd_1undo_1redo(void) { static int undo_levels = 10; reset_undo_list(); init_undo_list(&exec_dummy, &undo_levels); cmd_group_begin("msg0"); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg0", "undo_msg0")); cmd_group_end(); assert_int_equal(0, undo_group()); assert_int_equal(0, redo_group()); }
static void test_list_truncating(void) { assert_int_equal(0, undo_group()); assert_int_equal(0, undo_group()); assert_int_equal(0, undo_group()); assert_int_equal(0, redo_group()); assert_int_equal(0, redo_group()); assert_int_equal(0, redo_group()); assert_int_equal(0, undo_group()); assert_int_equal(0, undo_group()); cmd_group_begin("msg4"); assert_int_equal(0, add_operation(OP_MOVE, NULL, NULL, "do_msg4", "undo_msg4")); cmd_group_end(); assert_int_equal(-1, redo_group()); assert_int_equal(11, i); }
void files_chmod(FileView *view, const char *mode, int recurse_dirs) { char undo_msg[COMMAND_GROUP_INFO_LEN]; dir_entry_t *entry; size_t len; snprintf(undo_msg, sizeof(undo_msg), "chmod in %s: ", replace_home_part(flist_get_dir(view))); len = strlen(undo_msg); ui_cancellation_reset(); entry = NULL; while(iter_selection_or_current(view, &entry) && !ui_cancellation_requested()) { if(len >= 2U && undo_msg[len - 2U] != ':') { strncat(undo_msg + len, ", ", sizeof(undo_msg) - len - 1); len += strlen(undo_msg + len); } strncat(undo_msg + len, entry->name, sizeof(undo_msg) - len - 1); len += strlen(undo_msg + len); } cmd_group_begin(undo_msg); entry = NULL; while(iter_selection_or_current(view, &entry) && !ui_cancellation_requested()) { char inv[16]; snprintf(inv, sizeof(inv), "0%o", entry->mode & 0xff); chmod_file_in_list(view, entry_to_pos(view, entry), mode, inv, recurse_dirs); } cmd_group_end(); }
/* Changes attributes of files in the view. */ static void files_attrib(FileView *view, DWORD add, DWORD sub, int recurse_dirs) { char undo_msg[COMMAND_GROUP_INFO_LEN]; dir_entry_t *entry; size_t len; snprintf(undo_msg, sizeof(undo_msg), "chmod in %s: ", replace_home_part(flist_get_dir(view))); len = strlen(undo_msg); ui_cancellation_reset(); entry = NULL; while(iter_selection_or_current(view, &entry) && !ui_cancellation_requested()) { if(len >= 2U && undo_msg[len - 2U] != ':') { strncat(undo_msg + len, ", ", sizeof(undo_msg) - len - 1); len += strlen(undo_msg + len); } strncat(undo_msg + len, entry->name, sizeof(undo_msg) - len - 1); len += strlen(undo_msg + len); } cmd_group_begin(undo_msg); entry = NULL; while(iter_selection_or_current(view, &entry) && !ui_cancellation_requested()) { attrib_file_in_list(view, entry_to_pos(view, entry), add, sub, recurse_dirs); } cmd_group_end(); }
/* Returns negative value in case of error */ static int execute_command(FileView *view, const char command[], int menu) { int id; int result; if(command == NULL) { flist_sel_stash_if_nonempty(view); return 0; } command = skip_to_cmd_name(command); if(command[0] == '"') return 0; if(command[0] == '\0' && !menu) { flist_sel_stash_if_nonempty(view); return 0; } if(!menu) { init_cmds(1, &cmds_conf); cmds_conf.begin = 0; cmds_conf.current = view->list_pos; cmds_conf.end = view->list_rows - 1; } id = get_cmd_id(command); if(!cmd_should_be_processed(id)) { return 0; } if(id == USER_CMD_ID) { char undo_msg[COMMAND_GROUP_INFO_LEN]; snprintf(undo_msg, sizeof(undo_msg), "in %s: %s", replace_home_part(flist_get_dir(view)), command); cmd_group_begin(undo_msg); cmd_group_end(); } keep_view_selection = 0; result = execute_cmd(command); if(result >= 0) return result; switch(result) { case CMDS_ERR_LOOP: status_bar_error("Loop in commands"); break; case CMDS_ERR_NO_MEM: status_bar_error("Unable to allocate enough memory"); break; case CMDS_ERR_TOO_FEW_ARGS: status_bar_error("Too few arguments"); break; case CMDS_ERR_TRAILING_CHARS: status_bar_error("Trailing characters"); break; case CMDS_ERR_INCORRECT_NAME: status_bar_error("Incorrect command name"); break; case CMDS_ERR_NEED_BANG: status_bar_error("Add bang to force"); break; case CMDS_ERR_NO_BUILTIN_REDEFINE: status_bar_error("Can't redefine builtin command"); break; case CMDS_ERR_INVALID_CMD: status_bar_error("Invalid command name"); break; case CMDS_ERR_NO_BANG_ALLOWED: status_bar_error("No ! is allowed"); break; case CMDS_ERR_NO_RANGE_ALLOWED: status_bar_error("No range is allowed"); break; case CMDS_ERR_NO_QMARK_ALLOWED: status_bar_error("No ? is allowed"); break; case CMDS_ERR_INVALID_RANGE: /* message dialog is enough */ break; case CMDS_ERR_NO_SUCH_UDF: status_bar_error("No such user defined command"); break; case CMDS_ERR_UDF_IS_AMBIGUOUS: status_bar_error("Ambiguous use of user-defined command"); break; case CMDS_ERR_ZERO_COUNT: status_bar_error("Zero count"); break; case CMDS_ERR_INVALID_ARG: status_bar_error("Invalid argument"); break; case CMDS_ERR_CUSTOM: /* error message is posted by command handler */ break; default: status_bar_error("Unknown error"); break; } if(!menu && vle_mode_is(NORMAL_MODE)) { flist_sel_stash_if_nonempty(view); } return -1; }
static void perform_merge(int op) { #ifndef _WIN32 struct stat src, dst; #endif ops_t *ops; create_empty_dir("first"); create_empty_dir("first/nested1"); create_empty_dir("first/nested1/nested2"); create_empty_file("first/nested1/nested2/file"); create_empty_dir("second"); create_empty_dir("second/nested1"); #ifndef _WIN32 /* Something about GNU Hurd and OS X differs, so skip this workaround there. * Really need to figure out what's wrong with this thing... */ #if !defined(__gnu_hurd__) && !defined(__APPLE__) { struct timeval tv[2]; gettimeofday(&tv[0], NULL); tv[1] = tv[0]; /* This might be Linux-specific, but for the test to work properly access * time should be newer than modification time, in which case it's not * changed on listing directory. */ tv[0].tv_sec += 3; tv[0].tv_usec += 4; tv[1].tv_sec += 1; tv[1].tv_usec += 2; utimes("first/nested1", tv); } #endif assert_success(chmod("first/nested1", 0700)); assert_success(os_stat("first/nested1", &src)); #endif cmd_group_begin("undo msg"); assert_non_null(ops = ops_alloc(op, 0, "merge", ".", ".")); ops->crp = CRP_OVERWRITE_ALL; if(op == OP_MOVEF) { assert_success(merge_dirs("first", "second", ops)); } else { #ifndef _WIN32 if(!cfg.use_system_calls) { assert_success( perform_operation(op, ops, NULL, "first/nested1", "second/")); } else #endif { assert_success(perform_operation(op, ops, NULL, "first", "second")); } } ops_free(ops); cmd_group_end(); #ifndef _WIN32 { assert_success(os_stat("second/nested1", &dst)); #ifndef HAVE_STRUCT_STAT_ST_MTIM #define st_atim st_atime #define st_mtim st_mtime #endif assert_success(memcmp(&src.st_atim, &dst.st_atim, sizeof(src.st_atim))); assert_success(memcmp(&src.st_mtim, &dst.st_mtim, sizeof(src.st_mtim))); assert_success(memcmp(&src.st_mode, &dst.st_mode, sizeof(src.st_mode))); } #endif assert_true(file_exists("second/nested1/nested2/file")); assert_success(unlink("second/nested1/nested2/file")); assert_success(rmdir("second/nested1/nested2")); assert_success(rmdir("second/nested1")); assert_success(rmdir("second")); }