Skip to content

Commit

Permalink
feat: Rename subcommand
Browse files Browse the repository at this point in the history
Cobalt now has supprot for:
`cobalt rename <src_path> <new_title> [--file <dest_path>]`
This will
- Update the `title` in the frontmatter
- Move the file to the `dest_path` (or cwd)

We have all the information we need to help the user set up a
redirection, so ideally we would.  Unfortunately, that will require:
1. Deciding on an approach (alias vs file)
2. Refactoring the code necesary to make either work.

This has now been split out into #403.

Fixes #393
  • Loading branch information
epage committed Mar 20, 2018
1 parent efa54d6 commit 1fee077
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/bin/cobalt/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ fn run() -> Result<()> {
.args(&args::get_logging_args())
.subcommand(new::init_command_args())
.subcommand(new::new_command_args())
.subcommand(new::rename_command_args())
.subcommand(new::publish_command_args())
.subcommand(build::build_command_args())
.subcommand(build::clean_command_args())
Expand All @@ -64,6 +65,7 @@ fn run() -> Result<()> {
match command {
"init" => new::init_command(matches),
"new" => new::new_command(matches),
"rename" => new::rename_command(matches),
"publish" => new::publish_command(matches),
"build" => build::build_command(matches),
"clean" => build::clean_command(matches),
Expand Down
118 changes: 118 additions & 0 deletions src/bin/cobalt/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,52 @@ pub fn new_command(matches: &clap::ArgMatches) -> Result<()> {
Ok(())
}

pub fn rename_command_args() -> clap::App<'static, 'static> {
clap::SubCommand::with_name("rename")
.about("Rename a document")
.args(&args::get_config_args())
.arg(
clap::Arg::with_name("SRC")
.required(true)
.help("File to rename")
.takes_value(true),
)
.arg(
clap::Arg::with_name("TITLE")
.required(true)
.help("Title of the post")
.takes_value(true),
)
.arg(
clap::Arg::with_name("file")
.short("f")
.long("file")
.value_name("DIR_OR_FILE")
.help("New document's parent directory or file (default: `<CWD>/title.ext`)")
.takes_value(true),
)
}

pub fn rename_command(matches: &clap::ArgMatches) -> Result<()> {
let config = args::get_config(matches)?;
let config = config.build()?;

let source = path::PathBuf::from(matches.value_of("SRC").unwrap());

let title = matches.value_of("TITLE").unwrap();

let mut file = env::current_dir().expect("How does this fail?");
if let Some(rel_file) = matches.value_of("file") {
file.push(path::Path::new(rel_file))
}
let file = file;

rename_document(&config, source, title, file)
.chain_err(|| format!("Could not rename `{}`", title))?;

Ok(())
}

pub fn publish_command_args() -> clap::App<'static, 'static> {
clap::SubCommand::with_name("publish")
.about("Publish a document")
Expand Down Expand Up @@ -282,6 +328,78 @@ fn create_file_for_path(path: &path::Path, content: &str) -> Result<()> {
Ok(())
}

pub fn rename_document(
config: &cobalt_model::Config,
source: path::PathBuf,
title: &str,
file: path::PathBuf,
) -> Result<()> {
let target = if file.extension().is_none() || file.is_dir() {
let extension = source.extension().and_then(|s| s.to_str()).unwrap_or("md");
let file_name = format!("{}.{}", cobalt_model::slug::slugify(title), extension);
let mut file = file;
file.push(path::Path::new(&file_name));
file
} else {
file
};

let doc = cobalt_model::files::read_file(&source)?;
let doc = cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::parse(&doc)?;
let (front, content) = doc.parts();

let pages = config.pages.clone().build()?;
let posts = config.posts.clone().build()?;
let full_front = if posts.pages.includes_file(&target)
|| posts
.drafts
.map(|d| d.includes_file(&target))
.unwrap_or_default()
{
// Can't rely on this for drafts atm
let rel_src = target
.strip_prefix(&config.source)
.expect("file was found under the root");
front
.clone()
.merge_path(rel_src)
.merge(posts.default.clone())
} else if pages.pages.includes_file(&target)
|| pages
.drafts
.map(|d| d.includes_file(&target))
.unwrap_or_default()
{
// Can't rely on this for drafts atm
let rel_src = target
.strip_prefix(&config.source)
.expect("file was found under the root");
front
.clone()
.merge_path(rel_src)
.merge(pages.default.clone())
} else {
bail!(
"Target file wouldn't be a member of any collection: {:?}",
target
);
};
let full_front = full_front.build()?;

let new_front = front.set_title(Some(title.to_string()));
let doc =
cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::new(new_front, content);
let doc = doc.to_string();
cobalt_model::files::write_document_file(doc, target)?;

if !full_front.is_draft {
warn!("Renaming a published page might invalidate links");
}
fs::remove_file(source)?;

Ok(())
}

pub fn publish_document(file: &path::Path) -> Result<()> {
let doc = cobalt_model::files::read_file(file)?;
let doc = cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::parse(&doc)?;
Expand Down

0 comments on commit 1fee077

Please sign in to comment.