Skip to content

Commit

Permalink
Add files move command
Browse files Browse the repository at this point in the history
  • Loading branch information
prasmussen committed Jan 23, 2023
1 parent 7a37b2b commit cb24d27
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod import;
pub mod info;
pub mod list;
pub mod mkdir;
pub mod mv;
pub mod rename;
pub mod update;
pub mod upload;
Expand All @@ -18,6 +19,7 @@ pub use import::import;
pub use info::info;
pub use list::list;
pub use mkdir::mkdir;
pub use mv::mv;
pub use rename::rename;
pub use update::update;
pub use upload::upload;
150 changes: 150 additions & 0 deletions src/files/mv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use crate::common::delegate::UploadDelegate;
use crate::common::delegate::UploadDelegateConfig;
use crate::common::drive_file;
use crate::common::hub_helper;
use crate::files;
use crate::hub::Hub;
use std::error;
use std::fmt::Display;
use std::fmt::Formatter;

#[derive(Clone, Debug)]
pub struct Config {
pub file_id: String,
pub parent_id: String,
}

pub async fn mv(config: Config) -> Result<(), Error> {
let hub = hub_helper::get_hub().await.map_err(Error::Hub)?;
let delegate_config = UploadDelegateConfig::default();

let old_file = files::info::get_file(&hub, &config.file_id)
.await
.map_err(Error::GetFile)?;

let old_parent_id = get_old_parent_id(&old_file)?;

let old_parent = files::info::get_file(&hub, &old_parent_id)
.await
.map_err(|err| Error::GetOldParent(old_parent_id.clone(), err))?;

let new_parent = files::info::get_file(&hub, &config.parent_id)
.await
.map_err(Error::GetNewParent)?;

err_if_not_directory(&new_parent)?;

println!(
"Moving '{}' from '{}' to '{}'",
old_file.name.unwrap_or_default(),
old_parent.name.unwrap_or_default(),
new_parent.name.unwrap_or_default()
);

let change_parent_config = ChangeParentConfig {
file_id: config.file_id,
old_parent_id,
new_parent_id: config.parent_id,
};

change_parent(&hub, delegate_config, &change_parent_config)
.await
.map_err(Error::Move)?;

Ok(())
}

pub struct ChangeParentConfig {
pub file_id: String,
pub old_parent_id: String,
pub new_parent_id: String,
}

pub async fn change_parent(
hub: &Hub,
delegate_config: UploadDelegateConfig,
config: &ChangeParentConfig,
) -> Result<google_drive3::api::File, google_drive3::Error> {
let mut delegate = UploadDelegate::new(delegate_config);

let empty_file = google_drive3::api::File::default();

let (_, file) = hub
.files()
.update(empty_file, &config.file_id)
.remove_parents(&config.old_parent_id)
.add_parents(&config.new_parent_id)
.param("fields", "id,name,size,createdTime,modifiedTime,md5Checksum,mimeType,parents,shared,description,webContentLink,webViewLink")
.add_scope(google_drive3::api::Scope::Full)
.delegate(&mut delegate)
.supports_all_drives(true)
.doit_without_upload().await?;

Ok(file)
}

#[derive(Debug)]
pub enum Error {
Hub(hub_helper::Error),
GetFile(google_drive3::Error),
GetOldParent(String, google_drive3::Error),
GetNewParent(google_drive3::Error),
NoParents,
MultipleParents,
NotADirectory,
Move(google_drive3::Error),
}

impl error::Error for Error {}

impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
Error::Hub(err) => write!(f, "{}", err),
Error::GetFile(err) => {
write!(f, "Failed to get file: {}", err)
}
Error::GetNewParent(err) => {
write!(f, "Failed to get new parent: {}", err)
}
Error::GetOldParent(id, err) => {
write!(f, "Failed to get old parent '{}': {}", id, err)
}
Error::NoParents => {
write!(f, "File has no parents")
}
Error::MultipleParents => {
write!(f, "Can't move file with multiple parents")
}
Error::NotADirectory => {
write!(f, "New parent is not a directory")
}
Error::Move(err) => {
write!(f, "Failed to move file: {}", err)
}
}
}
}

fn get_old_parent_id(file: &google_drive3::api::File) -> Result<String, Error> {
match &file.parents {
None => {
// fmt
Err(Error::NoParents)
}

Some(parents) => match &parents[..] {
[] => Err(Error::NoParents),
[parent_id] => Ok(parent_id.to_string()),
_ => Err(Error::MultipleParents),
},
}
}

fn err_if_not_directory(file: &google_drive3::api::File) -> Result<(), Error> {
if !drive_file::is_directory(file) {
Err(Error::NotADirectory)
} else {
Ok(())
}
}
22 changes: 19 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,21 @@ enum FileCommand {
/// Rename file/directory
Rename {
/// Id of file or directory
id: String,
file_id: String,

/// New name
name: String,
},

/// Move file/directory
Move {
/// Id of file or directory to move
file_id: String,

/// Id of parent directory to move to
parent_id: String,
},

/// Import file as a google document/spreadsheet/presentation.
/// Example of file types that can be imported: doc, docx, odt, pdf, html, xls, xlsx, csv, ods, ppt, pptx, odp
Import {
Expand Down Expand Up @@ -431,9 +440,16 @@ async fn main() {
.unwrap_or_else(handle_error)
}

FileCommand::Rename { id, name } => {
FileCommand::Rename { file_id, name } => {
// fmt
files::rename(files::rename::Config { file_id, name })
.await
.unwrap_or_else(handle_error)
}

FileCommand::Move { file_id, parent_id } => {
// fmt
files::rename(files::rename::Config { file_id: id, name })
files::mv(files::mv::Config { file_id, parent_id })
.await
.unwrap_or_else(handle_error)
}
Expand Down

0 comments on commit cb24d27

Please sign in to comment.