Skip to content

Commit

Permalink
separate publish and publish-flow, add reslug, split in files
Browse files Browse the repository at this point in the history
  • Loading branch information
Geobert Quach committed Nov 3, 2019
1 parent dba2a30 commit c7fe7f2
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 140 deletions.
43 changes: 15 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,7 @@ publish_dest = "content/"

## Usage

```
emile 0.1.0
A workflow companion for zola.
USAGE:
emile <SUBCOMMAND>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
SUBCOMMANDS:
git-hook Called by the git webhook. Performs update of the blog repo, and check last log commit message for
commands:
* `blog_build`: build the blog
* `blog_sched "at-format-date" post-slug: schedule the post
* `blog_unsched post-slug`: cancel a previously scheduled post
help Prints this message or the help of the given subcommand(s)
new Create a new post in drafts folder, with current date prepended to filename.
publish Mark a post as not draft, move it to `posts` folder, set the `date` field in front, build the
website, commit the changes and push them back
schedule Schedule a post. Ex: `emile schedule "tomorrow" my-post-slug`.
unschedule Cancel a schedule for the post with `slug`
```
`emile --help` and `emile <command> --help` to get all the details.

### new

Expand All @@ -67,13 +44,17 @@ The `new` command takes the title of your new blog post, between quotes:
emile new "My new blog post"
```

### reslug

Rename the post's filename according to its title. If the provided path is a file, change
only this file. If it's a directory, `emile` will change files starting with `-`. So you
can mark files to be updated by prepending `-` to them.

### publish

This command takes a `slug` as parameter. It will take the file corresponding to the
`slug` in the `drafts_consumption_dir`, change its date and draft status and move it to
the `publish_dest` directory.

Then it calls `zola build`, commit the change and push them to `origin`.
the `publish_dest` directory. The site is not rebuild after that.

