diff options
| author | Jack Moffitt <jack@metajack.im> | 2013-12-09 14:56:53 -0700 |
|---|---|---|
| committer | Jack Moffitt <jack@metajack.im> | 2013-12-10 17:04:24 -0700 |
| commit | b349036e5f4f5f42e34ae9dd7859f3dc7a79de94 (patch) | |
| tree | c11b022d85120eddff8bdf1be2fd36fe3939369f /src/libsyntax | |
| parent | 29ca4350c8d64facb39311660e8ee919766f481a (diff) | |
| download | rust-b349036e5f4f5f42e34ae9dd7859f3dc7a79de94.tar.gz rust-b349036e5f4f5f42e34ae9dd7859f3dc7a79de94.zip | |
Make crate hash stable and externally computable.
This replaces the link meta attributes with a pkgid attribute and uses a hash of this as the crate hash. This makes the crate hash computable by things other than the Rust compiler. It also switches the hash function ot SHA1 since that is much more likely to be available in shell, Python, etc than SipHash. Fixes #10188, #8523.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/attr.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/lib.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/pkgid.rs | 160 |
3 files changed, 171 insertions, 0 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 05a65de16b8..ac5254f1aba 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -18,6 +18,7 @@ use codemap::{Span, Spanned, spanned, dummy_spanned}; use codemap::BytePos; use diagnostic::span_handler; use parse::comments::{doc_comment_style, strip_doc_comment_decoration}; +use pkgid::PkgId; use std::hashmap::HashSet; @@ -235,6 +236,13 @@ pub fn find_linkage_metas(attrs: &[Attribute]) -> ~[@MetaItem] { result } +pub fn find_pkgid(attrs: &[Attribute]) -> Option<PkgId> { + match first_attr_value_str_by_name(attrs, "pkgid") { + None => None, + Some(id) => from_str::<PkgId>(id), + } +} + #[deriving(Eq)] pub enum InlineAttr { InlineNone, diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index c9b3ba9d460..4382e6d67b8 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -13,6 +13,8 @@ * macros. */ +#[pkgid="syntax#0.9-pre"]; +// NOTE: remove after the next snapshot #[link(name = "syntax", package_id = "syntax", vers = "0.9-pre", @@ -51,6 +53,7 @@ pub mod fold; pub mod parse; +pub mod pkgid; pub mod print { pub mod pp; diff --git a/src/libsyntax/pkgid.rs b/src/libsyntax/pkgid.rs new file mode 100644 index 00000000000..1e840ca700b --- /dev/null +++ b/src/libsyntax/pkgid.rs @@ -0,0 +1,160 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[deriving(Clone, Eq)] +pub struct PkgId { + path: ~str, + name: ~str, + version: Option<~str>, +} + +impl ToStr for PkgId { + fn to_str(&self) -> ~str { + let version = match self.version { + None => "0.0", + Some(ref version) => version.as_slice(), + }; + if self.path.is_empty() { + format!("{}\\#{}", self.name, version) + } else { + format!("{}/{}\\#{}", self.path, self.name, version) + } + } +} + +impl FromStr for PkgId { + fn from_str(s: &str) -> Option<PkgId> { + let hash_idx = match s.find('#') { + None => s.len(), + Some(idx) => idx, + }; + let prefix = s.slice_to(hash_idx); + let name_idx = match prefix.rfind('/') { + None => 0, + Some(idx) => idx + 1, + }; + if name_idx >= prefix.len() { + return None; + } + let name = prefix.slice_from(name_idx); + if name.len() <= 0 { + return None; + } + + let path = if name_idx == 0 { + "" + } else { + prefix.slice_to(name_idx - 1) + }; + let check_path = Path::new(path); + if !check_path.is_relative() { + return None; + } + + let version = match s.find('#') { + None => None, + Some(idx) => { + if idx >= s.len() { + None + } else { + let v = s.slice_from(idx + 1); + if v.is_empty() { + None + } else { + Some(v.to_owned()) + } + } + } + }; + + Some(PkgId{ + path: path.to_owned(), + name: name.to_owned(), + version: version, + }) + } +} + +impl PkgId { + pub fn version_or_default<'a>(&'a self) -> &'a str { + match self.version { + None => "0.0", + Some(ref version) => version.as_slice(), + } + } +} + +#[test] +fn bare_name() { + let pkgid: PkgId = from_str("foo").expect("valid pkgid"); + assert_eq!(pkgid.name, ~"foo"); + assert_eq!(pkgid.version, None); + assert_eq!(pkgid.path, ~""); +} + +#[test] +fn bare_name_single_char() { + let pkgid: PkgId = from_str("f").expect("valid pkgid"); + assert_eq!(pkgid.name, ~"f"); + assert_eq!(pkgid.version, None); + assert_eq!(pkgid.path, ~""); +} + +#[test] +fn empty_pkgid() { + let pkgid: Option<PkgId> = from_str(""); + assert!(pkgid.is_none()); +} + +#[test] +fn simple_path() { + let pkgid: PkgId = from_str("example.com/foo/bar").expect("valid pkgid"); + assert_eq!(pkgid.name, ~"bar"); + assert_eq!(pkgid.version, None); + assert_eq!(pkgid.path, ~"example.com/foo"); +} + +#[test] +fn simple_version() { + let pkgid: PkgId = from_str("foo#1.0").expect("valid pkgid"); + assert_eq!(pkgid.name, ~"foo"); + assert_eq!(pkgid.version, Some(~"1.0")); + assert_eq!(pkgid.path, ~""); +} + +#[test] +fn absolute_path() { + let pkgid: Option<PkgId> = from_str("/foo/bar"); + assert!(pkgid.is_none()); +} + +#[test] +fn path_and_version() { + let pkgid: PkgId = from_str("example.com/foo/bar#1.0").expect("valid pkgid"); + assert_eq!(pkgid.name, ~"bar"); + assert_eq!(pkgid.version, Some(~"1.0")); + assert_eq!(pkgid.path, ~"example.com/foo"); +} + +#[test] +fn single_chars() { + let pkgid: PkgId = from_str("a/b#1").expect("valid pkgid"); + assert_eq!(pkgid.name, ~"b"); + assert_eq!(pkgid.version, Some(~"1")); + assert_eq!(pkgid.path, ~"a"); +} + +#[test] +fn missing_version() { + let pkgid: PkgId = from_str("foo#").expect("valid pkgid"); + assert_eq!(pkgid.name, ~"foo"); + assert_eq!(pkgid.version, None); + assert_eq!(pkgid.path, ~""); +} \ No newline at end of file |
