No issues found
1 /*
2 * Copyright (C) 2009, Nokia <ivan.frade@nokia.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <time.h>
24 #include <locale.h>
25
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <gio/gio.h>
29
30 #include <libtracker-sparql/tracker-sparql.h>
31
32 #define ABOUT \
33 "Tracker " PACKAGE_VERSION "\n"
34
35 #define LICENSE \
36 "This program is free software and comes without any warranty.\n" \
37 "It is licensed under version 2 or later of the General Public " \
38 "License which can be viewed at:\n" \
39 "\n" \
40 " http://www.gnu.org/licenses/gpl.txt\n"
41
42 static gint limit = 512;
43 static gint offset;
44 static gchar **files;
45 static gboolean or_operator;
46 static gchar *add_tag;
47 static gchar *remove_tag;
48 static gchar *description;
49 static gboolean *list;
50 static gboolean show_files;
51 static gboolean print_version;
52
53 static GOptionEntry entries[] = {
54 { "limit", 'l', 0, G_OPTION_ARG_INT, &limit,
55 N_("Limit the number of results shown"),
56 N_("512")
57 },
58 { "offset", 'o', 0, G_OPTION_ARG_INT, &offset,
59 N_("Offset the results"),
60 N_("0")
61 },
62 { "or-operator", 'r', 0, G_OPTION_ARG_NONE, &or_operator,
63 N_("Use OR for search terms instead of AND (the default)"),
64 NULL
65 },
66 { "list", 't', 0, G_OPTION_ARG_NONE, &list,
67 N_("List all tags (using FILTER if specified; FILTER always uses logical OR)"),
68 N_("FILTER"),
69 },
70 { "show-files", 's', 0, G_OPTION_ARG_NONE, &show_files,
71 N_("Show files associated with each tag (this is only used with --list)"),
72 NULL
73 },
74 { "add", 'a', 0, G_OPTION_ARG_STRING, &add_tag,
75 N_("Add a tag (if FILEs are omitted, TAG is not associated with any files)"),
76 N_("TAG")
77 },
78 { "delete", 'd', 0, G_OPTION_ARG_STRING, &remove_tag,
79 N_("Delete a tag (if FILEs are omitted, TAG is removed for all files)"),
80 N_("TAG")
81 },
82 { "description", 'e', 0, G_OPTION_ARG_STRING, &description,
83 N_("Description for a tag (this is only used with --add)"),
84 N_("STRING")
85 },
86 { "version", 'V', 0, G_OPTION_ARG_NONE, &print_version,
87 N_("Print version"),
88 NULL
89 },
90 { G_OPTION_REMAINING, 0, 0,
91 G_OPTION_ARG_FILENAME_ARRAY, &files,
92 N_("FILEâŚ"),
93 N_("FILE [FILEâŚ]")},
94 { NULL }
95 };
96
97 static void
98 show_limit_warning (void)
99 {
100 /* Display '...' so the user thinks there is
101 * more items.
102 */
103 g_print (" ...\n");
104
105 /* Display warning so the user knows this is
106 * not the WHOLE data set.
107 */
108 g_printerr ("\n%s\n",
109 _("NOTE: Limit was reached, there are more items in the database not listed here"));
110 }
111
112 static gchar *
113 get_escaped_sparql_string (const gchar *str)
114 {
115 GString *sparql;
116
117 sparql = g_string_new ("");
118 g_string_append_c (sparql, '"');
119
120 while (*str != '\0') {
121 gsize len = strcspn (str, "\t\n\r\"\\");
122 g_string_append_len (sparql, str, len);
123 str += len;
124 switch (*str) {
125 case '\t':
126 g_string_append (sparql, "\\t");
127 break;
128 case '\n':
129 g_string_append (sparql, "\\n");
130 break;
131 case '\r':
132 g_string_append (sparql, "\\r");
133 break;
134 case '"':
135 g_string_append (sparql, "\\\"");
136 break;
137 case '\\':
138 g_string_append (sparql, "\\\\");
139 break;
140 default:
141 continue;
142 }
143 str++;
144 }
145
146 g_string_append_c (sparql, '"');
147
148 return g_string_free (sparql, FALSE);
149 }
150
151 static gchar *
152 get_filter_string (GStrv files,
153 gboolean files_are_urns,
154 const gchar *tag)
155 {
156 GString *filter;
157 gint i, len;
158
159 if (!files) {
160 return NULL;
161 }
162
163 len = g_strv_length (files);
164
165 if (len < 1) {
166 return NULL;
167 }
168
169 filter = g_string_new ("");
170
171 g_string_append_printf (filter, "FILTER (");
172
173 if (tag) {
174 g_string_append (filter, "(");
175 }
176
177 for (i = 0; i < len; i++) {
178 if (files_are_urns) {
179 g_string_append_printf (filter, "?urn = <%s>", files[i]);
180 } else {
181 g_string_append_printf (filter, "?f = \"%s\"", files[i]);
182 }
183
184 if (i < len - 1) {
185 g_string_append (filter, " || ");
186 }
187 }
188
189 if (tag) {
190 g_string_append_printf (filter, ") && ?t = <%s>", tag);
191 }
192
193 g_string_append (filter, ")");
194
195 return g_string_free (filter, FALSE);
196 }
197
198 static GStrv
199 get_uris (GStrv files)
200 {
201 GStrv uris;
202 gint len, i;
203
204 if (!files) {
205 return NULL;
206 }
207
208 len = g_strv_length (files);
209
210 if (len < 1) {
211 return NULL;
212 }
213
214 uris = g_new0 (gchar *, len + 1);
215
216 for (i = 0; files[i]; i++) {
217 GFile *file;
218
219 file = g_file_new_for_commandline_arg (files[i]);
220 uris[i] = g_file_get_uri (file);
221 g_object_unref (file);
222 }
223
224 return uris;
225 }
226
227 static TrackerSparqlCursor *
228 get_file_urns (TrackerSparqlConnection *connection,
229 GStrv uris,
230 const gchar *tag)
231 {
232 TrackerSparqlCursor *cursor;
233 gchar *query, *filter;
234 GError *error = NULL;
235
236 filter = get_filter_string (uris, FALSE, tag);
237 query = g_strdup_printf ("SELECT ?urn ?f "
238 "WHERE { "
239 " ?urn "
240 " %s "
241 " nie:url ?f . "
242 " %s "
243 "}",
244 tag ? "nao:hasTag ?t ; " : "",
245 filter ? filter : "");
246
247 cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
248
249 g_free (query);
250 g_free (filter);
251
252 if (error) {
253 g_print (" %s, %s\n",
254 _("Could not get file URNs"),
255 error->message);
256 g_error_free (error);
257 return NULL;
258 }
259
260 return cursor;
261 }
262
263 static GStrv
264 result_to_strv (TrackerSparqlCursor *cursor,
265 gint n_col)
266 {
267 GStrv strv;
268 gint count, i;
269
270 if (!cursor) {
271 return NULL;
272 }
273
274 i = 0;
275 count = 0;
276
277 /* Really no other option here, but we iterate the cursor
278 * first to get the length.
279 */
280 while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
281 count++;
282 }
283
284 strv = g_new0 (gchar *, count + 1);
285
286 tracker_sparql_cursor_rewind (cursor);
287
288 while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
289 const gchar *str;
290
291 str = tracker_sparql_cursor_get_string (cursor, n_col, NULL);
292 strv[i++] = g_strdup (str);
293 }
294
295 return strv;
296 }
297
298 static void
299 get_all_tags_show_tag_id (TrackerSparqlConnection *connection,
300 const gchar *id)
301 {
302 TrackerSparqlCursor *cursor;
303 GError *error = NULL;
304 gchar *query;
305
306 /* Get files associated */
307 query = g_strdup_printf ("SELECT ?uri WHERE {"
308 " ?urn a rdfs:Resource; "
309 " nie:url ?uri ; "
310 " nao:hasTag \"%s\" . "
311 "}",
312 id);
313
314 cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
315 g_free (query);
316
317 if (error) {
318 g_printerr (" %s, %s\n",
319 _("Could not get files related to tag"),
320 error->message);
321 g_error_free (error);
322 return;
323 }
324
325 if (!cursor) {
326 g_print (" %s\n", _("None"));
327 return;
328 }
329
330
331 while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
332 g_print (" %s\n", tracker_sparql_cursor_get_string (cursor, 0, NULL));
333 }
334
335 g_object_unref (cursor);
336 }
337
338 static gboolean
339 get_all_tags (TrackerSparqlConnection *connection,
340 GStrv files,
341 gint search_offset,
342 gint search_limit,
343 gboolean use_or_operator,
344 gboolean show_files)
345 {
346 TrackerSparqlCursor *cursor;
347 GError *error = NULL;
348 gchar *query;
349
350 if (files && g_strv_length (files) > 0) {
351 gchar *filter;
352
353 /* e.g. '?label IN ("foo", "bar")' */
354 filter = g_strjoinv ("\",\"", files);
355
356 /* You might be asking, why not logical AND here, why
357 * logical OR for FILTER, well, tags can't have
358 * multiple labels is the simple answer.
359 */
360 query = g_strdup_printf ("SELECT ?tag ?label nao:description(?tag) COUNT(?urns) AS urns "
361 "WHERE {"
362 " ?tag a nao:Tag ;"
363 " nao:prefLabel ?label ."
364 " OPTIONAL {"
365 " ?urns nao:hasTag ?tag"
366 " } ."
367 " FILTER (?label IN (\"%s\"))"
368 "} "
369 "GROUP BY ?tag "
370 "ORDER BY ASC(?label) "
371 "OFFSET %d "
372 "LIMIT %d",
373 filter,
374 search_offset,
375 search_limit);
376 g_free (filter);
377 } else {
378 query = g_strdup_printf ("SELECT ?tag ?label nao:description(?tag) COUNT(?urns) AS urns "
379 "WHERE {"
380 " ?tag a nao:Tag ;"
381 " nao:prefLabel ?label ."
382 " OPTIONAL {"
383 " ?urns nao:hasTag ?tag"
384 " }"
385 "} "
386 "GROUP BY ?tag "
387 "ORDER BY ASC(?label) "
388 "OFFSET %d "
389 "LIMIT %d",
390 search_offset,
391 search_limit);
392 }
393
394 cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
395 g_free (query);
396
397 if (error) {
398 g_printerr ("%s, %s\n",
399 _("Could not get all tags"),
400 error->message);
401 g_error_free (error);
402
403 return FALSE;
404 }
405
406 if (!cursor) {
407 g_print ("%s\n",
408 _("No tags were found"));
409 } else {
410 gint count = 0;
411
412 g_print ("%s:\n", _("Tags (shown by name)"));
413
414 while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
415 const gchar *id;
416 const gchar *tag;
417 const gchar *description;
418 const gchar *files;
419 gint n_files = 0;
420
421 id = tracker_sparql_cursor_get_string (cursor, 0, NULL);
422 files = tracker_sparql_cursor_get_string (cursor, 3, NULL);
423 n_files = atoi (files);
424
425 tag = tracker_sparql_cursor_get_string (cursor, 1, NULL);
426 description = tracker_sparql_cursor_get_string (cursor, 2, NULL);
427
428 if (description && *description == '\0') {
429 description = NULL;
430 }
431
432 g_print (" %s %s%s%s\n",
433 tag,
434 description ? "(" : "",
435 description ? description : "",
436 description ? ")" : "");
437
438 if (show_files && n_files > 0) {
439 get_all_tags_show_tag_id (connection, id);
440 } else {
441 g_print (" %s\n", id);
442 g_print (" ");
443 g_print (g_dngettext (NULL,
444 "%d file",
445 "%d files",
446 n_files),
447 n_files);
448 g_print ("\n");
449 }
450
451 count++;
452 }
453
454 if (count == 0) {
455 g_print (" %s\n", _("None"));
456 }
457
458 g_print ("\n");
459
460 if (count >= search_limit) {
461 show_limit_warning ();
462 }
463
464 g_object_unref (cursor);
465 }
466
467 return TRUE;
468 }
469
470 static void
471 print_file_report (TrackerSparqlCursor *cursor,
472 GStrv uris,
473 const gchar *found_msg,
474 const gchar *not_found_msg)
475 {
476 gint i;
477
478 if (!cursor || !uris) {
479 g_print (" %s\n", _("No files were modified"));
480 return;
481 }
482
483 for (i = 0; uris[i]; i++) {
484 gboolean found = FALSE;
485
486 tracker_sparql_cursor_rewind (cursor);
487
488 while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
489 const gchar *str;
490
491 str = tracker_sparql_cursor_get_string (cursor, 1, NULL);
492
493 if (g_strcmp0 (str, uris[i]) == 0) {
494 found = TRUE;
495 break;
496 }
497 }
498
499 g_print (" %s: %s\n",
500 found ? found_msg : not_found_msg,
501 uris[i]);
502 }
503 }
504
505 static gboolean
506 add_tag_for_urns (TrackerSparqlConnection *connection,
507 GStrv files,
508 const gchar *tag,
509 const gchar *description)
510 {
511 TrackerSparqlCursor *cursor = NULL;
512 GError *error = NULL;
513 GStrv uris = NULL, urns_strv = NULL;
514 gchar *tag_escaped;
515 gchar *query;
516
517 tag_escaped = get_escaped_sparql_string (tag);
518
519 if (files) {
520 uris = get_uris (files);
521
522 if (!uris) {
523 return FALSE;
524 }
525
526 cursor = get_file_urns (connection, uris, NULL);
527
528 if (!cursor) {
529 g_printerr ("Files do not exist or aren't indexed\n");
530 g_strfreev (uris);
531 return FALSE;
532 }
533
534 urns_strv = result_to_strv (cursor, 0);
535
536 if (!urns_strv || g_strv_length (urns_strv) < 1) {
537 g_printerr ("Files do not exist or aren't indexed\n");
538 g_object_unref (cursor);
539 g_strfreev (uris);
540
541 return FALSE;
542 }
543 }
544
545 if (description) {
546 gchar *description_escaped;
547
548 description_escaped = get_escaped_sparql_string (description);
549
550 query = g_strdup_printf ("INSERT { "
551 " _:tag a nao:Tag;"
552 " nao:prefLabel %s ;"
553 " nao:description %s ."
554 "} "
555 "WHERE {"
556 " OPTIONAL {"
557 " ?tag a nao:Tag ;"
558 " nao:prefLabel %s ."
559 " } ."
560 " FILTER (!bound(?tag)) "
561 "}",
562 tag_escaped,
563 description_escaped,
564 tag_escaped);
565
566 g_free (description_escaped);
567 } else {
568 query = g_strdup_printf ("INSERT { "
569 " _:tag a nao:Tag;"
570 " nao:prefLabel %s ."
571 "} "
572 "WHERE {"
573 " OPTIONAL {"
574 " ?tag a nao:Tag ;"
575 " nao:prefLabel %s ."
576 " } ."
577 " FILTER (!bound(?tag)) "
578 "}",
579 tag_escaped,
580 tag_escaped);
581 }
582
583 tracker_sparql_connection_update (connection, query, 0, NULL, &error);
584 g_free (query);
585
586 if (error) {
587 g_printerr ("%s, %s\n",
588 _("Could not add tag"),
589 error->message);
590
591 if (cursor) {
592 g_object_unref (cursor);
593 }
594
595 g_error_free (error);
596 g_free (tag_escaped);
597 g_strfreev (urns_strv);
598 g_strfreev (uris);
599
600 return FALSE;
601 }
602
603 g_print ("%s\n",
604 _("Tag was added successfully"));
605
606 /* First we check if the tag is already set and only add if it
607 * is, then we add the urns specified to the new tag.
608 */
609 if (urns_strv) {
610 gchar *filter;
611
612 filter = get_filter_string (urns_strv, TRUE, NULL);
613
614 /* Add tag to specific urns */
615 query = g_strdup_printf ("INSERT { "
616 " ?urn nao:hasTag ?id "
617 "} "
618 "WHERE {"
619 " ?urn nie:url ?f ."
620 " ?id nao:prefLabel %s "
621 " %s "
622 "}",
623 tag_escaped,
624 filter ? filter : "");
625
626 tracker_sparql_connection_update (connection, query, 0, NULL, &error);
627 g_strfreev (urns_strv);
628 g_free (filter);
629 g_free (query);
630
631 if (error) {
632 g_printerr ("%s, %s\n",
633 _("Could not add tag to files"),
634 error->message);
635 g_object_unref (cursor);
636 g_error_free (error);
637 g_free (tag_escaped);
638 g_strfreev (uris);
639
640 return FALSE;
641 }
642
643 print_file_report (cursor, uris, _("Tagged"),
644 _("Not tagged, file is not indexed"));
645 }
646
647 g_strfreev (uris);
648 g_free (tag_escaped);
649
650 if (cursor) {
651 g_object_unref (cursor);
652 }
653
654 return TRUE;
655 }
656
657 static gboolean
658 remove_tag_for_urns (TrackerSparqlConnection *connection,
659 GStrv files,
660 const gchar *tag)
661 {
662 TrackerSparqlCursor *urns_cursor = NULL;
663 GError *error = NULL;
664 gchar *tag_escaped;
665 gchar *query;
666 GStrv uris;
667
668 tag_escaped = get_escaped_sparql_string (tag);
669 uris = get_uris (files);
670
671 if (uris && *uris) {
672 TrackerSparqlCursor *tag_cursor;
673 gchar *filter;
674 const gchar *urn;
675 GStrv urns_strv;
676
677 /* Get all tags urns */
678 query = g_strdup_printf ("SELECT ?tag "
679 "WHERE {"
680 " ?tag a nao:Tag ."
681 " ?tag nao:prefLabel %s "
682 "}",
683 tag_escaped);
684
685 tag_cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
686 g_free (query);
687
688 if (error) {
689 g_printerr ("%s, %s\n",
690 _("Could not get tag by label"),
691 error->message);
692 g_error_free (error);
693 g_free (tag_escaped);
694 g_strfreev (uris);
695
696 return FALSE;
697 }
698
699 if (!tag_cursor || !tracker_sparql_cursor_next (tag_cursor, NULL, NULL)) {
700 g_print ("%s\n",
701 _("No tags were found by that name"));
702
703 g_free (tag_escaped);
704 g_strfreev (uris);
705
706 if (tag_cursor) {
707 g_object_unref (tag_cursor);
708 }
709
710 return TRUE;
711 }
712
713 urn = tracker_sparql_cursor_get_string (tag_cursor, 0, NULL);
714 urns_cursor = get_file_urns (connection, uris, urn);
715
716 if (!urns_cursor || !tracker_sparql_cursor_next (urns_cursor, NULL, NULL)) {
717 g_print ("%s\n",
718 _("None of the files had this tag set"));
719
720 g_strfreev (uris);
721 g_free (tag_escaped);
722 g_object_unref (tag_cursor);
723
724 if (urns_cursor) {
725 g_object_unref (urns_cursor);
726 }
727
728 return TRUE;
729 }
730
731 urns_strv = result_to_strv (urns_cursor, 0);
732 filter = get_filter_string (urns_strv, TRUE, urn);
733 g_strfreev (urns_strv);
734
735 query = g_strdup_printf ("DELETE { "
736 " ?urn nao:hasTag ?t "
737 "} "
738 "WHERE { "
739 " ?urn nao:hasTag ?t . "
740 " %s "
741 "}",
742 filter ? filter : "");
743 g_free (filter);
744
745 g_object_unref (tag_cursor);
746 } else {
747 /* Remove tag completely */
748 query = g_strdup_printf ("DELETE { "
749 " ?tag a nao:Tag "
750 "} "
751 "WHERE {"
752 " ?tag nao:prefLabel %s "
753 "}",
754 tag_escaped);
755 }
756
757 g_free (tag_escaped);
758
759 tracker_sparql_connection_update (connection, query, 0, NULL, &error);
760 g_free (query);
761
762 if (error) {
763 g_printerr ("%s, %s\n",
764 _("Could not remove tag"),
765 error->message);
766 g_error_free (error);
767
768 return FALSE;
769 }
770
771 g_print ("%s\n", _("Tag was removed successfully"));
772
773 if (urns_cursor) {
774 print_file_report (urns_cursor, uris,
775 _("Untagged"),
776 _("File not indexed or already untagged"));
777 g_object_unref (urns_cursor);
778 }
779
780 g_strfreev (uris);
781
782 return TRUE;
783 }
784
785 static gboolean
786 get_tags_by_file (TrackerSparqlConnection *connection,
787 const gchar *uri)
788 {
789 TrackerSparqlCursor *cursor;
790 GError *error = NULL;
791 gchar *query;
792
793 query = g_strdup_printf ("SELECT ?tags ?labels "
794 "WHERE {"
795 " ?urn nao:hasTag ?tags ;"
796 " nie:url <%s> ."
797 " ?tags a nao:Tag ;"
798 " nao:prefLabel ?labels "
799 "} "
800 "ORDER BY ASC(?labels)",
801 uri);
802
803 cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
804 g_free (query);
805
806 if (error) {
807 g_printerr ("%s, %s\n",
808 _("Could not get all tags"),
809 error->message);
810 g_error_free (error);
811
812 return FALSE;
813 }
814
815 if (!cursor) {
816 g_print (" %s\n",
817 _("No tags were found"));
818 } else {
819 gint count = 0;
820
821 while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
822 g_print (" %s\n", tracker_sparql_cursor_get_string (cursor, 1, NULL));
823 count++;
824 }
825
826 if (count == 0) {
827 g_print (" %s\n", _("None"));
828 }
829
830 g_print ("\n");
831
832 g_object_unref (cursor);
833 }
834
835 return TRUE;
836 }
837
838 int
839 main (int argc, char **argv)
840 {
841 TrackerSparqlConnection *connection;
842 GOptionContext *context;
843 GError *error = NULL;
844 const gchar *failed = NULL;
845
846 setlocale (LC_ALL, "");
847
848 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
849 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
850 textdomain (GETTEXT_PACKAGE);
851
852 /* Translators: this messagge will apper immediately after the
853 * usage string - Usage: COMMAND [OPTION]... <THIS_MESSAGE>
854 */
855 context = g_option_context_new (_("Add, remove or list tags"));
856
857 /* Translators: this message will appear after the usage string
858 * and before the list of options, showing an usage example.
859 */
860 g_option_context_add_main_entries (context, entries, NULL);
861 g_option_context_parse (context, &argc, &argv, NULL);
862
863 if (print_version) {
864 g_print ("\n" ABOUT "\n" LICENSE "\n");
865 g_option_context_free (context);
866
867 return EXIT_SUCCESS;
868 }
869
870 if (!list && show_files) {
871 failed = _("The --list option is required for --show-files");
872 } else if (add_tag && remove_tag) {
873 failed = _("Add and delete actions can not be used together");
874 } else if (!list && !add_tag && !remove_tag && !files) {
875 failed = _("No arguments were provided");
876 } else if (description && !add_tag) {
877 failed = _("The --description option can only be used with --add");
878 }
879
880 if (failed) {
881 gchar *help;
882
883 g_printerr ("%s\n\n", failed);
884
885 help = g_option_context_get_help (context, TRUE, NULL);
886 g_option_context_free (context);
887 g_printerr ("%s", help);
888 g_free (help);
889
890 return EXIT_FAILURE;
891 }
892
893 g_option_context_free (context);
894
895 connection = tracker_sparql_connection_get (NULL, &error);
896
897 if (!connection) {
898 g_printerr ("%s: %s\n",
899 _("Could not establish a connection to Tracker"),
900 error ? error->message : _("No error given"));
901 g_clear_error (&error);
902 return EXIT_FAILURE;
903 }
904
905 if (list) {
906 gboolean success;
907
908 success = get_all_tags (connection, files, offset, limit, or_operator, show_files);
909 g_object_unref (connection);
910
911 return success ? EXIT_SUCCESS : EXIT_FAILURE;
912 }
913
914 if (add_tag) {
915 gboolean success;
916
917 success = add_tag_for_urns (connection, files, add_tag, description);
918 g_object_unref (connection);
919
920 return success ? EXIT_SUCCESS : EXIT_FAILURE;
921 }
922
923 if (remove_tag) {
924 gboolean success;
925
926 success = remove_tag_for_urns (connection, files, remove_tag);
927 g_object_unref (connection);
928
929 return success ? EXIT_SUCCESS : EXIT_FAILURE;
930 }
931
932 if (files) {
933 gboolean success = TRUE;
934 gchar **p;
935
936 for (p = files; *p; p++) {
937 GFile *file;
938 gchar *uri;
939
940 file = g_file_new_for_commandline_arg (*p);
941 uri = g_file_get_uri (file);
942 g_object_unref (file);
943
944 g_print ("%s\n", uri);
945 success &= get_tags_by_file (connection, uri);
946
947 g_free (uri);
948 }
949
950 g_object_unref (connection);
951
952 return success ? EXIT_SUCCESS : EXIT_FAILURE;
953 }
954
955 g_object_unref (connection);
956
957 /* This is a failure because we should have done something.
958 * This code should never be reached in practise.
959 */
960 return EXIT_FAILURE;
961 }