ghee_cli/
lib.rs

1use std::path::PathBuf;
2
3use clap::{builder::ValueParser, Parser, Subcommand};
4use thiserror::Error;
5
6use ghee_lang::{Assignment, AssignmentParser, Predicate, PredicateParser, Value, Xattr};
7
8#[derive(Parser)]
9#[command(author, version, about, long_about = None)]
10#[command(propagate_version = true)]
11pub struct Cli {
12    /// Subcommand to run. If none is provided, a REPL will be launched
13    #[command(subcommand)]
14    pub command: Option<Commands>,
15}
16
17#[derive(Error, Debug)]
18pub enum TableOpenErr {
19    #[error("Table path could not be opened because it doesn't exist")]
20    NoSuchPath,
21}
22
23#[derive(Subcommand)]
24pub enum Commands {
25    /// Copy xattr values from one path to another.
26    Cp {
27        #[arg(help = "Path to copy xattrs from")]
28        src: PathBuf,
29        #[arg(help = "Path to copy xattrs to")]
30        dest: PathBuf,
31        #[arg(name = "field", short, long, help = "xattrs to copy")]
32        fields: Vec<Xattr>,
33        #[arg(short, long)]
34        verbose: bool,
35    },
36    /// Move xattr values from one path to another.
37    Mv {
38        #[arg(help = "Path to move xattrs from")]
39        src: PathBuf,
40        #[arg(help = "Path to move xattrs to")]
41        dest: PathBuf,
42        #[arg(name = "field", short, long, help = "xattrs to move")]
43        fields: Vec<Xattr>,
44        #[arg(short, long)]
45        verbose: bool,
46    },
47    /// Remove xattr values.
48    Rm {
49        #[arg(name = "path", help = "Paths to remove xattrs from", required = true)]
50        paths: Vec<PathBuf>,
51        #[arg(name = "field", short, long, help = "xattrs to remove")]
52        fields: Vec<Xattr>,
53        #[arg(long, help = "Process paths nonrecursively; defaults to false")]
54        flat: bool,
55        #[arg(
56            long,
57            help = "Don't complain when an xattr doesn't exist; defaults to false"
58        )]
59        force: bool,
60        #[arg(short, long)]
61        verbose: bool,
62    },
63
64    /// Get and print xattr values for one or more paths.
65    Get {
66        #[arg(name = "path", help = "Paths to get xattrs from", required = true)]
67        paths: Vec<PathBuf>,
68        #[arg(name = "field", short, long, help = "xattrs to get")]
69        fields: Vec<Xattr>,
70        #[arg(short, long, help = "Output JSON; lossily decodes as UTF-8")]
71        json: bool,
72        #[arg(name = "where", short, long, help = "WHERE clause to filter results by", value_parser = ValueParser::new(PredicateParser{}))]
73        where_: Vec<Predicate>,
74        #[arg(long, help = "Process paths nonrecursively; defaults to false")]
75        flat: bool,
76        #[arg(short, long, help = "Include user.ghee prefix in output")]
77        all: bool,
78        #[arg(
79            short,
80            long,
81            help = "Sort directory contents as paths are walked; disable for potential speedup on large listings",
82            default_value_t = true
83        )]
84        sort: bool,
85        #[arg(short, long, help = "Return records even when apparently empty")]
86        visit_empty: bool,
87    },
88
89    /// Set xattr values
90    Set {
91        #[arg(name = "paths", help = "Paths to set xattrs on", required = true)]
92        paths: Vec<PathBuf>,
93        #[arg(name = "set", short, long, help = "k=v pairs to set", value_parser = ValueParser::new(AssignmentParser{}))]
94        field_assignments: Vec<Assignment>,
95        #[arg(long, help = "Process paths nonrecursively; defaults to false")]
96        flat: bool,
97        #[arg(short, long)]
98        verbose: bool,
99    },
100
101    /// Insert records into a table, updating related indices
102    Ins {
103        #[arg(help = "Path of the table to insert into")]
104        table_path: PathBuf,
105        #[arg(
106            help = "Path of the records, JSON, one record per line; if omitted, the same format is taken from stdin"
107        )]
108        records_path: Option<PathBuf>,
109        #[arg(short, long)]
110        verbose: bool,
111    },
112
113    /// Remove record from a table, updating related indices
114    Del {
115        #[arg(help = "Path of the table to delete from")]
116        table_path: PathBuf,
117        #[arg(name = "where", short, long, help = "WHERE clauses specifying what to delete", value_parser = ValueParser::new(PredicateParser{}))]
118        where_: Vec<Predicate>,
119        #[arg(help = "Primary key values, subkeys space separated")]
120        key: Vec<Value>,
121        #[arg(short, long)]
122        verbose: bool,
123    },
124
125    /// Index tables
126    Idx {
127        #[arg(help = "Path to recursively index")]
128        src: PathBuf,
129        #[arg(help = "Path to output the new index to")]
130        dest: Option<PathBuf>,
131        #[arg(name = "key", short, long, help = "xattrs to index by")]
132        keys: Vec<Xattr>,
133        #[arg(short, long)]
134        verbose: bool,
135    },
136
137    /// List directory contents as seen by Ghee
138    Ls {
139        #[arg(help = "Paths to list the contents of; current directory by default")]
140        paths: Vec<PathBuf>,
141
142        #[arg(
143            short,
144            long,
145            help = "Sort directory contents; disable for potential speedup on large listings",
146            default_value_t = true
147        )]
148        sort: bool,
149    },
150
151    /// Initialize a directory as a Ghee table with specified primary key, then optionally insert records
152    Init {
153        #[arg(help = "Directory to initialize as a Ghee table")]
154        dir: PathBuf,
155
156        #[arg(
157            name = "key",
158            short,
159            long,
160            help = "xattrs the table will be indexed by"
161        )]
162        keys: Vec<Xattr>,
163
164        #[arg(
165            help = "Path of the records to insert, JSON, one record per line; if omitted, the same format is taken from stdin"
166        )]
167        records_path: Option<PathBuf>,
168
169        #[arg(short, long)]
170        verbose: bool,
171    },
172
173    /// Like `init`, but creates the directory first, or errors if one exists already
174    Create {
175        #[arg(help = "Directory to create and initialize as a Ghee table")]
176        dir: PathBuf,
177
178        #[arg(
179            name = "key",
180            short,
181            long,
182            help = "xattrs the table will be indexed by"
183        )]
184        keys: Vec<Xattr>,
185
186        #[arg(
187            help = "Path of the records to insert, JSON, one record per line; if omitted, the same format is taken from stdin"
188        )]
189        records_path: Option<PathBuf>,
190
191        #[arg(short, long)]
192        verbose: bool,
193    },
194
195    /// Commit a table, storing its contents as a BTRFS snapshot
196    Commit {
197        #[arg(help = "Directory of the table to commit, or the current directory by default")]
198        dir: Option<PathBuf>,
199
200        #[arg(short, long, help = "A message describing the changes being committed")]
201        message: Option<String>,
202
203        #[arg(short, long)]
204        verbose: bool,
205    },
206
207    /// Print the commit log
208    Log {
209        #[arg(
210            help = "Directory of the table whose log to print, or the current directory by default"
211        )]
212        dir: Option<PathBuf>,
213    },
214
215    /// Create a file, inferring xattrs from path if part of a table
216    Touch {
217        #[arg(help = "Path at which to create the file")]
218        path: PathBuf,
219        #[arg(short, long, help = "Create parent directories")]
220        parents: bool,
221    },
222
223    /// Print the status of files in the table, relative to the most recent commit (if any)
224    Status {
225        #[arg(
226            help = "Path of a file in a table; the whole table's status will be listed; defaults to the current directory"
227        )]
228        path: Option<PathBuf>,
229    },
230
231    /// Return a path to its state as of the commit with uuid specified in `commit`
232    Restore {
233        #[arg(help = "Paths to restore", required = true)]
234        paths: Vec<PathBuf>,
235
236        #[arg(
237            short,
238            long,
239            help = "Keep paths not present in most recent commit; defaults to false",
240            default_value_t = false
241        )]
242        keep: bool,
243
244        #[arg(long, help = "Process paths nonrecursively; defaults to false")]
245        flat: bool,
246
247        #[arg(short, long)]
248        verbose: bool,
249    },
250
251    /// Return the current table to the state it had in the commit with the given uuid `commit`
252    Reset {
253        #[arg(help = "UUID of the commit to reset to", required = true)]
254        commit_uuid: String,
255
256        #[arg(
257            short,
258            long,
259            help = "Keep paths not present in commit; defaults to false",
260            default_value_t = false
261        )]
262        keep: bool,
263
264        #[arg(short, long)]
265        verbose: bool,
266    },
267}