All in one module

master
Dennis Schwerdel 2018-02-24 23:28:18 +01:00
parent a81aaae637
commit 6f9611bba6
18 changed files with 2191 additions and 246 deletions

2
.gitignore vendored
View File

@ -7,4 +7,6 @@ excludes
._*
.~*
docs/logo
lang/*.mo
lang/default.pot
.idea

18
Cargo.lock generated
View File

@ -67,13 +67,6 @@ dependencies = [
"time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "chunking"
version = "0.1.0"
dependencies = [
"quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.30.0"
@ -134,14 +127,6 @@ dependencies = [
"time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "index"
version = "0.1.0"
dependencies = [
"mmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@ -590,17 +575,16 @@ dependencies = [
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chunking 0.1.0",
"clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"index 0.1.0",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libsodium-sys 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"locale_config 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"pbr 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -4,6 +4,9 @@ version = "0.4.0"
authors = ["Dennis Schwerdel <schwerdel@googlemail.com>"]
description = "Deduplicating backup tool"
[profile.release]
lto = true
[dependencies]
serde = "1.0"
rmp-serde = "0.13"
@ -35,8 +38,7 @@ time = "*"
libc = "0.2"
runtime-fmt = "0.3"
locale_config = "^0.2.2"
index = {path="index"}
chunking = {path="chunking"}
mmap = "0.1"
[features]
default = []

14
chunking/Cargo.lock generated
View File

@ -1,14 +0,0 @@
[[package]]
name = "chunking"
version = "0.1.0"
dependencies = [
"quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quick-error"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"

View File

@ -1,7 +0,0 @@
[package]
name = "chunking"
version = "0.1.0"
authors = ["Dennis Schwerdel <schwerdel@googlemail.com>"]
[dependencies]
quick-error = "1.1"

134
index/Cargo.lock generated
View File

@ -1,134 +0,0 @@
[[package]]
name = "bitflags"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "index"
version = "0.1.0"
dependencies = [
"mmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mmap"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quick-error"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "remove_dir_all"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tempdir"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
"checksum mmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc85448a6006dd2ba26a385a564a8a0f1f2c7e78c70f1a70b2e0f4af286b823"
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
"checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5"
"checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -1,8 +0,0 @@
[package]
name = "index"
version = "0.1.0"
authors = ["Dennis Schwerdel <schwerdel@googlemail.com>"]
[dependencies]
mmap = "0.1"
quick-error = "1.1"

2116
lang/default.pot Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ use std::ptr;
pub struct AeChunker {
buffer: [u8; 4096],
buffer: [u8; 0x1000],
buffered: usize,
window_size: usize
}
@ -18,7 +18,7 @@ impl AeChunker {
//let window_size = (avg_size as f64 / (consts::E - 1.0)) as usize;
let window_size = avg_size - 256;
AeChunker{
buffer: [0; 4096],
buffer: [0; 0x1000],
buffered: 0,
window_size: window_size,
}

View File

@ -1,8 +1,3 @@
#![feature(test)]
extern crate test;
extern crate chunking;
use chunking::*;
use std::io::{self, Write, Cursor};

View File

@ -13,8 +13,8 @@ use std::cmp;
// Creating 256 pseudo-random values (based on Knuth's MMIX)
fn create_gear(seed: u64) -> [u64; 256] {
let mut table = [0u64; 256];
let a = 6364136223846793005;
let c = 1442695040888963407;
let a = 6_364_136_223_846_793_005;
let c = 1_442_695_040_888_963_407;
let mut v = seed;
for t in &mut table.iter_mut() {
v = v.wrapping_mul(a).wrapping_add(c);
@ -27,12 +27,12 @@ fn get_masks(avg_size: usize, nc_level: usize, seed: u64) -> (u64, u64) {
let bits = (avg_size.next_power_of_two() - 1).count_ones();
if bits == 13 {
// From the paper
return (0x0003590703530000, 0x0000d90003530000);
return (0x0003_5907_0353_0000, 0x0000_d900_0353_0000);
}
let mut mask = 0u64;
let mut v = seed;
let a = 6364136223846793005;
let c = 1442695040888963407;
let a = 6_364_136_223_846_793_005;
let c = 1_442_695_040_888_963_407;
while mask.count_ones() < bits - nc_level as u32 {
v = v.wrapping_mul(a).wrapping_add(c);
mask = (mask | 1).rotate_left(v as u32 & 0x3f);
@ -47,7 +47,7 @@ fn get_masks(avg_size: usize, nc_level: usize, seed: u64) -> (u64, u64) {
}
pub struct FastCdcChunker {
buffer: [u8; 4096],
buffer: [u8; 0x1000],
buffered: usize,
gear: [u64; 256],
min_size: usize,
@ -61,7 +61,7 @@ impl FastCdcChunker {
pub fn new(avg_size: usize, seed: u64) -> Self {
let (mask_short, mask_long) = get_masks(avg_size, 2, seed);
FastCdcChunker {
buffer: [0; 4096],
buffer: [0; 0x1000],
buffered: 0,
gear: create_gear(seed),
min_size: avg_size/4,

View File

@ -4,14 +4,14 @@ use std::cmp::min;
pub struct FixedChunker {
buffer: [u8; 4096],
buffer: [u8; 0x1000],
size: usize
}
impl FixedChunker {
pub fn new(avg_size: usize) -> FixedChunker {
FixedChunker{
buffer: [0; 4096],
buffer: [0; 0x1000],
size: avg_size,
}
}

View File

@ -1,11 +1,11 @@
#[macro_use] extern crate quick_error;
use std::io::{self, Write, Read};
mod fixed;
mod ae;
mod rabin;
mod fastcdc;
#[cfg(test)] mod test;
#[cfg(feature = "bench")] mod benches;
pub use self::fixed::FixedChunker;
pub use self::ae::AeChunker;
@ -25,18 +25,18 @@ quick_error!{
pub enum ChunkerError {
Read(err: io::Error) {
cause(err)
description("Failed to read input")
display("Chunker error: failed to read input\n\tcaused by: {}", err)
description(tr!("Failed to read input"))
display("{}", tr_format!("Chunker error: failed to read input\n\tcaused by: {}", err))
}
Write(err: io::Error) {
cause(err)
description("Failed to write to output")
display("Chunker error: failed to write to output\n\tcaused by: {}", err)
description(tr!("Failed to write to output"))
display("{}", tr_format!("Chunker error: failed to write to output\n\tcaused by: {}", err))
}
Custom(reason: &'static str) {
from()
description("Custom error")
display("Chunker error: {}", reason)
description(tr!("Custom error"))
display("{}", tr_format!("Chunker error: {}", reason))
}
}
}

View File

@ -34,7 +34,7 @@ fn create_table(alpha: u32, window_size: usize) -> [u32; 256] {
pub struct RabinChunker {
buffer: [u8; 4096],
buffer: [u8; 0x1000],
buffered: usize,
seed: u32,
alpha: u32,
@ -50,9 +50,9 @@ impl RabinChunker {
pub fn new(avg_size: usize, seed: u32) -> Self {
let chunk_mask = (avg_size as u32).next_power_of_two() - 1;
let window_size = avg_size/4-1;
let alpha = 1664525;//153191;
let alpha = 1_664_525;//153191;
RabinChunker {
buffer: [0; 4096],
buffer: [0; 0x1000],
buffered: 0,
table: create_table(alpha, window_size),
alpha: alpha,
@ -88,7 +88,7 @@ impl Chunker for RabinChunker {
return Ok(ChunkerStatus::Continue);
}
// Hash update
hash = hash.wrapping_mul(self.alpha).wrapping_add(val as u32);
hash = hash.wrapping_mul(self.alpha).wrapping_add(u32::from(val));
if pos >= self.window_size {
let take = window.pop_front().unwrap();
hash = hash.wrapping_sub(self.table[take as usize]);

View File

@ -1,6 +1,4 @@
extern crate chunking;
use chunking::*;
use super::*;
use std::io::Cursor;

View File

@ -1,6 +1,3 @@
extern crate mmap;
#[macro_use] extern crate quick_error;
use std::path::Path;
use std::fs::{File, OpenOptions};
use std::mem;
@ -17,36 +14,37 @@ pub const MIN_USAGE: f64 = 0.35;
pub const INITIAL_SIZE: usize = 1024;
//TODO: translate
quick_error!{
#[derive(Debug)]
pub enum IndexError {
Io(err: io::Error) {
from()
cause(err)
description("Failed to open index file")
display("Index error: failed to open the index file\n\tcaused by: {}", err)
description(tr!("Failed to open index file"))
display("{}", tr_format!("Index error: failed to open the index file\n\tcaused by: {}", err))
}
Mmap(err: MapError) {
from()
cause(err)
description("Failed to memory-map the index file")
display("Index error: failed to memory-map the index file\n\tcaused by: {}", err)
description(tr!("Failed to memory-map the index file"))
display("{}", tr_format!("Index error: failed to memory-map the index file\n\tcaused by: {}", err))
}
WrongMagic {
description("Wrong header")
display("Index error: file has the wrong magic header")
description(tr!("Wrong header"))
display("{}", tr!("Index error: file has the wrong magic header"))
}
UnsupportedVersion(version: u8) {
description("Unsupported version")
display("Index error: index file has unsupported version: {}", version)
description(tr!("Unsupported version"))
display("{}", tr_format!("Index error: index file has unsupported version: {}", version))
}
WrongPosition(should: usize, is: LocateResult) {
description("Key at wrong position")
display("Index error: key has wrong position, expected at: {}, but is at: {:?}", should, is)
description(tr!("Key at wrong position"))
display("{}", tr_format!("Index error: key has wrong position, expected at: {}, but is at: {:?}", should, is))
}
WrongEntryCount(header: usize, actual: usize) {
description("Wrong entry count")
display("Index error: index has wrong entry count, expected {}, but is {}", header, actual)
description(tr!("Wrong entry count"))
display("{}", tr_format!("Index error: index has wrong entry count, expected {}, but is {}", header, actual))
}
}
}
@ -72,7 +70,7 @@ pub trait Value: Clone + Copy + Default {}
#[repr(packed)]
#[derive(Clone, Default)]
#[derive(Default)]
pub struct Entry<K, V> {
pub key: K,
pub data: V
@ -81,12 +79,23 @@ pub struct Entry<K, V> {
impl<K: Key, V> Entry<K, V> {
#[inline]
fn is_used(&self) -> bool {
self.key.is_used()
unsafe { self.key.is_used() }
}
#[inline]
fn clear(&mut self) {
self.key.clear()
unsafe { self.key.clear() }
}
}
impl<K: Clone, V: Clone> Clone for Entry<K, V> {
fn clone(&self) -> Self {
unsafe {
Entry {
key: self.key.clone(),
data: self.data.clone()
}
}
}
}
@ -106,13 +115,14 @@ impl<'a, K: Key, V> Iterator for Iter<'a, K, V> {
while let Some((first, rest)) = self.0.split_first() {
self.0 = rest;
if first.is_used() {
return Some((&first.key, &first.data));
unsafe { return Some((&first.key, &first.data)) }
}
}
None
}
}
#[allow(dead_code)]
pub struct IterMut<'a, K: 'static, V: 'static> (&'a mut [Entry<K, V>]);
impl<'a, K: Key, V> Iterator for IterMut<'a, K, V> {
@ -125,7 +135,7 @@ impl<'a, K: Key, V> Iterator for IterMut<'a, K, V> {
Some((first, rest)) => {
self.0 = rest;
if first.is_used() {
return Some((&first.key, &mut first.data))
unsafe { return Some((&first.key, &mut first.data)) }
}
}
}
@ -137,7 +147,7 @@ impl<'a, K: Key, V> Iterator for IterMut<'a, K, V> {
/// This method is unsafe as it potentially creates references to uninitialized memory
unsafe fn mmap_as_ref<K, V>(mmap: &MemoryMap, len: usize) -> (&'static mut Header, &'static mut [Entry<K, V>]) {
if mmap.len() < mem::size_of::<Header>() + len * mem::size_of::<Entry<K, V>>() {
panic!("Memory map too small");
tr_panic!("Memory map too small");
}
let header = &mut *(mmap.data() as *mut Header);
let ptr = mmap.data().offset(mem::size_of::<Header>() as isize) as *mut Entry<K, V>;
@ -197,7 +207,7 @@ impl<K: Key, V: Value> Index<K, V> {
data: data,
header: header
};
debug_assert!(index.check().is_ok(), "Inconsistent after creation");
debug_assert!(index.check().is_ok(), tr!("Inconsistent after creation"));
Ok(index)
}
@ -302,7 +312,7 @@ impl<K: Key, V: Value> Index<K, V> {
continue;
}
entries += 1;
match self.locate(&entry.key) {
match unsafe { self.locate(&entry.key) } {
LocateResult::Found(p) if p == pos => true,
found => return Err(IndexError::WrongPosition(pos, found))
};
@ -431,7 +441,7 @@ impl<K: Key, V: Value> Index<K, V> {
#[inline]
pub fn contains(&self, key: &K) -> bool {
debug_assert!(self.check().is_ok(), "Inconsistent before get");
debug_assert!(self.check().is_ok(), tr!("Inconsistent before get"));
match self.locate(key) {
LocateResult::Found(_) => true,
_ => false
@ -440,7 +450,7 @@ impl<K: Key, V: Value> Index<K, V> {
#[inline]
pub fn pos(&self, key: &K) -> Option<usize> {
debug_assert!(self.check().is_ok(), "Inconsistent before get");
debug_assert!(self.check().is_ok(), tr!("Inconsistent before get"));
match self.locate(key) {
LocateResult::Found(pos) => Some(pos),
_ => None
@ -449,7 +459,7 @@ impl<K: Key, V: Value> Index<K, V> {
#[inline]
pub fn get(&self, key: &K) -> Option<V> {
debug_assert!(self.check().is_ok(), "Inconsistent before get");
debug_assert!(self.check().is_ok(), tr!("Inconsistent before get"));
match self.locate(key) {
LocateResult::Found(pos) => Some(self.data[pos].data),
_ => None
@ -457,11 +467,12 @@ impl<K: Key, V: Value> Index<K, V> {
}
#[inline]
#[allow(dead_code)]
pub fn modify<F>(&mut self, key: &K, mut f: F) -> bool where F: FnMut(&mut V) {
debug_assert!(self.check().is_ok(), "Inconsistent before get");
debug_assert!(self.check().is_ok(), tr!("Inconsistent before get"));
match self.locate(key) {
LocateResult::Found(pos) => {
f(&mut self.data[pos].data);
unsafe { f(&mut self.data[pos].data) };
true
},
_ => false

View File

@ -36,11 +36,10 @@ extern crate pbr;
extern crate users;
extern crate libc;
extern crate tar;
extern crate index;
extern crate chunking;
#[macro_use]
extern crate runtime_fmt;
extern crate locale_config;
extern crate mmap;
#[macro_use] mod translation;
pub mod util;
@ -50,6 +49,8 @@ mod cli;
mod prelude;
mod mount;
mod chunker;
mod chunking;
mod index;
use std::process::exit;

View File

@ -39,7 +39,6 @@ const INDEX_MAGIC: [u8; 7] = *b"zvault\x02";
const INDEX_VERSION: u8 = 1;
#[repr(packed)]
#[derive(Clone, Copy, PartialEq, Debug, Default)]
pub struct Location {
pub bundle: u32,
@ -178,7 +177,7 @@ impl Repository {
if !rebuild_bundle_map {
let mut save_bundle_map = false;
if !gone.is_empty() {
tr_info!("Removig {} old bundles from index", gone.len());
tr_info!("Removing {} old bundles from index", gone.len());
try!(repo.write_mode());
for bundle in gone {
try!(repo.remove_gone_remote_bundle(&bundle))