Skip to content

Commit

Permalink
fix(*): upgrade to latest Rust
Browse files Browse the repository at this point in the history
This makes plenty of adjustments to work
against the latest Rust version.

It also replaces docopt.rs with clap.rs

Fixes #16
  • Loading branch information
kbknapp authored and cburgdorf committed Mar 31, 2015
1 parent 88ccacd commit d230dd8
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 137 deletions.
47 changes: 38 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions Cargo.toml
Expand Up @@ -4,8 +4,8 @@ name = "clog"
version = "0.2.0"
authors = ["Christoph Burgdorf <christoph.burgdorf@bvsn.org>"]

[dependencies.docopt]
git = "https://github.com/docopt/docopt.rs"

[dependencies.docopt_macros]
git = "https://github.com/docopt/docopt.rs"
[dependencies]
regex = "*"
regex_macros = "*"
time = "*"
clap = "*"
24 changes: 12 additions & 12 deletions src/common.rs
@@ -1,14 +1,14 @@
use std::fmt;
use std::collections::hashmap::HashMap;
use std::collections::HashMap;

#[deriving(Show, PartialEq, Clone)]
#[derive(Debug, PartialEq, Clone)]
pub enum CommitType {
Feature,
Fix,
Unknown
}

#[deriving(Clone)]
#[derive(Clone)]
pub struct LogEntry {
pub hash: String,
pub subject: String,
Expand All @@ -18,15 +18,15 @@ pub struct LogEntry {
pub commit_type: CommitType
}

impl fmt::Show for LogEntry {
impl fmt::Debug for LogEntry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{
hash:{},
subject: {},
commit_type: {},
component: {},
closes: {},
breaks: {}
write!(f, "{{
hash:{:?},
subject: {:?},
commit_type: {:?},
component: {:?},
closes: {:?},
breaks: {:?}
}}", self.hash, self.subject, self.commit_type, self.component, self.closes, self.breaks)
}
}
Expand All @@ -35,4 +35,4 @@ pub struct SectionMap {
pub features: HashMap<String, Vec<LogEntry>>,
pub fixes: HashMap<String, Vec<LogEntry>>,
pub breaks: HashMap<String, Vec<LogEntry>>
}
}
2 changes: 1 addition & 1 deletion src/format_util.rs
@@ -1,4 +1,4 @@

pub fn get_short_hash(hash: &str) -> &str {
hash.slice_chars(0,8)
&hash[0..8]
}
75 changes: 36 additions & 39 deletions src/git.rs
@@ -1,8 +1,11 @@
use std::io::Command;
use std::process::Command;
use std::io::Read;
use regex::Regex;
use common:: { LogEntry, Feature, Fix, Unknown };
use common:: { LogEntry };
use common::CommitType;
use std::borrow::ToOwned;

#[deriving(Show)]
#[derive(Debug)]
pub struct LogReaderConfig {
pub grep: String,
pub format: String,
Expand All @@ -11,50 +14,44 @@ pub struct LogReaderConfig {
}

pub fn get_latest_tag () -> String {

Command::new("git")
let output = Command::new("git")
.arg("rev-list")
.arg("--tags")
.arg("--max-count=1")
.spawn()
.ok().expect("failed to invoke ref-list")
.stdout.as_mut().unwrap().read_to_string()
.ok().expect("failed to get latest git log")
.as_slice().trim_chars('\n')
.to_string()
.output().unwrap_or_else(|e| panic!("Failed to run git rev-list with error: {}",e));
let buf = String::from_utf8_lossy(&output.stdout);

buf.trim_matches('\n').to_owned()
}

pub fn get_last_commit () -> String {
Command::new("git")
let output = Command::new("git")
.arg("rev-parse")
.arg("HEAD")
.spawn()
.ok().expect("failed to invoke rev-parse")
.stdout.as_mut().unwrap().read_to_string()
.ok().expect("failed to get last commit")
.output().unwrap_or_else(|e| panic!("Failed to run git rev-parse with error: {}", e));

String::from_utf8_lossy(&output.stdout).into_owned()
}

pub fn get_log_entries (config:LogReaderConfig) -> Vec<LogEntry>{

let range = match config.from {
Some(ref from) => format!("{}..{}", from, config.to),
None => "HEAD".to_string()
None => "HEAD".to_owned()
};

Command::new("git")
let output = Command::new("git")
.arg("log")
.arg("-E")
.arg(format!("--grep={}",config.grep))
.arg(format!("--format={}", "%H%n%s%n%b%n==END=="))
.arg(range)
.spawn()
.ok().expect("failed to invoke `git log`")
.stdout.as_mut().unwrap().read_to_string()
.ok().expect("failed to read git log")
.as_slice()
.split_str("\n==END==\n")
.arg(&format!("--grep={}",config.grep))
.arg(&format!("--format={}", "%H%n%s%n%b%n==END=="))
.arg(&range)
.output().unwrap_or_else(|e| panic!("Failed to run git log with error: {}", e));

String::from_utf8_lossy(&output.stdout)
.split("\n==END==\n")
.map(|commit_str| { parse_raw_commit(commit_str) })
.filter(| entry| entry.commit_type != Unknown)
.filter(| entry| entry.commit_type != CommitType::Unknown)
.collect()
}

Expand All @@ -64,32 +61,32 @@ static CLOSES_PATTERN: Regex = regex!(r"(?:Closes|Fixes|Resolves)\s((?:#(\d+)(?:
fn parse_raw_commit(commit_str:&str) -> LogEntry {
let mut lines = commit_str.split('\n');

let hash = lines.next().unwrap_or("").to_string();
let hash = lines.next().unwrap_or("").to_owned();

let (subject, component, commit_type) =
match lines.next().and_then(|s| COMMIT_PATTERN.captures(s)) {
Some(caps) => {
let commit_type = match caps.at(1) {
"feat" => Feature,
"fix" => Fix,
_ => Unknown
Some("feat") => CommitType::Feature,
Some("fix") => CommitType::Fix,
_ => CommitType::Unknown
};
let component = caps.at(2).to_string();
let subject = caps.at(3).to_string();
let component = caps.at(2);
let subject = caps.at(3);
(subject, component, commit_type)
},
None => ("".to_string(), "".to_string(), Unknown)
None => (Some(""), Some(""), CommitType::Unknown)
};
let closes = lines.filter_map(|line| CLOSES_PATTERN.captures(line))
.map(|caps| caps.at(2).to_string())
.map(|caps| caps.at(2).unwrap().to_owned())
.collect();

LogEntry {
hash: hash,
subject: subject,
component: component,
subject: subject.unwrap().to_owned(),
component: component.unwrap().to_owned(),
closes: closes,
breaks: vec!(),
breaks: vec![],
commit_type: commit_type
}
}
49 changes: 27 additions & 22 deletions src/log_writer.rs
@@ -1,64 +1,68 @@
use std::collections::hashmap::HashMap;
use std::io::{Writer, IoResult};
use std::collections::HashMap;
use std::io::{Write, Result};
use time;
use format_util;
use common::{ LogEntry };
use std::borrow::ToOwned;

pub struct LogWriter<'a> {
writer: &'a mut Writer+'a,
options: LogWriterOptions<'a>
pub struct LogWriter<'a, 'lwo> {
writer: &'a mut (Write + 'a),
options: LogWriterOptions<'lwo>
}

pub struct LogWriterOptions<'a> {
pub repository_link: String,
pub repository_link: &'a str,
pub version: String,
pub subtitle: String
pub subtitle: String
}

