/* Composes two views containing only files that are unique to each of them. * Assumes that both lists are sorted by id. */ static void make_unique_lists(entries_t curr, entries_t other) { int i, j = 0; flist_custom_start(curr_view, "unique"); flist_custom_start(other_view, "unique"); for(i = 0; i < other.nentries; ++i) { const int id = other.entries[i].id; while(j < curr.nentries && curr.entries[j].id < id) { flist_custom_put(curr_view, &curr.entries[j]); ++j; } if(j >= curr.nentries || curr.entries[j].id != id) { flist_custom_put(other_view, &other.entries[i]); continue; } while(j < curr.nentries && curr.entries[j].id == id) { free_dir_entry(curr_view, &curr.entries[j++]); } while(i < other.nentries && other.entries[i].id == id) { free_dir_entry(other_view, &other.entries[i++]); } --i; } /* Entries' data has been moved out of them or freed, so need to free only the * lists. */ dynarray_free(curr.entries); dynarray_free(other.entries); (void)flist_custom_finish(curr_view, CV_REGULAR, 1); (void)flist_custom_finish(other_view, CV_REGULAR, 1); curr_view->list_pos = 0; other_view->list_pos = 0; ui_view_schedule_redraw(curr_view); ui_view_schedule_redraw(other_view); }
TEST(symlinks_to_dirs_are_recognized_as_dirs, IF(not_windows)) { char test_dir[PATH_MAX]; assert_non_null(os_realpath(TEST_DATA_PATH "/existing-files", test_dir)); assert_success(chdir(SANDBOX_PATH)); /* symlink() is not available on Windows, but other code is fine. */ #ifndef _WIN32 assert_success(symlink(test_dir, "dir-link")); #endif (void)test_dir; assert_false(flist_custom_active(&lwin)); flist_custom_start(&lwin, "test"); flist_custom_add(&lwin, "./dir-link"); assert_true(flist_custom_finish(&lwin, 0) == 0); assert_int_equal(1, lwin.list_rows); assert_true(is_directory_entry(&lwin.dir_entry[0])); assert_success(remove("dir-link")); }
TEST(reload_does_not_remove_broken_symlinks, IF(not_windows)) { char test_file[PATH_MAX]; assert_non_null(os_realpath(TEST_DATA_PATH "/existing-files/a", test_file)); assert_success(chdir(SANDBOX_PATH)); /* symlink() is not available on Windows, but other code is fine. */ #ifndef _WIN32 assert_success(symlink("/wrong/path", "broken-link")); #endif assert_false(flist_custom_active(&lwin)); flist_custom_start(&lwin, "test"); flist_custom_add(&lwin, test_file); flist_custom_add(&lwin, "./broken-link"); assert_true(flist_custom_finish(&lwin, 0) == 0); assert_int_equal(2, lwin.list_rows); load_dir_list(&lwin, 1); assert_int_equal(2, lwin.list_rows); assert_success(remove("broken-link")); }
static void setup_custom_view(FileView *view) { assert_false(flist_custom_active(view)); snprintf(view->curr_dir, sizeof(view->curr_dir), "%s/existing-files", test_data); flist_custom_start(view, "test"); flist_custom_add(view, TEST_DATA_PATH "/existing-files/a"); assert_true(flist_custom_finish(view, 0) == 0); }
int compare_two_panes(CompareType ct, ListType lt, int group_paths, int skip_empty) { int next_id = 1; entries_t curr, other; trie_t *const trie = trie_create(); ui_cancellation_reset(); ui_cancellation_enable(); curr = make_diff_list(trie, curr_view, &next_id, ct, skip_empty, 0); other = make_diff_list(trie, other_view, &next_id, ct, skip_empty, lt == LT_DUPS); ui_cancellation_disable(); trie_free_with_data(trie, &free_compare_records); /* Clear progress message displayed by make_diff_list(). */ ui_sb_quick_msg_clear(); if(ui_cancellation_requested()) { free_dir_entries(curr_view, &curr.entries, &curr.nentries); free_dir_entries(other_view, &other.entries, &other.nentries); status_bar_message("Comparison has been cancelled"); return 1; } if(!group_paths || lt != LT_ALL) { /* Sort both lists according to unique file numbers to group identical files * (sorting is stable, tags are set in make_diff_list()). */ qsort(curr.entries, curr.nentries, sizeof(*curr.entries), &id_sorter); qsort(other.entries, other.nentries, sizeof(*other.entries), &id_sorter); } if(lt == LT_UNIQUE) { make_unique_lists(curr, other); return 0; } if(lt == LT_DUPS) { leave_only_dups(&curr, &other); } flist_custom_start(curr_view, lt == LT_ALL ? "diff" : "dups diff"); flist_custom_start(other_view, lt == LT_ALL ? "diff" : "dups diff"); fill_side_by_side(curr, other, group_paths); if(flist_custom_finish(curr_view, CV_DIFF, 0) != 0) { show_error_msg("Comparison", "No results to display"); return 0; } if(flist_custom_finish(other_view, CV_DIFF, 0) != 0) { assert(0 && "The error shouldn't be happening here."); } curr_view->list_pos = 0; other_view->list_pos = 0; curr_view->custom.diff_cmp_type = ct; other_view->custom.diff_cmp_type = ct; curr_view->custom.diff_path_group = group_paths; other_view->custom.diff_path_group = group_paths; assert(curr_view->list_rows == other_view->list_rows && "Diff views must be in sync!"); ui_view_schedule_redraw(curr_view); ui_view_schedule_redraw(other_view); return 0; }
int compare_one_pane(FileView *view, CompareType ct, ListType lt, int skip_empty) { int i, dup_id; FileView *other = (view == curr_view) ? other_view : curr_view; const char *const title = (lt == LT_ALL) ? "compare" : (lt == LT_DUPS) ? "dups" : "nondups"; int next_id = 1; entries_t curr; trie_t *trie = trie_create(); ui_cancellation_reset(); ui_cancellation_enable(); curr = make_diff_list(trie, view, &next_id, ct, skip_empty, 0); ui_cancellation_disable(); trie_free_with_data(trie, &free_compare_records); /* Clear progress message displayed by make_diff_list(). */ ui_sb_quick_msg_clear(); if(ui_cancellation_requested()) { free_dir_entries(view, &curr.entries, &curr.nentries); status_bar_message("Comparison has been cancelled"); return 1; } qsort(curr.entries, curr.nentries, sizeof(*curr.entries), &id_sorter); flist_custom_start(view, title); dup_id = -1; next_id = 0; for(i = 0; i < curr.nentries; ++i) { dir_entry_t *entry = &curr.entries[i]; if(lt == LT_ALL) { flist_custom_put(view, entry); continue; } if(entry->id == dup_id) { put_or_free(view, entry, next_id, lt == LT_DUPS); continue; } dup_id = (i < curr.nentries - 1 && entry[0].id == entry[1].id) ? entry->id : -1; if(entry->id == dup_id) { put_or_free(view, entry, ++next_id, lt == LT_DUPS); continue; } put_or_free(view, entry, next_id, lt == LT_UNIQUE); } /* Entries' data has been moved out of them or freed, so need to free only the * list. */ dynarray_free(curr.entries); if(flist_custom_finish(view, lt == LT_UNIQUE ? CV_REGULAR : CV_COMPARE, 0) != 0) { show_error_msg("Comparison", "No results to display"); return 0; } /* Leave the other pane, if it's in the CV_DIFF mode, two panes are needed for * this. */ if(other->custom.type == CV_DIFF) { cd_updir(other, 1); } view->list_pos = 0; ui_view_schedule_redraw(view); return 0; }
int menu_to_custom_view(menu_state_t *m, FileView *view, int very) { int i; char *current = NULL; const char *const rel_base = get_relative_path_base(m->d, view); flist_custom_start(view, m->d->title); for(i = 0; i < m->d->len; ++i) { char *path; int line_num; /* Skip empty lines. */ if(skip_whitespace(m->d->items[i])[0] == '\0') { continue; } path = parse_file_spec(m->d->items[i], &line_num, rel_base); if(path == NULL) { continue; } flist_custom_add(view, path); /* Use either exact position or the next path. */ if(i == m->d->pos || (current == NULL && i > m->d->pos)) { current = path; continue; } free(path); } /* If current line and none of the lines below didn't contain valid path, try * to use file above cursor position. */ if(current == NULL && view->custom.entry_count != 0) { char full_path[PATH_MAX]; get_full_path_of(&view->custom.entries[view->custom.entry_count - 1], sizeof(full_path), full_path); current = strdup(full_path); } if(flist_custom_finish(view, very ? CV_VERY : CV_REGULAR, 0) != 0) { free(current); return 1; } if(current != NULL) { flist_goto_by_path(view, current); free(current); } return 0; }