```
emile publish my-new-blog-post
Expand All @@ -84,7 +65,8 @@ emile publish my-new-blog-post
This command needs a `date` and a `slug`. `date` need to be between quotes and in the
[`at`](https://linux.die.net/man/1/at) utility format.

It schedules the post corresponding to the slug to be `publish`ed at the given `date`.
It schedules the post corresponding to the slug to be published and the site updated at
the given `date`.

```
emile schedule "teatime tomorrow" my-new-blog-post
Expand All @@ -98,6 +80,11 @@ This cancel a previous scheduled post by its slug.
emile unschedule my-new-blog-post
```

### publish-flow

This does a `publish`, build the website, commit the changes and push them to origin.
It is used by `schedule` command as the configured job will call `publish-flow`.

### git-hook

This command is intended to be called by a git hook for my specific workflow. It may or
Expand Down
74 changes: 74 additions & 0 deletions src/git.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use std::io;
use std::process::Command;

use crate::config::Config;
use anyhow::{bail, Result};

pub fn update_repo() -> Result<()> {
match Command::new("git").arg("pull").output() {
Ok(output) => {
if !output.status.success() {
bail!(
"issue updating repo: {}\nerr: {}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
}
}
Err(e) => match e.kind() {
io::ErrorKind::NotFound => {
bail!("`git` was not found, please verify the PATH env.");
}
_ => {
bail!("{}", e);
}
},
}
Ok(())
}

pub fn update_remote(slug: &str, cfg: &Config) -> Result<()> {
let dest_dir = cfg
.publish_dest
.as_ref()
.expect("Should have a value by now")
.to_string_lossy();
Command::new("git")
.arg("add")
.arg(format!("{}*.md", dest_dir))
.output()?;
Command::new("git")
.arg("commit")
.arg("-a")
.arg("-m")
.arg(format!("\"published {}.md\"", slug))
.output()?;
Command::new("git").arg("push").output()?;
Ok(())
}

pub fn get_last_log() -> Result<String> {
match Command::new("git")
.arg("log")
.arg("-n")
.arg("1")
.arg("--format=%B")
.output()
{
Ok(output) => {
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
bail!("{}", String::from_utf8_lossy(&output.stdout));
}
}
Err(e) => match e.kind() {
io::ErrorKind::NotFound => {
bail!("`git` was not found, please verify the PATH env.");
}
_ => {
bail!("{}", e);
}
},
}
}
58 changes: 46 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use std::io::Write;

use anyhow::{bail, Result};
use config::Config;

use structopt::StructOpt;

mod cmd;
mod config;
mod git;
mod new;
mod opt;
mod post;
mod publish;
mod reslug;
mod schedule;

use opt::Opt;

Expand All @@ -19,31 +22,62 @@ fn main() -> Result<()> {
match opt {
Opt::New { title } => new::create_draft(&title, &cfg),
Opt::Publish { slug } => {
cmd::update_repo()?;
let dest = publish::publish_post(&slug, &cfg)?;
println!(
"Success: post `{}` published. Call `zola build` to build the site.",
dest
);
Ok(())
}
Opt::PublishFlow { slug } => {
git::update_repo()?;
publish::publish_post(&slug, &cfg)?;
cmd::clean_jobs_list(&slug)?;
cmd::update_remote(&slug, &cfg)
zola_build()?;
schedule::clean_jobs_list(&slug)?;
git::update_remote(&slug, &cfg)
}
Opt::GitHook {} => {
cmd::update_repo()?;
let log = cmd::get_last_log()?;
git::update_repo()?;
let log = git::get_last_log()?;
let mut log = log.split_ascii_whitespace();
let command = log.next().expect("Empty log");
match command {
"blog_build" => cmd::zola_build(),
"blog_build" => zola_build(),
"blog_sched" => {
let date = log.next().expect("No date specified");
let slug = log.next().expect("No slug specified");
cmd::schedule_publish(date, slug)
schedule::schedule_publish(date, slug)
}
"blog_unsched" => {
let slug = log.next().expect("No slug specified");
cmd::unschedule_publish(slug)
schedule::unschedule_publish(slug)
}
_ => bail!("unknown command: {}", command),
}
}
Opt::Unschedule { slug } => cmd::unschedule_publish(&slug),
Opt::Schedule { date, slug } => cmd::schedule_publish(&date, &slug),
Opt::Unschedule { slug } => schedule::unschedule_publish(&slug),
Opt::Schedule { date, slug } => schedule::schedule_publish(&date, &slug),
Opt::Reslug { path } => reslug::reslug(&path),
}
}

fn zola_build() -> Result<()> {
match std::process::Command::new("zola").arg("build").output() {
Ok(output) => {
if output.status.success() {
std::io::stdout().write_all(&output.stdout)?;
Ok(std::io::stdout().flush()?)
} else {
bail!("{}", String::from_utf8_lossy(&output.stdout));
}
}
Err(e) => match e.kind() {
std::io::ErrorKind::NotFound => {
bail!("`zola` was not found, please verify the PATH env.");
}
_ => {
bail!("{}", e);
}
},
}
}
16 changes: 14 additions & 2 deletions src/opt.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::PathBuf;

use structopt::StructOpt;

#[derive(Debug, StructOpt)]
Expand All @@ -8,12 +10,16 @@ pub enum Opt {
/// Title of the blog post. Needs to be around quotes.
title: String,
},
/// Mark a post as not draft, move it to `posts` folder, set the `date` field in front, build
/// the website, commit the changes and push them back
/// Mark a post as not draft, move it to `posts` folder, set the `date` field in front.
Publish {
/// Slug part of the file name
slug: String,
},
/// Do `publish`, build the website, commit the changes and push them to origin
PublishFlow {
/// Slug part of the file name
slug: String,
},
/// Called by the git webhook. Performs update of the blog repo, and check last log commit
/// message for commands:{n}
/// * `blog_build`: build the blog{n}
Expand All @@ -32,4 +38,10 @@ pub enum Opt {
/// slug part of the file name
slug: String,
},
/// Rename the post's filename according to its title
Reslug {
/// If it's a file, it will rename it. If it's a directory, will rename files which file
/// name begins with `-`.
path: PathBuf,
},
}
8 changes: 2 additions & 6 deletions src/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ use std::path::PathBuf;
use anyhow::{bail, Result};
use chrono::Local;

use crate::cmd;
use crate::config::Config;
use crate::post::modify_post;

pub fn publish_post(slug: &str, cfg: &Config) -> Result<()> {
pub fn publish_post(slug: &str, cfg: &Config) -> Result<String> {
let drafts_consumption_dir = cfg
.drafts_consumption_dir
.as_ref()
Expand Down Expand Up @@ -54,10 +53,7 @@ pub fn publish_post(slug: &str, cfg: &Config) -> Result<()> {
fs::write(&dest, new_content)?;
fs::remove_file(&src)?;

cmd::zola_build()?;

println!("Success: post `{}` published", dest.to_string_lossy());
Ok(())
Ok(dest.to_string_lossy().to_string())
}

fn does_same_title_exist(slug: &str, dir: &PathBuf) -> Result<Option<DirEntry>> {
Expand Down
49 changes: 49 additions & 0 deletions src/reslug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::fs;
use std::io::{BufRead, BufReader};

use anyhow::{bail, Result};
use slug::slugify;

fn _reslug(file_path: &std::path::Path) -> Result<()> {
let file = std::fs::File::open(&file_path)?;
let reader = BufReader::new(&file);
let mut title = String::new();
for line in reader.lines() {
let line = line.expect("Should have text");
if line.starts_with("title") {
let start = line.find('\"').expect("Should have starting quote in toml");
let end = line.rfind('\"').expect("Should have ending quote in toml");
if start < end {
title = line.clone().drain(start + 1..end).collect();
} else {
bail!("Corrupted title: {}", line);
}
break;
}
}
let dest_file = file_path.with_file_name(format!("{}.md", slugify(title)));
std::fs::rename(&file_path, &dest_file)?;
println!(
"Renamed `{}` to `{}`",
file_path.display(),
dest_file.display()
);
Ok(())
}

pub fn reslug(path: &std::path::Path) -> Result<()> {
if path.is_file() {
_reslug(&path)
} else {
for entry in fs::read_dir(&path)? {
if let Ok(entry) = entry {
let filename = entry.file_name();
let filename = filename.to_string_lossy();
if filename.starts_with("-") {
_reslug(&entry.path())?;
}
}
}
Ok(())
}
}
Loading

0 comments on commit c7fe7f2

Please sign in to comment.