aboutsummaryrefslogtreecommitdiff
path: root/ticket/src/actions.rs
diff options
context:
space:
mode:
authorMichael Gattozzi <mgattozzi@gmail.com>2019-12-02 17:31:33 -0500
committerMichael Gattozzi <mgattozzi@gmail.com>2019-12-03 11:47:05 -0500
commitfcd4ccbec30493872feba137342347541b6a4e28 (patch)
tree1a74b26b4d49c952252f8816f7a7f616ae8a0792 /ticket/src/actions.rs
parentb41ddc1c38ac64a8d63fe99ee86a888c2d7adfa9 (diff)
Upgrade ticket format from V0 to V1 to use UUIDs
This is a necessary upgrade to deal with the fact that incremental ids do not work in distributed systems. For instance say we have two branches from the same commit on master and they both add a new ticket. Both will have the same incremental ID despite being completely separate tickets. In this case we want to use UUIDs, specifically version 1 as defined in IETF RFC 4122. This version of UUID uses a timestamp to generate it and as a result the UUID it generates is *sortable*. This means that the UUIDs can be created whenever on any branch, be unique, and will be sortable by time. No matter when or where our tickets can be sorted correctly by this UUID in a deterministic order. Since we are also upgrading the code we've set up migration upgrade code to handle this in case we need to do this again in the future. We also add a few more fields and make some breaking changes since we already are for the UUIDs. Resources: - https://tools.ietf.org/html/rfc4122
Diffstat (limited to 'ticket/src/actions.rs')
-rw-r--r--ticket/src/actions.rs65
1 files changed, 59 insertions, 6 deletions
diff --git a/ticket/src/actions.rs b/ticket/src/actions.rs
index 381c9f7..3e237ff 100644
--- a/ticket/src/actions.rs
+++ b/ticket/src/actions.rs
@@ -1,5 +1,11 @@
-use crate::Ticket;
-use anyhow::Result;
+use crate::{
+ Ticket,
+ TicketV0,
+};
+use anyhow::{
+ bail,
+ Result,
+};
use log::*;
use shared::find_root;
use std::{
@@ -8,11 +14,11 @@ use std::{
};
pub fn get_open_tickets() -> Result<Vec<Ticket>> {
- get_tickets(ticket_root()?.join("open"))
+ get_tickets(open_tickets()?)
}
pub fn get_closed_tickets() -> Result<Vec<Ticket>> {
- get_tickets(ticket_root()?.join("closed"))
+ get_tickets(closed_tickets()?)
}
fn get_tickets(path: PathBuf) -> Result<Vec<Ticket>> {
@@ -24,13 +30,60 @@ fn get_tickets(path: PathBuf) -> Result<Vec<Ticket>> {
trace!("Looking at entry {}.", path.display());
if path.is_file() {
trace!("Entry is a file.");
- out.push(toml::from_slice::<Ticket>(&fs::read(&path)?)?);
+ match toml::from_slice::<Ticket>(&fs::read(&path)?) {
+ Ok(ticket) => out.push(ticket),
+ Err(e) => {
+ error!("Failed to parse ticket {}", path.canonicalize()?.display());
+ error!("Is the file an old ticket format? You might need to run `ticket migrate`.");
+ bail!("Underlying error was {}", e);
+ }
+ }
}
}
- out.sort_by(|a, b| a.number.cmp(&b.number));
+ out.sort_by(|a, b| a.id.cmp(&b.id));
Ok(out)
}
pub fn ticket_root() -> Result<PathBuf> {
Ok(find_root()?.join(".dev-suite").join("ticket"))
}
+
+pub fn closed_tickets() -> Result<PathBuf> {
+ Ok(ticket_root()?.join("closed"))
+}
+
+pub fn open_tickets() -> Result<PathBuf> {
+ Ok(ticket_root()?.join("open"))
+}
+
+// Old version ticket code to handle grabbing code
+pub fn get_all_ticketsv0() -> Result<Vec<TicketV0>> {
+ let mut tickets = get_open_ticketsv0()?;
+ tickets.extend(get_closed_ticketsv0()?);
+ Ok(tickets)
+}
+pub fn get_open_ticketsv0() -> Result<Vec<TicketV0>> {
+ get_ticketsv0(open_tickets()?)
+}
+
+pub fn get_closed_ticketsv0() -> Result<Vec<TicketV0>> {
+ get_ticketsv0(closed_tickets()?)
+}
+
+fn get_ticketsv0(path: PathBuf) -> Result<Vec<TicketV0>> {
+ let mut out = Vec::new();
+ debug!("Looking for ticket.");
+ for entry in fs::read_dir(&path)? {
+ let entry = entry?;
+ let path = entry.path();
+ trace!("Looking at entry {}.", path.display());
+ if path.is_file() {
+ trace!("Entry is a file.");
+ if let Ok(ticket) = toml::from_slice::<TicketV0>(&fs::read(&path)?) {
+ out.push(ticket);
+ }
+ }
+ }
+ out.sort_by(|a, b| a.number.cmp(&b.number));
+ Ok(out)
+}