Skip to content

Commit

Permalink
Remove dependency on deprecated error_chain
Browse files Browse the repository at this point in the history
  • Loading branch information
sourcefrog committed Nov 3, 2018
1 parent b8a8a3e commit 08ea0ba
Show file tree
Hide file tree
Showing 17 changed files with 118 additions and 107 deletions.
10 changes: 0 additions & 10 deletions Cargo.lock

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

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ doc = false # Conflicts with library docs which are more useful.
[dependencies]
chrono = "0.2"
clap = "2.32"
error-chain = "0.11"
isatty = "0.1"
rayon = "1.0.2"
regex = "0.2"
Expand Down
4 changes: 0 additions & 4 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,6 @@ Clean message, and test for it, when the archive directory just doesn't exist.

* Add a 'high-level' module similar to the CLI, but not coupled to it?

* Maybe don't use `error_chain`? I have an unjustified feeling it slows down
compilation. Perhaps use `Failure`.

* Report warnings by failures/errors that are passed to the UI rather than
returned.

Expand Down Expand Up @@ -213,7 +210,6 @@ and if pre-measuring is turned off we could stay in this mode.
* Make a macro like `try!` that logs when it sees an error?
* Errors to stderr rather than stdout?
Hard to reconcile with use of terminal for colored errors.
* Maybe have Conserve-specific error types rather than `io::Error` everywhere?

## Store/restore metadata

Expand Down
2 changes: 1 addition & 1 deletion copyright
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ Upstream-Contact: Martin Pool <[email protected]>
Source: https://github.com/sourcefrog/conserve

Files: *
Copyright: 2012-2016 Martin Pool
Copyright: 2012-2018 Martin Pool
Licence: GPL-2+
36 changes: 17 additions & 19 deletions src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,11 @@ impl Archive {
let header_filename = path.join(HEADER_FILENAME);
let report = Report::new();
jsonio::write(&header_filename, &header, &report)
.chain_err(|| format!("Failed to write archive header: {:?}", header_filename))?;
Ok(Archive {
path: path.to_path_buf(),
report,
block_dir,
})
.and(Ok(Archive {
path: path.to_path_buf(),
report,
block_dir,
}))
}

/// Open an existing archive.
Expand All @@ -64,15 +63,14 @@ impl Archive {
let path = path.as_ref();
let header_path = path.join(HEADER_FILENAME);
if !file_exists(&header_path)? {
return Err(ErrorKind::NotAnArchive(path.into()).into());
return Err(Error::NotAnArchive(path.into()));
}
let block_dir = BlockDir::new(&path.join(BLOCK_DIR));
let header: ArchiveHeader =
jsonio::read(&header_path, &report).chain_err(|| "Failed to read archive header")?;
let header: ArchiveHeader = jsonio::read(&header_path, &report)?;
if header.conserve_archive_version != ARCHIVE_VERSION {
return Err(
ErrorKind::UnsupportedArchiveVersion(header.conserve_archive_version).into(),
);
return Err(Error::UnsupportedArchiveVersion(
header.conserve_archive_version,
));
}
Ok(Archive {
path: path.to_path_buf(),
Expand Down Expand Up @@ -119,7 +117,7 @@ impl Archive {
};
}
}
l.ok_or_else(|| ErrorKind::ArchiveEmpty.into())
l.ok_or(Error::ArchiveEmpty)
}

/// Return the last completely-written band id.
Expand All @@ -130,7 +128,7 @@ impl Archive {
return Ok(b);
}
}
Err(ErrorKind::NoCompleteBands.into())
Err(Error::NoCompleteBands)
}

/// Return a sorted set containing all the blocks referenced by all bands.
Expand Down Expand Up @@ -171,7 +169,7 @@ mod tests {
use std::io::Read;

use super::*;
use errors::ErrorKind;
use errors::Error;
use test_fixtures::ScratchArchive;

#[test]
Expand Down Expand Up @@ -217,13 +215,13 @@ mod tests {
header_file.read_to_string(&mut contents).unwrap();
assert_eq!(contents, "{\"conserve_archive_version\":\"0.5\"}\n");

match *af.last_band_id().unwrap_err().kind() {
ErrorKind::ArchiveEmpty => (),
match af.last_band_id().unwrap_err() {
Error::ArchiveEmpty => (),
ref x => panic!("Unexpected error {:?}", x),
}

match *af.last_complete_band().unwrap_err().kind() {
ErrorKind::NoCompleteBands => (),
match af.last_complete_band().unwrap_err() {
Error::NoCompleteBands => (),
ref x => panic!("Unexpected error {:?}", x),
}

Expand Down
4 changes: 2 additions & 2 deletions src/band.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Band {
/// The Band gets the next id after those that already exist.
pub fn create(archive: &Archive) -> Result<Band> {
let new_band_id = match archive.last_band_id() {
Err(Error(ErrorKind::ArchiveEmpty, _)) => BandId::zero(),
Err(Error::ArchiveEmpty) => BandId::zero(),
Ok(b) => b.next_sibling(),
Err(e) => return Err(e),
};
Expand Down Expand Up @@ -240,7 +240,7 @@ mod tests {
let band_id = BandId::from_string("b0001").unwrap();
Band::create_specific_id(&af, band_id.clone()).unwrap();
let e = Band::create_specific_id(&af, band_id).unwrap_err();
if let ErrorKind::Io(ref ioerror) = *e.kind() {
if let Error::IoError(ref ioerror) = e {
assert_eq!(ioerror.kind(), io::ErrorKind::AlreadyExists);
} else {
panic!("expected an ioerror, got {:?}", e);
Expand Down
3 changes: 1 addition & 2 deletions src/bandid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl BandId {

/// Make a new BandId from a string form.
pub fn from_string(s: &str) -> Result<BandId> {
let nope = Err(ErrorKind::InvalidVersion.into());
let nope = Err(Error::InvalidVersion);
if !s.starts_with('b') {
return nope;
}
Expand All @@ -53,7 +53,6 @@ impl BandId {
if seqs.is_empty() {
nope
} else {
// This rebuilds a new string form to get it into the canonical form.
Ok(BandId::new(&seqs))
}
}
Expand Down
8 changes: 1 addition & 7 deletions src/bin/conserve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,8 @@ fn make_clap<'a, 'b>() -> clap::App<'a, 'b> {
}

fn show_chained_errors(report: &Report, e: &Error) {
// TODO: Implement this again when core error types have backtraces.
report.problem(&format!("{}", e));
for suberr in e.iter().skip(1) {
// First was already printed
report.problem(&format!(" {}", suberr));
}
if let Some(bt) = e.backtrace() {
report.problem(&format!("{:?}", bt));
}
}

fn init(subm: &ArgMatches, report: &Report) -> Result<()> {
Expand Down
4 changes: 2 additions & 2 deletions src/blockdir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ impl Block {
Err(e) => {
report.increment("block.corrupt", 1);
report.problem(&format!("Block file {:?} read error {:?}", self.path, e));
return Err(ErrorKind::BlockCorrupt(self.hash.to_string()).into());
return Err(Error::BlockCorrupt(self.path.clone()));
}
};
report.increment("block.read", 1);
Expand All @@ -337,7 +337,7 @@ impl Block {
"Block file {:?} has actual decompressed hash {:?}",
self.path, actual_hash
));
return Err(ErrorKind::BlockCorrupt(self.hash.to_string()).into());
return Err(Error::BlockCorrupt(self.path.clone()));
}
Ok(())
}
Expand Down
99 changes: 70 additions & 29 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,82 @@

//! Conserve error types.
use rustc_serialize;
use std::error;
use std::fmt;
use std::io;
use std::path::PathBuf;

use BandId;
use rustc_serialize;

error_chain! {
foreign_links {
Io(io::Error);
JsonDecode(rustc_serialize::json::DecoderError);
}
use super::*;

errors {
BlockCorrupt(block_hash: String) {
}
NotAnArchive(path: PathBuf) {
display("Not a Conserve archive: {:?}", path)
}
UnsupportedArchiveVersion(version: String) {
display("Unsupported archive version: {:?}", version)
}
DestinationNotEmpty(destination: PathBuf) {
display("Destination directory not empty: {:?}", destination)
}
ArchiveEmpty {
display("Archive is empty")
}
NoCompleteBands {
display("Archive has no complete bands")
}
InvalidVersion {
display("Invalid version number")
/// Conserve specific error.
#[derive(Debug)]
pub enum Error {
BlockCorrupt(PathBuf),
NotAnArchive(PathBuf),
NotADirectory(PathBuf),
NotAFile(PathBuf),
UnsupportedArchiveVersion(String),
DestinationNotEmpty(PathBuf),
ArchiveEmpty,
NoCompleteBands,
InvalidVersion,
BandIncomplete(BandId),
IoError(io::Error),
// TODO: Include the path in the json error.
JsonDecode(rustc_serialize::json::DecoderError),
BadGlob(globset::Error),
IndexCorrupt(PathBuf),
}

pub type Result<T> = std::result::Result<T, Error>;

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::DestinationNotEmpty(d) => write!(f, "Destination directory not empty: {:?}", d),
Error::ArchiveEmpty => write!(f, "Archive is empty"),
Error::NoCompleteBands => write!(f, "Archive has no complete bands"),
Error::InvalidVersion => write!(f, "Invalid version number"),
Error::NotAnArchive(p) => write!(f, "Not a Conserve archive: {:?}", p),
Error::BandIncomplete(b) => write!(f, "Band {} is incomplete", b),
Error::UnsupportedArchiveVersion(v) => write!(
f,
"Archive version {:?} is not supported by Conserve {}",
v,
version()
),
_ => write!(f, "{:?}", self),
}
BandIncomplete(band_id: BandId) {
display("Band {} is incomplete", band_id)
}
}

impl std::error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
match self {
Error::IoError(c) => Some(c),
Error::JsonDecode(c) => Some(c),
Error::BadGlob(c) => Some(c),
_ => None,
}
}
}

impl From<io::Error> for Error {
fn from(c: io::Error) -> Error {
Error::IoError(c)
}
}

impl From<globset::Error> for Error {
fn from(c: globset::Error) -> Error {
Error::BadGlob(c)
}
}

impl From<rustc_serialize::json::DecoderError> for Error {
fn from(c: rustc_serialize::json::DecoderError) -> Error {
Error::JsonDecode(c)
}
}
17 changes: 8 additions & 9 deletions src/excludes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@ use super::*;

pub fn from_strings<I: IntoIterator<Item = S>, S: AsRef<str>>(excludes: I) -> Result<GlobSet> {
let mut builder = GlobSetBuilder::new();
for e in excludes {
let exclude = e.as_ref();
builder.add(
Glob::new(exclude)
.chain_err(|| format!("Failed to parse exclude value: {}", exclude))?,
);
for i in excludes {
match Glob::new(i.as_ref()) {
Ok(g) => builder.add(g),
Err(e) => {
return Err(e.into());
}
};
}
builder
.build()
.chain_err(|| "Failed to build exclude patterns")
builder.build().or_else(|e| Err(e.into()))
}

pub fn excludes_nothing() -> GlobSet {
Expand Down
8 changes: 4 additions & 4 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,10 @@ impl Iter {
self.report.increment("index.hunk", 1);

let start_parse = Instant::now();
let index_json = str::from_utf8(&index_bytes)
.chain_err(|| format!("index file {:?} is not UTF-8", hunk_path))?;
let entries: Vec<IndexEntry> = json::decode(index_json)
.chain_err(|| format!("couldn't deserialize index hunk {:?}", hunk_path))?;
let index_json =
str::from_utf8(&index_bytes).or_else(|_| Err(Error::IndexCorrupt(hunk_path.clone())))?;
let entries: Vec<IndexEntry> =
json::decode(index_json).or_else(|e| Err(Error::JsonDecode(e)))?;
if entries.is_empty() {
self.report
.problem(&format!("Index hunk {} is empty", hunk_path.display()));
Expand Down
Loading

0 comments on commit 08ea0ba

Please sign in to comment.