impl<'a> LogWriter<'a> {
impl<'a, 'lwo> LogWriter<'a, 'lwo> {

fn commit_link(&self, hash: &String) -> String {
let short_hash = format_util::get_short_hash(hash.as_slice());
match self.options.repository_link.as_slice() {
fn commit_link(hash: &String, options: &LogWriterOptions) -> String {
let short_hash = format_util::get_short_hash(&hash[..]);
match &options.repository_link[..] {
"" => format!("({})", short_hash),
link => format!("[{}]({}/commit/{})", short_hash, link, hash)

}
}

fn issue_link(&self, issue: &String) -> String {
match self.options.repository_link.as_slice() {
match &self.options.repository_link[..] {
"" => format!("(#{})", issue),
link => format!("[#{}]({}/issues/{})", issue, link, issue)
}
}

pub fn write_header(&mut self) -> IoResult<()> {
pub fn write_header(&mut self) -> Result<()> {
let subtitle = match self.options.subtitle.len() {
0 => self.options.subtitle.clone(),
0 => self.options.subtitle.to_owned(),
_ => format!(" {}", self.options.subtitle)
};

let version_text = format!("## {}{}", self.options.version, subtitle);

let date = time::now_utc().strftime("%Y-%m-%d");
let date = time::now_utc();

write!(self.writer, "<a name=\"{}\"></a>\n{} ({})\n\n", self.options.version, version_text, date)
match date.strftime("%Y-%m-%d") {
Ok(date) => write!(self.writer, "<a name=\"{}\"></a>\n{} ({})\n\n", self.options.version, version_text, date),
Err(_) => write!(self.writer, "<a name=\"{}\"></a>\n{} ({})\n\n", self.options.version, version_text, "XXXX-XX-XX")
}
}

pub fn write_section(&mut self, title: &str, section: &HashMap<String, Vec<LogEntry>>)
-> IoResult<()> {
-> Result<()> {
if section.len() == 0 { return Ok(()) }

try!(self.writer.write_line(format!("\n#### {}\n\n", title).as_slice()));
try!(self.writer.write(&format!("\n#### {}\n\n", title)[..].as_bytes()));

for (component, entries) in section.iter() {
let nested = entries.len() > 1;

//TODO: implement the empty component stuff
let prefix = if nested {
try!(write!(self.writer, "* **{}**\n", component));
" *".to_string()
" *".to_owned()
} else {
format!("* **{}**", component)
};
Expand All @@ -67,7 +71,7 @@ impl<'a> LogWriter<'a> {
try!(write!(self.writer, "{} {} ({}",
prefix,
entry.subject,
self.commit_link(&entry.hash)));
LogWriter::commit_link(&entry.hash, &self.options)));

if entry.closes.len() > 0 {
let closes_string = entry.closes.iter()
Expand All @@ -88,12 +92,13 @@ impl<'a> LogWriter<'a> {
}


pub fn write(&mut self, content: &str) -> IoResult<()> {
pub fn write(&mut self, content: &str) -> Result<()> {
try!(write!(self.writer, "\n\n\n"));
write!(self.writer, "{}", content)
}

pub fn new<T:Writer + Send>(writer: &'a mut T, options: LogWriterOptions) -> LogWriter<'a> {
pub fn new<T>(writer: &'a mut T, options: LogWriterOptions<'lwo>) -> LogWriter<'a, 'lwo>
where T: Write + Send {
LogWriter {
writer: writer,
options: options
Expand Down

0 comments on commit d230dd8

Please sign in to comment.