update: obey .mpdignore files
This commit is contained in:
		
							
								
								
									
										94
									
								
								src/exclude.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/exclude.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* | ||||
|  * Copyright (C) 2003-2009 The Music Player Daemon Project | ||||
|  * http://www.musicpd.org | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along | ||||
|  * with this program; if not, write to the Free Software Foundation, Inc., | ||||
|  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * The .mpdignore backend code. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "exclude.h" | ||||
| #include "path.h" | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
| #include <fnmatch.h> | ||||
|  | ||||
| GSList * | ||||
| exclude_list_load(const char *path_fs) | ||||
| { | ||||
| 	FILE *file; | ||||
| 	char line[1024]; | ||||
| 	GSList *list = NULL; | ||||
|  | ||||
| 	assert(path_fs != NULL); | ||||
|  | ||||
| 	file = fopen(path_fs, "r"); | ||||
| 	if (file == NULL) { | ||||
| 		if (errno != ENOENT) { | ||||
| 			char *path_utf8 = fs_charset_to_utf8(path_fs); | ||||
| 			g_debug("Failed to open %s: %s", | ||||
| 				path_utf8, g_strerror(errno)); | ||||
| 			g_free(path_utf8); | ||||
| 		} | ||||
|  | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	while (fgets(line, sizeof(line), file) != NULL) { | ||||
| 		char *p = strchr(line, '#'); | ||||
| 		if (p != NULL) | ||||
| 			*p = 0; | ||||
|  | ||||
| 		p = g_strstrip(line); | ||||
| 		if (*p != 0) | ||||
| 			list = g_slist_prepend(list, g_strdup(p)); | ||||
| 	} | ||||
|  | ||||
| 	fclose(file); | ||||
|  | ||||
| 	return list; | ||||
| } | ||||
|  | ||||
| void | ||||
| exclude_list_free(GSList *list) | ||||
| { | ||||
| 	while (list != NULL) { | ||||
| 		g_free(list->data); | ||||
| 		list = g_slist_remove(list, list->data); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| bool | ||||
| exclude_list_check(GSList *list, const char *name_fs) | ||||
| { | ||||
| 	assert(name_fs != NULL); | ||||
|  | ||||
| 	/* XXX include full path name in check */ | ||||
|  | ||||
| 	for (; list != NULL; list = list->next) { | ||||
| 		const char *pattern = list->data; | ||||
|  | ||||
| 		if (fnmatch(pattern, name_fs, FNM_PATHNAME|FNM_PERIOD) == 0) | ||||
| 			return true; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
							
								
								
									
										51
									
								
								src/exclude.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/exclude.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
|  * Copyright (C) 2003-2009 The Music Player Daemon Project | ||||
|  * http://www.musicpd.org | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along | ||||
|  * with this program; if not, write to the Free Software Foundation, Inc., | ||||
|  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * The .mpdignore backend code. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef MPD_EXCLUDE_H | ||||
| #define MPD_EXCLUDE_H | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| #include <stdbool.h> | ||||
|  | ||||
| /** | ||||
|  * Loads and parses a .mpdignore file. | ||||
|  */ | ||||
| GSList * | ||||
| exclude_list_load(const char *path_fs); | ||||
|  | ||||
| /** | ||||
|  * Frees a list returned by exclude_list_load(). | ||||
|  */ | ||||
| void | ||||
| exclude_list_free(GSList *list); | ||||
|  | ||||
| /** | ||||
|  * Checks whether one of the patterns in the .mpdignore file matches | ||||
|  * the specified file name. | ||||
|  */ | ||||
| bool | ||||
| exclude_list_check(GSList *list, const char *name_fs); | ||||
|  | ||||
| #endif | ||||
| @@ -19,6 +19,7 @@ | ||||
|  | ||||
| #include "update_internal.h" | ||||
| #include "database.h" | ||||
| #include "exclude.h" | ||||
| #include "directory.h" | ||||
| #include "song.h" | ||||
| #include "uri.h" | ||||
| @@ -154,6 +155,48 @@ delete_name_in(struct directory *parent, const char *name) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* passed to songvec_for_each */ | ||||
| static int | ||||
| delete_song_if_excluded(struct song *song, void *_data) | ||||
| { | ||||
| 	GSList *exclude_list = _data; | ||||
| 	char *name_fs; | ||||
|  | ||||
| 	assert(song->parent != NULL); | ||||
|  | ||||
| 	name_fs = utf8_to_fs_charset(song->uri); | ||||
| 	if (exclude_list_check(exclude_list, name_fs)) { | ||||
| 		delete_song(song->parent, song); | ||||
| 		modified = true; | ||||
| 	} | ||||
|  | ||||
| 	g_free(name_fs); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void | ||||
| remove_excluded_from_directory(struct directory *directory, | ||||
| 			       GSList *exclude_list) | ||||
| { | ||||
| 	int i; | ||||
| 	struct dirvec *dv = &directory->children; | ||||
|  | ||||
| 	for (i = dv->nr; --i >= 0; ) { | ||||
| 		struct directory *child = dv->base[i]; | ||||
| 		char *name_fs = utf8_to_fs_charset(directory_get_name(child)); | ||||
|  | ||||
| 		if (exclude_list_check(exclude_list, name_fs)) { | ||||
| 			delete_directory(child); | ||||
| 			modified = true; | ||||
| 		} | ||||
|  | ||||
| 		g_free(name_fs); | ||||
| 	} | ||||
|  | ||||
| 	songvec_for_each(&directory->songs, | ||||
| 			 delete_song_if_excluded, exclude_list); | ||||
| } | ||||
|  | ||||
| /* passed to songvec_for_each */ | ||||
| static int | ||||
| delete_song_if_removed(struct song *song, void *_data) | ||||
| @@ -613,7 +656,8 @@ updateDirectory(struct directory *directory, const struct stat *st) | ||||
| { | ||||
| 	DIR *dir; | ||||
| 	struct dirent *ent; | ||||
| 	char *path_fs; | ||||
| 	char *path_fs, *exclude_path_fs; | ||||
| 	GSList *exclude_list; | ||||
|  | ||||
| 	assert(S_ISDIR(st->st_mode)); | ||||
|  | ||||
| @@ -631,15 +675,24 @@ updateDirectory(struct directory *directory, const struct stat *st) | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	exclude_path_fs  = g_strconcat(path_fs, G_DIR_SEPARATOR_S, | ||||
| 				       ".mpdignore", NULL); | ||||
| 	exclude_list = exclude_list_load(exclude_path_fs); | ||||
| 	g_free(exclude_path_fs); | ||||
|  | ||||
| 	g_free(path_fs); | ||||
|  | ||||
| 	if (exclude_list != NULL) | ||||
| 		remove_excluded_from_directory(directory, exclude_list); | ||||
|  | ||||
| 	removeDeletedFromDirectory(directory); | ||||
|  | ||||
| 	while ((ent = readdir(dir))) { | ||||
| 		char *utf8; | ||||
| 		struct stat st2; | ||||
|  | ||||
| 		if (skip_path(ent->d_name)) | ||||
| 		if (skip_path(ent->d_name) || | ||||
| 		    exclude_list_check(exclude_list, ent->d_name)) | ||||
| 			continue; | ||||
|  | ||||
| 		utf8 = fs_charset_to_utf8(ent->d_name); | ||||
| @@ -656,6 +709,8 @@ updateDirectory(struct directory *directory, const struct stat *st) | ||||
| 		g_free(utf8); | ||||
| 	} | ||||
|  | ||||
| 	exclude_list_free(exclude_list); | ||||
|  | ||||
| 	closedir(dir); | ||||
|  | ||||
| 	directory->mtime = st->st_mtime; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann