commit 777bd77b64b4ca9c5e38c9cb5971a62684215f2a
parent e883c2678838f60970d7e1008635cda28472cb28
Author: Louis Burda <quent.burda@gmail.com>
Date: Sat, 28 Jan 2023 15:51:20 +0100
If trash tag exists, move tracks there on delete
Diffstat:
M | src/cmd.c | | | 80 | +++++++++++++++++++++++++------------------------------------------------------ |
M | src/data.c | | | 75 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
M | src/data.h | | | 4 | ++++ |
M | src/tui.c | | | 10 | ++++++++-- |
4 files changed, 99 insertions(+), 70 deletions(-)
diff --git a/src/cmd.c b/src/cmd.c
@@ -7,12 +7,16 @@
#include "tui.h"
#include "util.h"
+#include <asm-generic/errno-base.h>
+#include <errno.h>
#include <stdbool.h>
#include <string.h>
static const struct cmd *last_cmd;
static char *last_args;
+static void cmd_status_from_errno(int err);
+
static bool cmd_save(const char *args);
static bool cmd_move(const char *args);
static bool cmd_copy(const char *args);
@@ -33,6 +37,17 @@ const struct cmd commands[] = {
const size_t command_count = ARRLEN(commands);
+void
+cmd_status_from_errno(int err)
+{
+ if (err == EACCES || err == EPERM)
+ CMD_SET_STATUS("Missing permissions");
+ else if (err == EEXIST)
+ CMD_SET_STATUS("Path already exists");
+ else
+ CMD_SET_STATUS("Unknown error");
+}
+
bool
cmd_save(const char *args)
{
@@ -44,9 +59,8 @@ bool
cmd_move(const char *name)
{
struct link *link;
- struct track *track, *new;
+ struct track *track;
struct tag *tag;
- char *newpath;
tag = tag_find(name);
if (!tag) {
@@ -66,33 +80,8 @@ cmd_move(const char *name)
return false;
}
- newpath = aprintf("%s/%s", tag->fpath, track->name);
- if (path_exists(newpath)) {
- free(newpath);
- CMD_SET_STATUS("File already exists");
- return false;
- }
-
- if (!dup_file(track->fpath, newpath)) {
- free(newpath);
- CMD_SET_STATUS("Failed to move track");
- return false;
- }
-
- free(newpath);
-
- new = track_add(tag, track->name);
- if (!new) {
- track_rm(new, true);
- CMD_SET_STATUS("Failed to move track");
- return false;
- }
-
- if (player.track == track)
- player.track = new;
-
- if (!track_rm(track, true)) {
- CMD_SET_STATUS("Failed to move track");
+ if (!track_move(track, tag)) {
+ cmd_status_from_errno(errno);
return false;
}
@@ -229,31 +218,17 @@ cleanup:
bool
cmd_add_tag(const char *name)
{
- struct link *link;
struct tag *tag;
- char *fpath;
- for (LIST_ITER(&tags, link)) {
- tag = UPCAST(link, struct tag, link);
- if (!strcmp(tag->name, name)) {
- CMD_SET_STATUS("Tag already exists");
- return false;
- }
- }
-
- fpath = aprintf("%s/%s", datadir, name);
-
- if (!make_dir(fpath)) {
- free(fpath);
- CMD_SET_STATUS("Failed to create dir");
+ tag = tag_find(name);
+ if (tag) {
+ CMD_SET_STATUS("Tag already exists");
return false;
}
- free(fpath);
-
- tag = tag_add(name);
+ tag = tag_create(name);
if (!tag) {
- CMD_SET_STATUS("Failed to add tag");
+ CMD_SET_STATUS("Failed to create tag");
return false;
}
@@ -271,13 +246,8 @@ cmd_rm_tag(const char *name)
if (!link) return false;
tag = UPCAST(link, struct tag, link);
} else {
- for (LIST_ITER(&tags, link)) {
- tag = UPCAST(link, struct tag, link);
- if (!strcmp(tag->name, name))
- break;
- }
-
- if (!LIST_INNER(link)) {
+ tag = tag_find(name);
+ if (!tag) {
CMD_SET_STATUS("No such tag");
return false;
}
diff --git a/src/data.c b/src/data.c
@@ -6,6 +6,7 @@
#include "log.h"
#include <fts.h>
+#include <errno.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -18,6 +19,8 @@ struct list tracks; /* struct track (link) */
struct list tags; /* struct track (link) */
struct list tags_sel; /* struct tag (link_sel) */
+struct tag *trash_tag;
+
bool playlist_outdated;
static struct tag *tag_alloc(const char *path, const char *fname);
@@ -25,7 +28,6 @@ static void tag_free(struct tag *tag);
static struct track *track_alloc(const char *path, const char *fname);
static void track_free(struct track *t);
-static int track_name_compare(struct link *a, struct link *b);
static void tracks_load(struct tag *tag);
static void tracks_save(struct tag *tag);
@@ -85,17 +87,6 @@ track_free(struct track *t)
free(t);
}
-int
-track_name_compare(struct link *a, struct link *b)
-{
- struct track *ta, *tb;
-
- ta = UPCAST(a, struct track, link);
- tb = UPCAST(b, struct track, link);
-
- return strcmp(ta->name, tb->name);
-}
-
void
tracks_load(struct tag *tag)
{
@@ -379,12 +370,34 @@ playlist_update(void)
}
struct tag *
+tag_create(const char *fname)
+{
+ struct tag *tag;
+ char *path;
+
+ path = aprintf("%s/%s", datadir, fname);
+ if (!make_dir(path)) {
+ free(path);
+ return NULL;
+ }
+ free(path);
+
+ tag = tag_add(fname);
+ if (!tag) {
+ rm_dir(path, false);
+ return NULL;
+ }
+
+ return tag;
+}
+
+struct tag *
tag_add(const char *fname)
{
struct tag *tag;
- /* add to tags list */
tag = tag_alloc(datadir, fname);
+ if (!tag) return NULL;
list_push_back(&tags, &tag->link);
return tag;
@@ -547,6 +560,39 @@ track_rename(struct track *track, const char *name)
}
bool
+track_move(struct track *track, struct tag *tag)
+{
+ struct track *new;
+ char *newpath;
+
+ newpath = aprintf("%s/%s", tag->fpath, track->name);
+ if (path_exists(newpath)) {
+ free(newpath);
+ return false;
+ }
+
+ if (!dup_file(track->fpath, newpath)) {
+ free(newpath);
+ return false;
+ }
+
+ free(newpath);
+
+ new = track_add(tag, track->name);
+ if (!new) return false;
+
+ if (player.track == track)
+ player.track = new;
+
+ if (!track_rm(track, true)) {
+ track_rm(new, true);
+ return false;
+ }
+
+ return true;
+}
+
+bool
acquire_lock(const char *datadir)
{
char *lockpath, *procpath;
@@ -623,6 +669,7 @@ data_load(void)
dir = opendir(datadir);
if (!dir) ERROR(SYSTEM, "opendir %s", datadir);
+ trash_tag = NULL;
while ((ent = readdir(dir))) {
if (!strcmp(ent->d_name, "."))
continue;
@@ -632,6 +679,8 @@ data_load(void)
path = aprintf("%s/%s", datadir, ent->d_name);
if (!stat(path, &st) && S_ISDIR(st.st_mode)) {
tag = tag_add(ent->d_name);
+ if (!strcmp(tag->name, "trash"))
+ trash_tag = tag;
tracks_load(tag);
}
free(path);
diff --git a/src/data.h b/src/data.h
@@ -41,6 +41,7 @@ struct track *tracks_vis_track(struct link *link);
void playlist_clear(void);
void playlist_update(void);
+struct tag *tag_create(const char *fname);
struct tag *tag_add(const char *fname);
struct tag *tag_find(const char *name);
bool tag_rm(struct tag *tag, bool sync_fs);
@@ -49,6 +50,7 @@ bool tag_rename(struct tag *tag, const char *name);
struct track *track_add(struct tag *tag, const char *fname);
bool track_rm(struct track *track, bool sync_fs);
bool track_rename(struct track *track, const char *name);
+bool track_move(struct track *track, struct tag *tag);
bool acquire_lock(const char *path);
bool release_lock(const char *path);
@@ -63,4 +65,6 @@ extern struct list tracks; /* struct track (link) */
extern struct list tags; /* struct track (link) */
extern struct list tags_sel; /* struct tag (link_sel) */
+extern struct tag *trash_tag;
+
extern bool playlist_outdated;
diff --git a/src/tui.c b/src/tui.c
@@ -551,8 +551,14 @@ delete_selected_track(void)
if (!link) return false;
track = tracks_vis_track(link);
- if (!track_rm(track, true))
- CMD_SET_STATUS("Failed to remove track");
+
+ if (!trash_tag || !strcmp(track->tag->name, "trash")) {
+ if (!track_rm(track, true))
+ CMD_SET_STATUS("Failed to remove track");
+ } else {
+ if (!track_move(track, trash_tag))
+ CMD_SET_STATUS("Failed to trash track");
+ }
return true;
}