diff --git a/NEWS b/NEWS
index b6a64d4c3..145361c35 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,8 @@ ver 0.20 (not yet released)
* support libsystemd (instead of the older libsystemd-daemon)
* database
- proxy: add TCP keepalive option
+* update
+ - apply .mpdignore matches to subdirectories
ver 0.19.10 (2015/06/21)
* input
diff --git a/doc/user.xml b/doc/user.xml
index a08a5aec0..8a37a7cce 100644
--- a/doc/user.xml
+++ b/doc/user.xml
@@ -1077,6 +1077,8 @@ database {
To exclude a file from the update, create a file called
.mpdignore in its parent directory. Each
line of that file may contain a list of shell wildcards.
+ Matching files in the current directory and all subdirectories
+ are excluded.
diff --git a/src/db/update/ExcludeList.cxx b/src/db/update/ExcludeList.cxx
index 3b54d635e..b09f349ac 100644
--- a/src/db/update/ExcludeList.cxx
+++ b/src/db/update/ExcludeList.cxx
@@ -89,6 +89,12 @@ ExcludeList::Check(Path name_fs) const
/* XXX include full path name in check */
#ifdef HAVE_CLASS_GLOB
+ if (parent != nullptr) {
+ if (parent->Check(name_fs)) {
+ return true;
+ }
+ }
+
for (const auto &i : patterns)
if (i.Check(NarrowPath(name_fs).c_str()))
return true;
diff --git a/src/db/update/ExcludeList.hxx b/src/db/update/ExcludeList.hxx
index de48bac99..4952d291a 100644
--- a/src/db/update/ExcludeList.hxx
+++ b/src/db/update/ExcludeList.hxx
@@ -36,15 +36,23 @@
class Path;
class ExcludeList {
+ const ExcludeList *const parent;
+
#ifdef HAVE_CLASS_GLOB
std::forward_list patterns;
#endif
public:
+ ExcludeList()
+ :parent(nullptr) {}
+
+ ExcludeList(const ExcludeList &_parent)
+ :parent(&_parent) {}
+
gcc_pure
bool IsEmpty() const {
#ifdef HAVE_CLASS_GLOB
- return patterns.empty();
+ return ((parent == nullptr) || parent->IsEmpty()) && patterns.empty();
#else
/* not implemented */
return true;
diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx
index af039ee48..3e5654a3c 100644
--- a/src/db/update/Walk.cxx
+++ b/src/db/update/Walk.cxx
@@ -219,6 +219,7 @@ UpdateWalk::UpdateRegularFile(Directory &directory,
void
UpdateWalk::UpdateDirectoryChild(Directory &directory,
+ const ExcludeList &exclude_list,
const char *name, const StorageFileInfo &info)
{
assert(strchr(name, '/') == nullptr);
@@ -236,7 +237,7 @@ UpdateWalk::UpdateDirectoryChild(Directory &directory,
assert(&directory == subdir->parent);
- if (!UpdateDirectory(*subdir, info))
+ if (!UpdateDirectory(*subdir, exclude_list, info))
editor.LockDeleteDirectory(subdir);
} else {
FormatDebug(update_domain,
@@ -327,7 +328,9 @@ UpdateWalk::SkipSymlink(const Directory *directory,
}
bool
-UpdateWalk::UpdateDirectory(Directory &directory, const StorageFileInfo &info)
+UpdateWalk::UpdateDirectory(Directory &directory,
+ const ExcludeList &exclude_list,
+ const StorageFileInfo &info)
{
assert(info.IsDirectory());
@@ -340,17 +343,17 @@ UpdateWalk::UpdateDirectory(Directory &directory, const StorageFileInfo &info)
return false;
}
- ExcludeList exclude_list;
+ ExcludeList child_exclude_list(exclude_list);
{
const auto exclude_path_fs =
storage.MapChildFS(directory.GetPath(), ".mpdignore");
if (!exclude_path_fs.IsNull())
- exclude_list.LoadFile(exclude_path_fs);
+ child_exclude_list.LoadFile(exclude_path_fs);
}
- if (!exclude_list.IsEmpty())
- RemoveExcludedFromDirectory(directory, exclude_list);
+ if (!child_exclude_list.IsEmpty())
+ RemoveExcludedFromDirectory(directory, child_exclude_list);
PurgeDeletedFromDirectory(directory);
@@ -361,7 +364,7 @@ UpdateWalk::UpdateDirectory(Directory &directory, const StorageFileInfo &info)
{
const auto name_fs = AllocatedPath::FromUTF8(name_utf8);
- if (name_fs.IsNull() || exclude_list.Check(name_fs))
+ if (name_fs.IsNull() || child_exclude_list.Check(name_fs))
continue;
}
@@ -376,7 +379,7 @@ UpdateWalk::UpdateDirectory(Directory &directory, const StorageFileInfo &info)
continue;
}
- UpdateDirectoryChild(directory, name_utf8, info2);
+ UpdateDirectoryChild(directory, child_exclude_list, name_utf8, info2);
}
directory.mtime = info.mtime;
@@ -468,7 +471,9 @@ UpdateWalk::UpdateUri(Directory &root, const char *uri)
return;
}
- UpdateDirectoryChild(*parent, name, info);
+ ExcludeList exclude_list;
+
+ UpdateDirectoryChild(*parent, exclude_list, name, info);
}
bool
@@ -484,7 +489,9 @@ UpdateWalk::Walk(Directory &root, const char *path, bool discard)
if (!GetInfo(storage, "", info))
return false;
- UpdateDirectory(root, info);
+ ExcludeList exclude_list;
+
+ UpdateDirectory(root, exclude_list, info);
}
return modified;
diff --git a/src/db/update/Walk.hxx b/src/db/update/Walk.hxx
index d9fe7c84c..99d54ef51 100644
--- a/src/db/update/Walk.hxx
+++ b/src/db/update/Walk.hxx
@@ -129,10 +129,12 @@ private:
const char *name, const StorageFileInfo &info);
void UpdateDirectoryChild(Directory &directory,
+ const ExcludeList &exclude_list,
const char *name,
const StorageFileInfo &info);
bool UpdateDirectory(Directory &directory,
+ const ExcludeList &exclude_list,
const StorageFileInfo &info);
/**