add self-import to merge multiple zoxide databases
This commit is contained in:
parent
1d64ae0b87
commit
4cbab9b812
|
|
@ -94,7 +94,7 @@ esac
|
||||||
;;
|
;;
|
||||||
(import)
|
(import)
|
||||||
_arguments "${_arguments_options[@]}" \
|
_arguments "${_arguments_options[@]}" \
|
||||||
'--from=[Application to import from]:FROM:(autojump z)' \
|
'--from=[Application to import from]:FROM:(autojump z zoxide)' \
|
||||||
'--merge[Merge into existing database]' \
|
'--merge[Merge into existing database]' \
|
||||||
'-h[Print help]' \
|
'-h[Print help]' \
|
||||||
'--help[Print help]' \
|
'--help[Print help]' \
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ _zoxide() {
|
||||||
fi
|
fi
|
||||||
case "${prev}" in
|
case "${prev}" in
|
||||||
--from)
|
--from)
|
||||||
COMPREPLY=($(compgen -W "autojump z" -- "${cur}"))
|
COMPREPLY=($(compgen -W "autojump z zoxide" -- "${cur}"))
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcomm
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from increment" -s V -l version -d 'Print version'
|
complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from increment" -s V -l version -d 'Print version'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from reload" -s h -l help -d 'Print help'
|
complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from reload" -s h -l help -d 'Print help'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from reload" -s V -l version -d 'Print version'
|
complete -c zoxide -n "__fish_seen_subcommand_from edit; and __fish_seen_subcommand_from reload" -s V -l version -d 'Print version'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from import" -l from -d 'Application to import from' -r -f -a "{autojump ,z }"
|
complete -c zoxide -n "__fish_seen_subcommand_from import" -l from -d 'Application to import from' -r -f -a "{autojump ,z ,zoxide }"
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from import" -l merge -d 'Merge into existing database'
|
complete -c zoxide -n "__fish_seen_subcommand_from import" -l merge -d 'Merge into existing database'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from import" -s h -l help -d 'Print help'
|
complete -c zoxide -n "__fish_seen_subcommand_from import" -s h -l help -d 'Print help'
|
||||||
complete -c zoxide -n "__fish_seen_subcommand_from import" -s V -l version -d 'Print version'
|
complete -c zoxide -n "__fish_seen_subcommand_from import" -s V -l version -d 'Print version'
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ const completion: Fig.Spec = {
|
||||||
suggestions: [
|
suggestions: [
|
||||||
"autojump",
|
"autojump",
|
||||||
"z",
|
"z",
|
||||||
|
"zoxide",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ pub enum ImportFrom {
|
||||||
Autojump,
|
Autojump,
|
||||||
#[clap(alias = "fasd")]
|
#[clap(alias = "fasd")]
|
||||||
Z,
|
Z,
|
||||||
|
Zoxide,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate shell configuration
|
/// Generate shell configuration
|
||||||
|
|
|
||||||
|
|
@ -7,25 +7,41 @@ use crate::db::Database;
|
||||||
|
|
||||||
impl Run for Import {
|
impl Run for Import {
|
||||||
fn run(&self) -> Result<()> {
|
fn run(&self) -> Result<()> {
|
||||||
let buffer = fs::read_to_string(&self.path).with_context(|| {
|
|
||||||
format!("could not open database for importing: {}", &self.path.display())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let mut db = Database::open()?;
|
let mut db = Database::open()?;
|
||||||
if !self.merge && !db.dirs().is_empty() {
|
if !self.merge && !db.dirs().is_empty() {
|
||||||
bail!("current database is not empty, specify --merge to continue anyway");
|
bail!("current database is not empty, specify --merge to continue anyway");
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.from {
|
let buffer = fs::read(&self.path).with_context(|| {
|
||||||
ImportFrom::Autojump => import_autojump(&mut db, &buffer),
|
format!("could not open database for importing: {}", &self.path.display())
|
||||||
ImportFrom::Z => import_z(&mut db, &buffer),
|
})?;
|
||||||
|
|
||||||
|
if matches!(self.from, ImportFrom::Zoxide) {
|
||||||
|
from_self(&mut db, &buffer)?;
|
||||||
|
} else {
|
||||||
|
let buffer = std::str::from_utf8(&buffer).with_context(|| {
|
||||||
|
format!("could not open database for importing: {}", &self.path.display())
|
||||||
|
})?;
|
||||||
|
match self.from {
|
||||||
|
ImportFrom::Autojump => import_autojump(&mut db, buffer),
|
||||||
|
ImportFrom::Z => import_z(&mut db, buffer),
|
||||||
|
ImportFrom::Zoxide => unreachable!(),
|
||||||
|
}
|
||||||
|
.context("import error")?;
|
||||||
}
|
}
|
||||||
.context("import error")?;
|
|
||||||
|
|
||||||
db.save()
|
db.save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_self(db: &mut Database, buffer: &[u8]) -> Result<()> {
|
||||||
|
for dir in Database::deserialize(buffer).context("could not deserialize database")? {
|
||||||
|
db.add_unchecked(dir.path, dir.rank, dir.last_accessed);
|
||||||
|
}
|
||||||
|
db.dedup();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn import_autojump(db: &mut Database, buffer: &str) -> Result<()> {
|
fn import_autojump(db: &mut Database, buffer: &str) -> Result<()> {
|
||||||
for line in buffer.lines() {
|
for line in buffer.lines() {
|
||||||
if line.is_empty() {
|
if line.is_empty() {
|
||||||
|
|
@ -80,8 +96,10 @@ fn sigmoid(x: f64) -> f64 {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use std::fs;
|
||||||
use crate::db::Dir;
|
|
||||||
|
use super::{sigmoid, *};
|
||||||
|
use crate::db::{Database, Dir};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_autojump() {
|
fn from_autojump() {
|
||||||
|
|
@ -163,4 +181,44 @@ mod tests {
|
||||||
assert_eq!(dir1.last_accessed, dir2.last_accessed);
|
assert_eq!(dir1.last_accessed, dir2.last_accessed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_self() {
|
||||||
|
let path = if cfg!(windows) { r"C:\foo\bar" } else { "/foo/bar" };
|
||||||
|
let second_path = if cfg!(windows) { r"C:\bar\foo" } else { "/bar/foo" };
|
||||||
|
let now = 946684800;
|
||||||
|
let before = 946684700;
|
||||||
|
|
||||||
|
let source_data_dir = tempfile::tempdir().unwrap();
|
||||||
|
{
|
||||||
|
let mut db = Database::open_dir(source_data_dir.path()).unwrap();
|
||||||
|
db.add(path, 1.0, now);
|
||||||
|
db.save().unwrap();
|
||||||
|
assert_eq!(db.dirs().len(), 1);
|
||||||
|
let dir = &db.dirs()[0];
|
||||||
|
assert_eq!(dir.path, path);
|
||||||
|
assert_eq!(dir.last_accessed, now);
|
||||||
|
assert_eq!(dir.rank, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let dest_data_dir = tempfile::tempdir().unwrap();
|
||||||
|
let mut db = Database::open_dir(dest_data_dir.path()).unwrap();
|
||||||
|
db.add(path, 1.0, before);
|
||||||
|
db.add(second_path, 1.0, before);
|
||||||
|
db.save().unwrap();
|
||||||
|
|
||||||
|
let source_buf = fs::read(source_data_dir.path().join("db.zo")).unwrap();
|
||||||
|
|
||||||
|
super::from_self(&mut db, &source_buf).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(db.dirs().len(), 2);
|
||||||
|
let dir = &db.dirs()[0];
|
||||||
|
assert_eq!(dir.path, second_path);
|
||||||
|
assert_eq!(dir.last_accessed, before);
|
||||||
|
assert_eq!(dir.rank, 1.0);
|
||||||
|
let dir2 = &db.dirs()[1];
|
||||||
|
assert_eq!(dir2.path, path);
|
||||||
|
assert_eq!(dir2.last_accessed, now);
|
||||||
|
assert_eq!(dir2.rank, 2.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ impl Database {
|
||||||
.context("could not serialize database")
|
.context("could not serialize database")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize(bytes: &[u8]) -> Result<Vec<Dir>> {
|
pub(crate) fn deserialize(bytes: &[u8]) -> Result<Vec<Dir>> {
|
||||||
// Assume a maximum size for the database. This prevents bincode from throwing
|
// Assume a maximum size for the database. This prevents bincode from throwing
|
||||||
// strange errors when it encounters invalid data.
|
// strange errors when it encounters invalid data.
|
||||||
const MAX_SIZE: u64 = 32 << 20; // 32 MiB
|
const MAX_SIZE: u64 = 32 << 20; // 32 MiB
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue