command: added command "rescan"
"rescan" is the same as "update", but it discards existing songs in the database.
This commit is contained in:
parent
47ab2ad6f3
commit
89ba540e6d
@ -1245,6 +1245,20 @@ OK
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry id="command_rescan">
|
||||||
|
<term>
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>rescan</command>
|
||||||
|
<arg choice="opt"><replaceable>URI</replaceable></arg>
|
||||||
|
</cmdsynopsis>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Same as <command>update</command>, but also rescans
|
||||||
|
unmodified files.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@ -1025,7 +1025,28 @@ handle_update(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
|
|||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
path = argv[1];
|
path = argv[1];
|
||||||
|
|
||||||
ret = update_enqueue(path);
|
ret = update_enqueue(path, false);
|
||||||
|
if (ret > 0) {
|
||||||
|
client_printf(client, "updating_db: %i\n", ret);
|
||||||
|
return COMMAND_RETURN_OK;
|
||||||
|
} else {
|
||||||
|
command_error(client, ACK_ERROR_UPDATE_ALREADY,
|
||||||
|
"already updating");
|
||||||
|
return COMMAND_RETURN_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum command_return
|
||||||
|
handle_rescan(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const char *path = NULL;
|
||||||
|
unsigned ret;
|
||||||
|
|
||||||
|
assert(argc <= 2);
|
||||||
|
if (argc == 2)
|
||||||
|
path = argv[1];
|
||||||
|
|
||||||
|
ret = update_enqueue(path, true);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
client_printf(client, "updating_db: %i\n", ret);
|
client_printf(client, "updating_db: %i\n", ret);
|
||||||
return COMMAND_RETURN_OK;
|
return COMMAND_RETURN_OK;
|
||||||
@ -1731,6 +1752,7 @@ static const struct command commands[] = {
|
|||||||
{ "random", PERMISSION_CONTROL, 1, 1, handle_random },
|
{ "random", PERMISSION_CONTROL, 1, 1, handle_random },
|
||||||
{ "rename", PERMISSION_CONTROL, 2, 2, handle_rename },
|
{ "rename", PERMISSION_CONTROL, 2, 2, handle_rename },
|
||||||
{ "repeat", PERMISSION_CONTROL, 1, 1, handle_repeat },
|
{ "repeat", PERMISSION_CONTROL, 1, 1, handle_repeat },
|
||||||
|
{ "rescan", PERMISSION_ADMIN, 0, 1, handle_rescan },
|
||||||
{ "rm", PERMISSION_CONTROL, 1, 1, handle_rm },
|
{ "rm", PERMISSION_CONTROL, 1, 1, handle_rm },
|
||||||
{ "save", PERMISSION_CONTROL, 1, 1, handle_save },
|
{ "save", PERMISSION_CONTROL, 1, 1, handle_save },
|
||||||
{ "search", PERMISSION_READ, 2, -1, handle_search },
|
{ "search", PERMISSION_READ, 2, -1, handle_search },
|
||||||
|
@ -362,7 +362,7 @@ int main(int argc, char *argv[])
|
|||||||
if (create_db) {
|
if (create_db) {
|
||||||
/* the database failed to load: recreate the
|
/* the database failed to load: recreate the
|
||||||
database */
|
database */
|
||||||
unsigned job = update_enqueue(NULL);
|
unsigned job = update_enqueue(NULL, true);
|
||||||
if (job == 0)
|
if (job == 0)
|
||||||
g_error("directory update failed");
|
g_error("directory update failed");
|
||||||
}
|
}
|
||||||
|
12
src/update.c
12
src/update.c
@ -52,6 +52,9 @@ static unsigned update_task_id;
|
|||||||
/** used by the main thread to notify the update thread */
|
/** used by the main thread to notify the update thread */
|
||||||
struct notify update_notify;
|
struct notify update_notify;
|
||||||
|
|
||||||
|
/* XXX this flag is passed to update_task() */
|
||||||
|
static bool discard;
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
isUpdatingDB(void)
|
isUpdatingDB(void)
|
||||||
{
|
{
|
||||||
@ -62,7 +65,7 @@ static void * update_task(void *_path)
|
|||||||
{
|
{
|
||||||
const char *path = _path;
|
const char *path = _path;
|
||||||
|
|
||||||
modified = update_walk(path);
|
modified = update_walk(path, discard);
|
||||||
g_free(_path);
|
g_free(_path);
|
||||||
|
|
||||||
if (modified || !db_exists())
|
if (modified || !db_exists())
|
||||||
@ -93,7 +96,7 @@ spawn_update_task(const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
update_enqueue(const char *path)
|
update_enqueue(const char *path, bool _discard)
|
||||||
{
|
{
|
||||||
assert(g_thread_self() == main_task);
|
assert(g_thread_self() == main_task);
|
||||||
|
|
||||||
@ -102,13 +105,14 @@ update_enqueue(const char *path)
|
|||||||
|
|
||||||
if (progress != UPDATE_PROGRESS_IDLE) {
|
if (progress != UPDATE_PROGRESS_IDLE) {
|
||||||
unsigned next_task_id =
|
unsigned next_task_id =
|
||||||
update_queue_push(path, update_task_id);
|
update_queue_push(path, discard, update_task_id);
|
||||||
if (next_task_id == 0)
|
if (next_task_id == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return next_task_id > update_task_id_max ? 1 : next_task_id;
|
return next_task_id > update_task_id_max ? 1 : next_task_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
discard = _discard;
|
||||||
spawn_update_task(path);
|
spawn_update_task(path);
|
||||||
|
|
||||||
idle_add(IDLE_UPDATE);
|
idle_add(IDLE_UPDATE);
|
||||||
@ -135,7 +139,7 @@ static void update_finished_event(void)
|
|||||||
idle_add(IDLE_DATABASE);
|
idle_add(IDLE_DATABASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
path = update_queue_shift();
|
path = update_queue_shift(&discard);
|
||||||
if (path != NULL) {
|
if (path != NULL) {
|
||||||
/* schedule the next path */
|
/* schedule the next path */
|
||||||
spawn_update_task(path);
|
spawn_update_task(path);
|
||||||
|
@ -35,6 +35,6 @@ isUpdatingDB(void);
|
|||||||
* @return the job id, or 0 on error
|
* @return the job id, or 0 on error
|
||||||
*/
|
*/
|
||||||
unsigned
|
unsigned
|
||||||
update_enqueue(const char *path);
|
update_enqueue(const char *path, bool discard);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,10 +33,10 @@ struct directory;
|
|||||||
extern struct notify update_notify;
|
extern struct notify update_notify;
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
update_queue_push(const char *path, unsigned base);
|
update_queue_push(const char *path, bool discard, unsigned base);
|
||||||
|
|
||||||
char *
|
char *
|
||||||
update_queue_shift(void);
|
update_queue_shift(bool *discard_r);
|
||||||
|
|
||||||
void
|
void
|
||||||
update_walk_global_init(void);
|
update_walk_global_init(void);
|
||||||
@ -48,7 +48,7 @@ update_walk_global_finish(void);
|
|||||||
* Returns true if the database was modified.
|
* Returns true if the database was modified.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
update_walk(const char *path);
|
update_walk(const char *path, bool discard);
|
||||||
|
|
||||||
void
|
void
|
||||||
update_remove_global_init(void);
|
update_remove_global_init(void);
|
||||||
|
@ -25,31 +25,41 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* make this dynamic?, or maybe this is big enough... */
|
/* make this dynamic?, or maybe this is big enough... */
|
||||||
static char *update_paths[32];
|
static struct {
|
||||||
static size_t update_paths_nr;
|
char *path;
|
||||||
|
bool discard;
|
||||||
|
} update_queue[32];
|
||||||
|
|
||||||
|
static size_t update_queue_length;
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
update_queue_push(const char *path, unsigned base)
|
update_queue_push(const char *path, bool discard, unsigned base)
|
||||||
{
|
{
|
||||||
assert(update_paths_nr <= G_N_ELEMENTS(update_paths));
|
assert(update_queue_length <= G_N_ELEMENTS(update_queue));
|
||||||
|
|
||||||
if (update_paths_nr == G_N_ELEMENTS(update_paths))
|
if (update_queue_length == G_N_ELEMENTS(update_queue))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
update_paths[update_paths_nr++] = g_strdup(path);
|
update_queue[update_queue_length].path = g_strdup(path);
|
||||||
return base + update_paths_nr;
|
update_queue[update_queue_length].discard = discard;
|
||||||
|
|
||||||
|
++update_queue_length;
|
||||||
|
|
||||||
|
return base + update_queue_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
update_queue_shift(void)
|
update_queue_shift(bool *discard_r)
|
||||||
{
|
{
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
if (update_paths_nr == 0)
|
if (update_queue_length == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
path = update_paths[0];
|
path = update_queue[0].path;
|
||||||
memmove(&update_paths[0], &update_paths[1],
|
*discard_r = update_queue[0].discard;
|
||||||
--update_paths_nr * sizeof(char *));
|
|
||||||
|
memmove(&update_queue[0], &update_queue[1],
|
||||||
|
--update_queue_length * sizeof(update_queue[0]));
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
static bool walk_discard;
|
||||||
static bool modified;
|
static bool modified;
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
@ -350,7 +351,8 @@ update_archive_file(struct directory *parent, const char *name,
|
|||||||
char *filepath;
|
char *filepath;
|
||||||
|
|
||||||
directory = dirvec_find(&parent->children, name);
|
directory = dirvec_find(&parent->children, name);
|
||||||
if (directory != NULL && directory->mtime == st->st_mtime)
|
if (directory != NULL && directory->mtime == st->st_mtime &&
|
||||||
|
!walk_discard)
|
||||||
/* MPD has already scanned the archive, and it hasn't
|
/* MPD has already scanned the archive, and it hasn't
|
||||||
changed since - don't consider updating it */
|
changed since - don't consider updating it */
|
||||||
return;
|
return;
|
||||||
@ -405,7 +407,7 @@ update_container_file( struct directory* directory,
|
|||||||
if (contdir != NULL)
|
if (contdir != NULL)
|
||||||
{
|
{
|
||||||
// modification time not eq. file mod. time
|
// modification time not eq. file mod. time
|
||||||
if (contdir->mtime != st->st_mtime)
|
if (contdir->mtime != st->st_mtime || walk_discard)
|
||||||
{
|
{
|
||||||
g_message("removing container file: %s", pathname);
|
g_message("removing container file: %s", pathname);
|
||||||
|
|
||||||
@ -470,7 +472,8 @@ update_regular_file(struct directory *directory,
|
|||||||
{
|
{
|
||||||
struct song* song = songvec_find(&directory->songs, name);
|
struct song* song = songvec_find(&directory->songs, name);
|
||||||
|
|
||||||
if (!(song != NULL && st->st_mtime == song->mtime) &&
|
if (!(song != NULL && st->st_mtime == song->mtime &&
|
||||||
|
!walk_discard) &&
|
||||||
plugin->container_scan != NULL)
|
plugin->container_scan != NULL)
|
||||||
{
|
{
|
||||||
if (update_container_file(directory, name, st, plugin))
|
if (update_container_file(directory, name, st, plugin))
|
||||||
@ -491,7 +494,7 @@ update_regular_file(struct directory *directory,
|
|||||||
modified = true;
|
modified = true;
|
||||||
g_message("added %s/%s",
|
g_message("added %s/%s",
|
||||||
directory_get_path(directory), name);
|
directory_get_path(directory), name);
|
||||||
} else if (st->st_mtime != song->mtime) {
|
} else if (st->st_mtime != song->mtime || walk_discard) {
|
||||||
g_message("updating %s/%s",
|
g_message("updating %s/%s",
|
||||||
directory_get_path(directory), name);
|
directory_get_path(directory), name);
|
||||||
if (!song_file_update(song))
|
if (!song_file_update(song))
|
||||||
@ -737,8 +740,9 @@ updatePath(const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
update_walk(const char *path)
|
update_walk(const char *path, bool discard)
|
||||||
{
|
{
|
||||||
|
walk_discard = discard;
|
||||||
modified = false;
|
modified = false;
|
||||||
|
|
||||||
if (path != NULL && !isRootDirectory(path)) {
|
if (path != NULL && !isRootDirectory(path)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user