Skip to content

Commit

Permalink
feature: add rm & put --rename
Browse files Browse the repository at this point in the history
  • Loading branch information
RCmerci committed Feb 14, 2019
1 parent 83883a9 commit ea9dd72
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 47 deletions.
2 changes: 1 addition & 1 deletion db/src/containeritem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<'a, 'b> ContainerItem<'a, 'b> {
dockercli: &'b dockerclient::DockerClient,
image: &str,
) -> Result<Self, Error> {
let mut filename = "".into();
let filename;
match path.file_name() {
None => {
return Err(Error::BadPath(path.display().to_string()));
Expand Down
48 changes: 38 additions & 10 deletions db/src/docker.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::utils::get_or_run;
use crate::utils::{get_or_run, run};
use crate::*;
use hex;
use std::fmt;
Expand Down Expand Up @@ -35,6 +35,34 @@ impl ImageDrive {
dockercli: dockercli,
}
}
// cat /checksum/data/*/* | sort
fn get_checksum_str(&self, container: &str) -> String {
let cmd = "cat /checksum/data/*/* | sort";
self.dockercli
.exec(container, cmd)
.map_err(Error::DockerError)
.map(|(out, err)| {
(
String::from_utf8_lossy(&out).to_owned().to_string(),
String::from_utf8_lossy(&err).to_owned().to_string(),
)
})
.and_then(|(out, err)| {
if err != "" {
return Err(Error::ExecError(err));
}
Ok(out.trim().to_owned())
})
.expect("get checksum")
}
// diff_container_with_image return true if different
fn diff_container_with_image(&self) -> bool {
let c = get_or_run(&self.dockercli, &self.image_name).expect("get or run");
let image_c = run(&self.dockercli, &self.image_name).expect("run");
let c_checksum = self.get_checksum_str(&c.id);
let image_c_checksum = self.get_checksum_str(&image_c.id);
c_checksum != image_c_checksum
}
}

impl fmt::Display for ImageDrive {
Expand All @@ -55,11 +83,11 @@ impl DB<Error> for ImageDrive {
)
}

fn add(&self, entry: &str, itempath: &Path) -> Result<AddResult, Error> {
fn add(&self, entry: &str, itempath: &Path, rename: Option<&str>) -> Result<AddResult, Error> {
if !itempath.exists() {
return Err(Error::NotExistItem(format!("{}", itempath.display())));
}
let mut item = hostitem::HostItem::new(itempath).map_err(Error::HostItemError)?;
let mut item = hostitem::HostItem::new(itempath, rename).map_err(Error::HostItemError)?;

let c = get_or_run(&self.dockercli, &self.image_name).map_err(Error::DockerError)?;
let path = Path::new("/data").join(entry);
Expand Down Expand Up @@ -126,9 +154,12 @@ impl DB<Error> for ImageDrive {
Ok(AddResult::Succ)
})
}
fn delete(&self, entry: &str, item: &str) -> Result<(), Error> {
fn delete(&self, entry: &str, item: Option<&str>) -> Result<(), Error> {
let c = get_or_run(&self.dockercli, &self.image_name).map_err(Error::DockerError)?;
let dstpath = Path::new("/data").join(entry).join(item);
let dstpath = match item {
None => Path::new("/data").join(entry),
Some(file) => Path::new("/data").join(entry).join(file),
};
self.dockercli
.remove_file(&c.id, &dstpath)
.map_err(|e| Error::ExecError(format!("{:?}", e)))
Expand All @@ -143,13 +174,10 @@ impl DB<Error> for ImageDrive {
}

fn sync(&self) -> Result<(), Error> {
// TODO: check image exist, if not , pull from registry

// image existed, so push to registry

// 1. commit all changed data in container to image
let c = get_or_run(&self.dockercli, &self.image_name).map_err(Error::DockerError)?;
if self.dockercli.diff_container_image_content(&c.id) {
if self.diff_container_with_image() {
println!("something changed in localDB , so need to sync to remote");
let _ = self
.dockercli
.commit(&c.id, "commit by sync", &self.image_name)
Expand Down
9 changes: 6 additions & 3 deletions db/src/hostitem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ pub struct HostItem<'a> {
}

impl<'a> HostItem<'a> {
pub fn new(path: &'a Path) -> Result<Self, Error> {
let mut filename = "".into();
pub fn new(path: &'a Path, rename: Option<&str>) -> Result<Self, Error> {
let filename;
match path.file_name() {
None => {
return Err(Error::BadPath(path.display().to_string()));
}
Some(s) => filename = s.to_string_lossy().to_owned(),
}
let id = format!("{:?}", filename);
let mut id = format!("{:?}", filename);
if rename.is_some() {
id = format!("{:?}", rename.unwrap())
}
let mut fs = vec![];
// host file or dir
if path.is_file() {
Expand Down
9 changes: 7 additions & 2 deletions db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ where
/// items list items under `entry`
fn items(&self, entry: &str) -> Result<Vec<String>, E>;
/// add `item` to DB under `entry`
fn add(&self, entry: &str, itempath: &std::path::Path) -> Result<AddResult, E>;
fn add(
&self,
entry: &str,
itempath: &std::path::Path,
rename: Option<&str>,
) -> Result<AddResult, E>;
/// delete item from DB, which is located by entry and reference
fn delete(&self, entry: &str, item: &str) -> Result<(), E>;
fn delete(&self, entry: &str, item: Option<&str>) -> Result<(), E>;
/// export_to_dir export `entry` to `dir`
fn export_to_dir(&self, dir: &std::path::Path, entry: &str) -> Result<(), E>;
/// sync local DB to remote DB
Expand Down
8 changes: 8 additions & 0 deletions db/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ pub fn get_or_run(
cli.start(&c.id)?;
Ok(c)
}
pub fn run(
cli: &dockerclient::DockerClient,
image: &str,
) -> Result<dockerclient::Container, dockerclient::Error> {
let c = cli.create(image)?;
cli.start(&c.id)?;
Ok(c)
}
34 changes: 19 additions & 15 deletions dockerclient/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,17 +265,21 @@ impl DockerClient {
})
}

// it maybe long duration, so print docker push's processing stdout
pub fn push(&self, image: &str) -> Result<(), Error> {
let cmd = format!("docker push {}", image);
let r = std::process::Command::new("sh")
let mut r = std::process::Command::new("sh")
.arg("-c")
.arg(&cmd)
.output()
.stderr(std::process::Stdio::null())
.stdout(std::process::Stdio::inherit())
.spawn()
.map_err(|e| Error::DefaultError(e.to_string()))?;
if r.status.success() {
let status = r.wait().map_err(|e| Error::DefaultError(e.to_string()))?;
if status.success() {
return Ok(());
}
if (!r.status.success())
if (!status.success())
&& self.server.is_some()
&& self.username.is_some()
&& self.password.is_some()
Expand All @@ -295,30 +299,30 @@ impl DockerClient {
let errstr = String::from_utf8_lossy(&output.stderr).to_string();
return Err(Error::LoginError(errstr));
}
} else if !r.status.success() {
return Err(Error::PushError(format!("code: {:?}", r.status.code())));
} else if !status.success() {
return Err(Error::PushError(format!("code: {:?}", status.code())));
}

// login succ, retry push

std::process::Command::new("sh")
.arg("-c")
.arg(&cmd)
.output()
.map_err(|e| Error::DefaultError(e.to_string()))
.stderr(std::process::Stdio::piped())
.stdout(std::process::Stdio::inherit())
.spawn()
.map_err(|e| Error::PushError(e.to_string()))
.and_then(|r| {
if !r.status.success() {
let errstr = String::from_utf8_lossy(&r.stderr).to_string();
let output = r
.wait_with_output()
.map_err(|e| Error::PushError(e.to_string()))?;
if !output.status.success() {
let errstr = String::from_utf8_lossy(&output.stderr).to_string();
return Err(Error::PushError(errstr));
}
Ok(())
})
}

/// return true if container's content is different with its image.
pub fn diff_container_image_content(&self, _container: &str) -> bool {
true
}
}

fn copy(
Expand Down
11 changes: 9 additions & 2 deletions front/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub fn list_entry_item(db: &ImageDrive, entry: &str) {
}
}

pub fn put(db: &ImageDrive, entry: &str, item: &str) {
match db.add(entry, Path::new(item)) {
pub fn put(db: &ImageDrive, entry: &str, item: &str, rename: Option<&str>) {
match db.add(entry, Path::new(item), rename) {
Err(e) => println!("put item fail: {:?}", e),
Ok(r) => println!("{:?}", r),
}
Expand All @@ -61,6 +61,13 @@ pub fn sync(db: &ImageDrive, from_remote: bool) {
}
}

pub fn rm(db: &ImageDrive, entry: &str, file: Option<&str>) {
match db.delete(entry, file) {
Err(e) => println!("rm entry (or file) fail: {:?}", e),
Ok(_) => println!("rm [{:?}]", entry.to_owned() + "/" + file.unwrap_or("")),
}
}

#[cfg(test)]
mod tests {
#[test]
Expand Down
39 changes: 25 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ fn main() {
SubCommand::with_name("put")
.about("put host file to imagedrive")
.arg(Arg::with_name("entry").help("entry name").required(true))
.arg(Arg::with_name("file").help("file path").required(true)),
.arg(Arg::with_name("file").help("file path").required(true))
.arg(Arg::with_name("name").help("rename file")),
)
.subcommand(
SubCommand::with_name("export")
Expand All @@ -54,9 +55,15 @@ fn main() {
.long("remote"),
),
)
.subcommand(
SubCommand::with_name("rm")
.about("remove entry or file")
.arg(Arg::with_name("entry").help("entry name").required(true))
.arg(Arg::with_name("file").help("file name")),
)
.get_matches();

let mut config_path = None;
let mut config_path;
if matches.is_present("config") {
config_path = Some(std::path::Path::new(matches.value_of("config").unwrap()).to_path_buf());
} else {
Expand All @@ -79,7 +86,6 @@ fn main() {
let image_name = &cfg.image_name;

if let Some(matches) = matches.subcommand_matches("ls") {
// "$ myapp test" was run
if matches.is_present("entry") {
front::list_entry_item(
&ImageDrive::new(image_name, server, username, password),
Expand All @@ -88,34 +94,39 @@ fn main() {
} else {
front::list_entry(&ImageDrive::new(image_name, server, username, password));
}
}

if let Some(matches) = matches.subcommand_matches("put") {
} else if let Some(matches) = matches.subcommand_matches("put") {
let entry = matches.value_of("entry").unwrap();
let filepath = matches.value_of("file").unwrap();
let rename = matches.value_of("name");
front::put(
&ImageDrive::new(image_name, server, username, password),
entry,
filepath,
rename,
);
}

if let Some(matches) = matches.subcommand_matches("export") {
} else if let Some(matches) = matches.subcommand_matches("export") {
let entry = matches.value_of("entry").unwrap();
let filepath = matches.value_of("dir").unwrap();
front::export(
&ImageDrive::new(image_name, server, username, password),
entry,
filepath,
);
}

if let Some(matches) = matches.subcommand_matches("sync") {
} else if let Some(matches) = matches.subcommand_matches("sync") {
front::sync(
&ImageDrive::new(image_name, server, username, password),
matches.is_present("from_remote"),
);
} else if let Some(matches) = matches.subcommand_matches("rm") {
let entry = matches.value_of("entry").unwrap();
let file = matches.value_of("file");
front::rm(
&ImageDrive::new(image_name, server, username, password),
entry,
file,
);
} else {
// default
front::list_entry(&ImageDrive::new(image_name, server, username, password));
}

// Continued program logic goes here...
}

0 comments on commit ea9dd72

Please sign in to comment.