1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
// Copyright © 2020 Jakob L. Kreuze <zerodaysfordays@sdf.org>
//
// This file is part of Kona.
//
// Kona is free software; you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License as published by
// the Free Software Foundation; either version 3 of the License, or (at
// your option) any later version.
//
// Kona 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 Affero General Public
// License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with Kona. If not, see <http://www.gnu.org/licenses/>.
use std::env;
use std::path::Path;
use kona::TagDatabase;
fn main() {
let mut args: Vec<String> = env::args().collect();
if args.len() < 2 || args.iter().any(|arg| arg == "-h" || arg == "--help") {
println!("usage: {} ACTION [ARGS ...]", args[0]);
println!();
println!("\t-o, --output [PATH]: Path to the tag database.");
println!();
println!("\tACTION: add [PATH] [TAGS ...]: index an image, optionally tagged.");
println!("\tACTION: remove [PATH]: remove an image from the database.");
println!("\tACTION: add_tags [PATH] [TAGS ...]: add tags to an indexed image.");
println!("\tACTION: remove_tags [PATH] [TAGS ...]: remove tags from an indexed image.");
println!("\tACTION: query [QUERY_STRING]: list images in the database.");
std::process::exit(1);
}
let tb = if let Some(i) = args.iter().position(|x| x == "-o" || x == "--output") {
// Ensure that a path follows the "-o" argument.
if i + 1 >= args.len() {
eprintln!("{} requires an argument", args[i]);
std::process::exit(1);
}
args.remove(i);
TagDatabase::new(args.remove(i))
} else if let Ok(path) = std::env::var("TB_PATH") {
TagDatabase::new(path)
} else {
TagDatabase::new("./kona.db")
}
.unwrap();
let action = &args[1];
match action.to_lowercase().as_str() {
"add" => {
if args.len() < 3 {
eprintln!("usage: {} add PATH [TAGS ...]", args[0]);
std::process::exit(1);
}
let path = Path::new(&args[2]).canonicalize().unwrap();
if path.is_dir() {
eprintln!("'{}' is a directory", args[2]);
}
tb.add_file(&path, &args[3..].to_vec()).unwrap();
}
"remove" => {
if args.len() < 3 {
eprintln!("usage: {} remove PATH", args[0]);
std::process::exit(1);
}
let file = tb.file_by_path(&args[2]).unwrap();
tb.remove_file(file.id).unwrap();
}
"add_tags" => {
if args.len() < 3 {
eprintln!("usage: {} add_tags PATH [TAGS ...]", args[0]);
std::process::exit(1);
}
let file = tb.file_by_path(&args[2]).unwrap();
tb.tag_file(file.id, &args[3..].to_vec()).unwrap();
}
"remove_tags" => {
if args.len() < 3 {
eprintln!("usage: {} remove_tags PATH [TAGS ...]", args[0]);
std::process::exit(1);
}
let file = tb.file_by_path(&args[2]).unwrap();
tb.untag_file(file.id, &args[3..].to_vec()).unwrap();
}
"query" => {
let query = if args.len() < 3 {
kona::parse_query("").unwrap()
} else {
kona::parse_query(&args[2]).unwrap()
};
for file in tb.query(&query, None).unwrap() {
println!("{}", file.path);
}
}
"tags" => {
for (count, tag) in tb.top_tags(None).unwrap() {
println!("{}: {}", count, tag);
}
}
_ => {
eprintln!("Unknown action '{}'", action);
std::process::exit(1);
}
}
}
|