mononoke: add separate types for Bookmark and BookmarkPrefix

Summary:
This will make it easier to change the "real" bookmark type from AsciiString to
String if we decide to do that.

BookmarkPrefix is a separate type because we may want to change it from
AsciiString to String. Also we don't want to confuse a bookmark prefix with a
bookmark name.

Reviewed By: jsgf

Differential Revision: D7909992

fbshipit-source-id: 3d4d075c204ed5ef1114a743430982c2836bac04
This commit is contained in:
Stanislau Hlebik 2018-05-09 01:53:55 -07:00 committed by Facebook Github Bot
parent a29aac3469
commit e99fce6bd4
10 changed files with 153 additions and 77 deletions

View File

@ -12,7 +12,6 @@ use std::thread;
use std::time::Duration;
use std::usize;
use ascii::AsciiString;
use db::{get_connection_params, InstanceRequirement, ProxyRequirement};
use failure::{Fail, ResultExt};
use futures::{Async, Poll};
@ -26,7 +25,7 @@ use time_ext::DurationExt;
use uuid::Uuid;
use blobstore::{Blobstore, CachingBlobstore};
use bookmarks::{self, Bookmarks};
use bookmarks::{self, Bookmark, BookmarkPrefix, Bookmarks};
use changesets::{CachingChangests, ChangesetInsert, Changesets, MysqlChangesets, SqliteChangesets};
use dbbookmarks::{MysqlDbBookmarks, SqliteDbBookmarks};
use delayblob::DelayBlob;
@ -299,7 +298,7 @@ impl BlobRepo {
pub fn get_heads(&self) -> impl Stream<Item = DNodeHash, Error = Error> {
self.bookmarks
.list_by_prefix(&AsciiString::default(), &self.repoid)
.list_by_prefix(&BookmarkPrefix::empty(), &self.repoid)
.map(|(_, cs)| cs.into_nodehash())
}
@ -348,14 +347,14 @@ impl BlobRepo {
Box::new(HgBlobEntry::new_root(self.blobstore.clone(), *manifestid))
}
pub fn get_bookmark(&self, name: &AsciiString) -> BoxFuture<Option<DChangesetId>, Error> {
pub fn get_bookmark(&self, name: &Bookmark) -> BoxFuture<Option<DChangesetId>, Error> {
self.bookmarks.get(name, &self.repoid)
}
// TODO(stash): rename to get_all_bookmarks()?
pub fn get_bookmarks(&self) -> BoxStream<(AsciiString, DChangesetId), Error> {
let empty_prefix = AsciiString::new();
self.bookmarks.list_by_prefix(&empty_prefix, &self.repoid)
pub fn get_bookmarks(&self) -> BoxStream<(Bookmark, DChangesetId), Error> {
self.bookmarks
.list_by_prefix(&BookmarkPrefix::empty(), &self.repoid)
}
pub fn update_bookmark_transaction(&self) -> Box<bookmarks::Transaction> {

View File

@ -25,8 +25,7 @@ extern crate storage_types;
mod schema;
mod models;
use ascii::AsciiString;
use bookmarks::{Bookmarks, Transaction};
use bookmarks::{Bookmark, BookmarkPrefix, Bookmarks, Transaction};
use diesel::{delete, insert_into, replace_into, update, MysqlConnection, SqliteConnection};
use diesel::connection::SimpleConnection;
use diesel::prelude::*;
@ -136,16 +135,15 @@ macro_rules! impl_bookmarks {
impl Bookmarks for $struct {
fn get(
&self,
name: &AsciiString,
name: &Bookmark,
repo_id: &RepositoryId,
) -> BoxFuture<Option<DChangesetId>, Error> {
#[allow(unreachable_code, unreachable_patterns)] // sqlite can't fail
let connection = try_boxfuture!(self.get_conn());
let name = name.as_str().to_string();
schema::bookmarks::table
.filter(schema::bookmarks::repo_id.eq(repo_id))
.filter(schema::bookmarks::name.eq(name))
.filter(schema::bookmarks::name.eq(name.to_string()))
.select(schema::bookmarks::changeset_id)
.first::<DChangesetId>(&*connection)
.optional()
@ -156,9 +154,9 @@ macro_rules! impl_bookmarks {
fn list_by_prefix(
&self,
prefix: &AsciiString,
prefix: &BookmarkPrefix,
repo_id: &RepositoryId,
) -> BoxStream<(AsciiString, DChangesetId), Error> {
) -> BoxStream<(Bookmark, DChangesetId), Error> {
#[allow(unreachable_code, unreachable_patterns)] // sqlite can't fail
let connection = match self.get_conn() {
Ok(conn) => conn,
@ -167,10 +165,9 @@ macro_rules! impl_bookmarks {
},
};
let prefix = prefix.as_str().to_string();
let query = schema::bookmarks::table
.filter(schema::bookmarks::repo_id.eq(repo_id))
.filter(schema::bookmarks::name.like(format!("{}%", prefix)));
.filter(schema::bookmarks::name.like(format!("{}%", prefix.to_string())));
query
.get_results::<models::BookmarkRow>(&*connection)
@ -183,7 +180,7 @@ macro_rules! impl_bookmarks {
})
.from_err()
.flatten_stream()
.and_then(|entry| Ok((AsciiString::from_ascii(entry.0)?, entry.1)))
.and_then(|entry| Ok((Bookmark::new(entry.0)?, entry.1)))
.boxify()
}
@ -197,11 +194,11 @@ macro_rules! impl_bookmarks {
struct $transaction_struct {
db: $struct,
force_sets: HashMap<AsciiString, DChangesetId>,
creates: HashMap<AsciiString, DChangesetId>,
sets: HashMap<AsciiString, BookmarkSetData>,
force_deletes: HashSet<AsciiString>,
deletes: HashMap<AsciiString, DChangesetId>,
force_sets: HashMap<Bookmark, DChangesetId>,
creates: HashMap<Bookmark, DChangesetId>,
sets: HashMap<Bookmark, BookmarkSetData>,
force_deletes: HashSet<Bookmark>,
deletes: HashMap<Bookmark, DChangesetId>,
repo_id: RepositoryId,
}
@ -218,7 +215,7 @@ macro_rules! impl_bookmarks {
}
}
fn check_if_bookmark_already_used(&self, key: &AsciiString) -> Result<()> {
fn check_if_bookmark_already_used(&self, key: &Bookmark) -> Result<()> {
if self.creates.contains_key(key) || self.force_sets.contains_key(key)
|| self.sets.contains_key(key) || self.force_deletes.contains(key)
|| self.deletes.contains_key(key)
@ -232,7 +229,7 @@ macro_rules! impl_bookmarks {
impl Transaction for $transaction_struct {
fn update(
&mut self,
key: &AsciiString,
key: &Bookmark,
new_cs: &DChangesetId,
old_cs: &DChangesetId,
) -> Result<()> {
@ -247,25 +244,25 @@ macro_rules! impl_bookmarks {
Ok(())
}
fn create(&mut self, key: &AsciiString, new_cs: &DChangesetId) -> Result<()> {
fn create(&mut self, key: &Bookmark, new_cs: &DChangesetId) -> Result<()> {
self.check_if_bookmark_already_used(key)?;
self.creates.insert(key.clone(), *new_cs);
Ok(())
}
fn force_set(&mut self, key: &AsciiString, new_cs: &DChangesetId) -> Result<()> {
fn force_set(&mut self, key: &Bookmark, new_cs: &DChangesetId) -> Result<()> {
self.check_if_bookmark_already_used(key)?;
self.force_sets.insert(key.clone(), *new_cs);
Ok(())
}
fn delete(&mut self, key: &AsciiString, old_cs: &DChangesetId) -> Result<()> {
fn delete(&mut self, key: &Bookmark, old_cs: &DChangesetId) -> Result<()> {
self.check_if_bookmark_already_used(key)?;
self.deletes.insert(key.clone(), *old_cs);
Ok(())
}
fn force_delete(&mut self, key: &AsciiString) -> Result<()> {
fn force_delete(&mut self, key: &Bookmark) -> Result<()> {
self.check_if_bookmark_already_used(key)?;
self.force_deletes.insert(key.clone());
Ok(())
@ -285,7 +282,7 @@ macro_rules! impl_bookmarks {
.execute(&*connection)?;
for (key, &BookmarkSetData { new_cs, old_cs }) in self.sets.iter() {
let key = key.as_str().to_string();
let key = key.to_string();
let num_affected_rows = update(
schema::bookmarks::table
.filter(schema::bookmarks::name.eq(key.clone()))
@ -298,13 +295,13 @@ macro_rules! impl_bookmarks {
}
for key in self.force_deletes.iter() {
let key = key.as_str().to_string();
let key = key.to_string();
delete(schema::bookmarks::table.filter(schema::bookmarks::name.eq(key)))
.execute(&*connection)?;
}
for (key, old_cs) in self.deletes.iter() {
let key = key.as_str().to_string();
let key = key.to_string();
let num_deleted_rows = delete(
schema::bookmarks::table
.filter(schema::bookmarks::name.eq(key.clone()))
@ -332,12 +329,12 @@ struct BookmarkSetData {
fn create_bookmarks_rows(
repo_id: RepositoryId,
map: &HashMap<AsciiString, DChangesetId>,
map: &HashMap<Bookmark, DChangesetId>,
) -> Vec<models::BookmarkRow> {
map.iter()
.map(|(name, changeset_id)| models::BookmarkRow {
repo_id,
name: name.as_str().to_string(),
name: name.to_string(),
changeset_id: *changeset_id,
})
.collect()

View File

@ -20,11 +20,19 @@ extern crate mercurial_types;
extern crate mercurial_types_mocks;
extern crate tokio;
use ascii::AsciiString;
use bookmarks::{Bookmark, BookmarkPrefix};
use dbbookmarks::{MysqlDbBookmarks, SqliteDbBookmarks};
use mercurial_types_mocks::nodehash::{ONES_CSID, TWOS_CSID};
use mercurial_types_mocks::repo::REPO_ZERO;
fn create_bookmark(book: &str) -> Bookmark {
Bookmark::new(book.to_string()).unwrap()
}
fn create_prefix(book: &str) -> BookmarkPrefix {
BookmarkPrefix::new(book.to_string()).unwrap()
}
macro_rules! bookmarks_test_impl {
($mod_name: ident => {
new: $new_cb: expr,
@ -39,8 +47,8 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_simple_unconditional_set_get() {
let bookmarks = $new_cb();
let name_correct = AsciiString::from_ascii("book".to_string()).unwrap();
let name_incorrect = AsciiString::from_ascii("book2".to_string()).unwrap();
let name_correct = create_bookmark("book");
let name_incorrect = create_bookmark("book2");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.force_set(&name_correct, &ONES_CSID).unwrap();
@ -59,8 +67,8 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_multi_unconditional_set_get() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_2 = AsciiString::from_ascii("book2".to_string()).unwrap();
let name_1 = create_bookmark("book");
let name_2 = create_bookmark("book2");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.force_set(&name_1, &ONES_CSID).unwrap();
@ -80,7 +88,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_unconditional_set_same_bookmark() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.force_set(&name_1, &ONES_CSID).unwrap();
@ -99,7 +107,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_simple_create() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.create(&name_1, &ONES_CSID).unwrap();
@ -114,7 +122,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_create_already_existing() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.create(&name_1, &ONES_CSID).unwrap();
@ -128,7 +136,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_create_change_same_bookmark() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.create(&name_1, &ONES_CSID).unwrap();
@ -166,7 +174,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_simple_update_bookmark() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.create(&name_1, &ONES_CSID).unwrap();
@ -185,7 +193,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_update_non_existent_bookmark() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.update(&name_1, &TWOS_CSID, &ONES_CSID).unwrap();
@ -195,7 +203,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_update_existing_bookmark_with_incorrect_commit() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.create(&name_1, &ONES_CSID).unwrap();
@ -209,7 +217,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_force_delete() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.force_delete(&name_1).unwrap();
@ -232,7 +240,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_delete() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.delete(&name_1, &ONES_CSID).unwrap();
@ -251,7 +259,7 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_delete_incorrect_hash() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book".to_string()).unwrap();
let name_1 = create_bookmark("book");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.create(&name_1, &ONES_CSID).unwrap();
@ -266,15 +274,17 @@ macro_rules! bookmarks_test_impl {
#[test]
fn test_list_by_prefix() {
let bookmarks = $new_cb();
let name_1 = AsciiString::from_ascii("book1".to_string()).unwrap();
let name_2 = AsciiString::from_ascii("book2".to_string()).unwrap();
let name_1 = create_bookmark("book1");
let name_2 = create_bookmark("book2");
let mut txn = bookmarks.create_transaction(&REPO_ZERO);
txn.create(&name_1, &ONES_CSID).unwrap();
txn.create(&name_2, &ONES_CSID).unwrap();
txn.commit().wait().unwrap();
let prefix = AsciiString::from_ascii("book".to_string()).unwrap();
let prefix = create_prefix("book");
let name_1_prefix = create_prefix("book1");
let name_2_prefix = create_prefix("book2");
assert_eq!(
bookmarks
.list_by_prefix(&prefix, &REPO_ZERO)
@ -286,7 +296,7 @@ macro_rules! bookmarks_test_impl {
assert_eq!(
bookmarks
.list_by_prefix(&name_1, &REPO_ZERO)
.list_by_prefix(&name_1_prefix, &REPO_ZERO)
.collect()
.wait()
.unwrap(),
@ -295,7 +305,7 @@ macro_rules! bookmarks_test_impl {
assert_eq!(
bookmarks
.list_by_prefix(&name_2, &REPO_ZERO)
.list_by_prefix(&name_2_prefix, &REPO_ZERO)
.collect()
.wait()
.unwrap(),

View File

@ -7,22 +7,92 @@
#![deny(warnings)]
extern crate ascii;
#[macro_use]
extern crate failure_ext as failure;
extern crate futures_ext;
extern crate mercurial_types;
use std::fmt;
use ascii::AsciiString;
use failure::{Error, Result};
use futures_ext::{BoxFuture, BoxStream};
use mercurial_types::{DChangesetId, RepositoryId};
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Bookmark {
bookmark: AsciiString,
}
impl fmt::Display for Bookmark {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.bookmark)
}
}
impl Bookmark {
pub fn new<B: AsRef<str>>(bookmark: B) -> Result<Self> {
Ok(Self {
bookmark: AsciiString::from_ascii(bookmark.as_ref())
.map_err(|bytes| format_err!("non-ascii bookmark name: {:?}", bytes))?,
})
}
pub fn new_ascii(bookmark: AsciiString) -> Self {
Self { bookmark }
}
pub fn to_ascii(&self) -> Result<AsciiString> {
Ok(self.bookmark.clone())
}
pub fn to_string(&self) -> String {
self.bookmark.clone().into()
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct BookmarkPrefix {
bookmark_prefix: AsciiString,
}
impl fmt::Display for BookmarkPrefix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.bookmark_prefix)
}
}
impl BookmarkPrefix {
pub fn new<B: AsRef<str>>(bookmark_prefix: B) -> Result<Self> {
Ok(Self {
bookmark_prefix: AsciiString::from_ascii(bookmark_prefix.as_ref())
.map_err(|bytes| format_err!("non-ascii bookmark prefix: {:?}", bytes))?,
})
}
pub fn new_ascii(bookmark_prefix: AsciiString) -> Self {
Self { bookmark_prefix }
}
pub fn empty() -> Self {
Self {
bookmark_prefix: AsciiString::default(),
}
}
pub fn to_ascii(&self) -> Result<AsciiString> {
Ok(self.bookmark_prefix.clone())
}
pub fn to_string(&self) -> String {
self.bookmark_prefix.clone().into()
}
}
pub trait Bookmarks: Send + Sync + 'static {
/// Returns Some(DChangesetId) if bookmark exists, returns None if doesn't
fn get(
&self,
name: &AsciiString,
repoid: &RepositoryId,
) -> BoxFuture<Option<DChangesetId>, Error>;
fn get(&self, name: &Bookmark, repoid: &RepositoryId)
-> BoxFuture<Option<DChangesetId>, Error>;
/// Lists the bookmarks that match the prefix with bookmark's values.
/// Empty prefix means list all of the available bookmarks
@ -30,9 +100,9 @@ pub trait Bookmarks: Send + Sync + 'static {
/// listing all the bookmarks?
fn list_by_prefix(
&self,
prefix: &AsciiString,
prefix: &BookmarkPrefix,
repoid: &RepositoryId,
) -> BoxStream<(AsciiString, DChangesetId), Error>;
) -> BoxStream<(Bookmark, DChangesetId), Error>;
/// Creates a transaction that will be used for write operations.
fn create_transaction(&self, repoid: &RepositoryId) -> Box<Transaction>;
@ -44,7 +114,7 @@ pub trait Transaction: Send + Sync + 'static {
/// committing the transaction will fail.
fn update(
&mut self,
key: &AsciiString,
key: &Bookmark,
new_cs: &DChangesetId,
old_cs: &DChangesetId,
) -> Result<()>;
@ -52,20 +122,20 @@ pub trait Transaction: Send + Sync + 'static {
/// Adds create() operation to the transaction set.
/// Creates a bookmark. Bookmark should not already exist, otherwise committing the
/// transaction will fail.
fn create(&mut self, key: &AsciiString, new_cs: &DChangesetId) -> Result<()>;
fn create(&mut self, key: &Bookmark, new_cs: &DChangesetId) -> Result<()>;
/// Adds force_set() operation to the transaction set.
/// Unconditionally sets the new value of the bookmark. Succeeds regardless of whether bookmark
/// exists or not.
fn force_set(&mut self, key: &AsciiString, new_cs: &DChangesetId) -> Result<()>;
fn force_set(&mut self, key: &Bookmark, new_cs: &DChangesetId) -> Result<()>;
/// Adds delete operation to the transaction set.
/// Deletes bookmark only if it currently points to `old_cs`.
fn delete(&mut self, key: &AsciiString, old_cs: &DChangesetId) -> Result<()>;
fn delete(&mut self, key: &Bookmark, old_cs: &DChangesetId) -> Result<()>;
/// Adds force_delete operation to the transaction set.
/// Deletes bookmark unconditionally.
fn force_delete(&mut self, key: &AsciiString) -> Result<()>;
fn force_delete(&mut self, key: &Bookmark) -> Result<()>;
/// Commits the transaction. Future succeeds if transaction has been
/// successful, or errors if transaction has failed. Transaction may fail because of the

View File

@ -131,7 +131,7 @@ struct ChangegroupPush {
struct BookmarkPush {
part_id: PartId,
name: AsciiString,
name: bookmarks::Bookmark,
old: Option<DChangesetId>,
new: Option<DChangesetId>,
}
@ -241,6 +241,7 @@ impl Bundle2Resolver {
);
let name = try_boxfuture!(get_ascii_param(mparams, "key"));
let name = bookmarks::Bookmark::new_ascii(name);
let old = try_boxfuture!(get_optional_changeset_param(mparams, "old"));
let new = try_boxfuture!(get_optional_changeset_param(mparams, "new"));

View File

@ -13,6 +13,7 @@ use futures_ext::{BoxFuture, FutureExt};
use slog::Logger;
use blobrepo::BlobRepo;
use bookmarks::Bookmark;
use mercurial::RevlogRepo;
use mercurial_types::DChangesetId;
@ -40,7 +41,7 @@ pub fn upload_bookmarks(
let mut transaction = blobrepo.update_bookmark_transaction();
for (key, value) in vec {
let key = try_boxfuture!(AsciiString::from_ascii(key));
let key = Bookmark::new_ascii(try_boxfuture!(AsciiString::from_ascii(key)));
let value = DChangesetId::new(value.into_nodehash().into_mononoke());
try_boxfuture!(transaction.create(&key, &value))
}

View File

@ -9,6 +9,7 @@
extern crate ascii;
extern crate blobrepo;
extern crate bookmarks;
extern crate bytes;
extern crate changesets;
extern crate clap;

View File

@ -8,7 +8,7 @@
#![feature(never_type)]
#![feature(try_from)]
extern crate ascii;
extern crate bookmarks;
#[macro_use]
extern crate failure_ext as failure;
#[macro_use]
@ -75,8 +75,6 @@ use std::sync::{Arc, Mutex};
use std::thread::{self, JoinHandle};
use std::time::Instant;
use ascii::AsciiString;
use failure::SlogKVError;
use futures::{Future, IntoFuture, Sink, Stream};
use futures::sink::Wait;
@ -222,7 +220,7 @@ fn get_config<'a>(logger: &Logger, matches: &ArgMatches<'a>) -> Result<RepoConfi
let changesetid = match matches.value_of("crbook") {
Some(book) => {
let book = AsciiString::from_ascii(book).expect("book must be ascii");
let book = bookmarks::Bookmark::new(book).expect("book must be ascii");
config_repo
.get_bookmark(&book)
.wait()?

View File

@ -418,7 +418,7 @@ impl RepoClient {
let blobrepo = self.repo.blobrepo.clone();
let items = blobrepo.get_bookmarks().map(|(name, cs)| {
let hash: Vec<u8> = cs.into_nodehash().into_mercurial().to_hex().into();
(name, hash)
(name.to_string(), hash)
});
bundle.add_part(parts::listkey_part("bookmarks", items)?);
}
@ -704,8 +704,7 @@ impl HgCommands for RepoClient {
.collect()
.map(|bookmarks| {
let bookiter = bookmarks.into_iter().map(|(name, value)| {
let name: &[u8] = name.as_ref();
(Vec::from(name), value)
(Vec::from(name.to_string()), value)
});
HashMap::from_iter(bookiter)
})

View File

@ -58,7 +58,8 @@ extern crate slog;
use std::str::FromStr;
use bookmarks::Bookmarks;
use ascii::AsciiString;
use bookmarks::{Bookmark, Bookmarks};
use changesets::{Changesets, ChangesetInsert, SqliteChangesets};
use memblob::EagerMemblob;
use dbbookmarks::SqliteDbBookmarks;
@ -66,7 +67,6 @@ use dieselfilenodes::SqliteFilenodes;
use mercurial_types::{DChangesetId, DNodeHash, RepositoryId};
use mononoke_types::BlobstoreBytes;
use blobrepo::BlobRepo;
use ascii::AsciiString;
use blobstore::Blobstore;
use futures::future::Future;
use slog::{Discard, Drain, Logger};
@ -140,7 +140,7 @@ pub fn getrepo(logger: Option<Logger>) -> BlobRepo {
head = head[-40:]
writeline(
'''book_txn.create(
&AsciiString::from_ascii("head-{0}").unwrap(),
&Bookmark::new("head-{0}".to_string()).unwrap(),
&DChangesetId::new(DNodeHash::from_ascii_str(
&AsciiString::from_ascii("{0}").unwrap(),
).unwrap()),