static void rm_directory_add_subdir(RmDirectory *parent, RmDirectory *subdir) { if(subdir->was_merged) { return; } parent->mergeups = subdir->mergeups + parent->mergeups + 1; parent->dupe_count += subdir->dupe_count; g_queue_push_head(&parent->children, subdir); parent->prefd_files += subdir->prefd_files; #ifdef _RM_TREEMERGE_DEBUG g_printerr("%55s (%3ld/%3ld) <- %s (%3ld/%3ld)\n", parent->dirname, parent->dupe_count, parent->file_count, subdir->dirname, subdir->dupe_count, subdir->file_count); #endif /** * Here's something weird: * - a counter is used and substraced at once from parent->dupe_count. * - it would ofc. be nicer to substract it step by step. * - but for some weird reasons this only works on clang, not gcc. * - yes, what. But I tested this, I promise! */ for(GList *iter = subdir->known_files.head; iter; iter = iter->next) { int c = rm_directory_add(parent, (RmFile *)iter->data); parent->dupe_count -= c; } /* Inherit the child's checksum */ unsigned char *subdir_cksum = rm_digest_steal_buffer(subdir->digest); rm_digest_update(parent->digest, subdir_cksum, subdir->digest->bytes); g_slice_free1(subdir->digest->bytes, subdir_cksum); subdir->was_merged = true; }
void rm_tm_feed(RmTreeMerger *self, RmFile *file) { RM_DEFINE_PATH(file); char *dirname = g_path_get_dirname(file_path); /* See if we know that directory already */ RmDirectory *directory = rm_trie_search(&self->dir_tree, dirname); if(directory == NULL) { /* Get the actual file count */ int file_count = GPOINTER_TO_INT(rm_trie_search(&self->count_tree, dirname)); if(file_count == 0) { rm_log_error( RED "Empty directory or weird RmFile encountered; rejecting.\n" RESET); file_count = -1; } directory = rm_directory_new(dirname); directory->file_count = file_count; /* Make the new directory known */ rm_trie_insert(&self->dir_tree, dirname, directory); g_queue_push_head(&self->valid_dirs, directory); } else { g_free(dirname); } g_queue_push_tail(self->free_list, file); rm_directory_add(directory, file); /* Add the file to this directory */ g_queue_push_head(&directory->known_files, file); /* Remember the digest (if only to free it later...) */ g_hash_table_replace(self->known_hashs, file->digest, NULL); /* Check if the directory reached the number of actual files in it */ if(directory->dupe_count == directory->file_count && directory->file_count > 0) { rm_tm_insert_dir(self, directory); } }