auto merge of #10972 : metajack/rust/pkgid-with-name, r=alexcrichton
This change extends the pkgid attribute to allow of explicit crate names, instead of always inferring them based on the path. This means that if your GitHub repo is called `rust-foo`, you can have your pkgid set your library name to `foo`. You'd do this with a pkgid attribute like `github.com/somewhere/rust-foo#foo:1.0`. This is half of the fix for #10922.
This commit is contained in:
commit
d5798b3902
@ -790,7 +790,7 @@ extern mod extra; // equivalent to: extern mod extra = "extra";
|
||||
|
||||
extern mod rustextra = "extra"; // linking to 'extra' under another name
|
||||
|
||||
extern mod foo = "some/where/foo#1.0"; // a full package ID for rustpkg
|
||||
extern mod foo = "some/where/rust-foo#foo:1.0"; // a full package ID for rustpkg
|
||||
~~~~
|
||||
|
||||
##### Use declarations
|
||||
|
@ -8,10 +8,21 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/// PkgIds identify crates and include the crate name and optionall a path and
|
||||
/// version. In the full form, they look like relative URLs. Example:
|
||||
/// `github.com/mozilla/rust#std:1.0` would be a package ID with a path of
|
||||
/// `gitub.com/mozilla/rust` and a crate name of `std` with a version of
|
||||
/// `1.0`. If no crate name is given after the hash, the name is inferred to
|
||||
/// be the last component of the path. If no version is given, it is inferred
|
||||
/// to be `0.0`.
|
||||
#[deriving(Clone, Eq)]
|
||||
pub struct PkgId {
|
||||
/// A path which represents the codes origin. By convention this is the
|
||||
/// URL, without `http://` or `https://` prefix, to the crate's repository
|
||||
path: ~str,
|
||||
/// The name of the crate.
|
||||
name: ~str,
|
||||
/// The version of the crate.
|
||||
version: Option<~str>,
|
||||
}
|
||||
|
||||
@ -21,62 +32,55 @@ fn to_str(&self) -> ~str {
|
||||
None => "0.0",
|
||||
Some(ref version) => version.as_slice(),
|
||||
};
|
||||
if self.path.is_empty() {
|
||||
format!("{}\\#{}", self.name, version)
|
||||
if self.path == self.name || self.path.ends_with(format!("/{}", self.name)) {
|
||||
format!("{}\\#{}", self.path, version)
|
||||
} else {
|
||||
format!("{}/{}\\#{}", self.path, self.name, version)
|
||||
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 {
|
||||
let pieces: ~[&str] = s.splitn('#', 1).collect();
|
||||
let path = pieces[0].to_owned();
|
||||
|
||||
if path.starts_with("/") || path.ends_with("/") ||
|
||||
path.starts_with(".") || path.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let path = if name_idx == 0 {
|
||||
""
|
||||
let path_pieces: ~[&str] = path.rsplitn('/', 1).collect();
|
||||
let inferred_name = path_pieces[0];
|
||||
|
||||
let (name, version) = if pieces.len() == 1 {
|
||||
(inferred_name.to_owned(), None)
|
||||
} else {
|
||||
prefix.slice_to(name_idx - 1)
|
||||
};
|
||||
let check_path = Path::new(path);
|
||||
if !check_path.is_relative() {
|
||||
return None;
|
||||
}
|
||||
let hash_pieces: ~[&str] = pieces[1].splitn(':', 1).collect();
|
||||
let (hash_name, hash_version) = if hash_pieces.len() == 1 {
|
||||
("", hash_pieces[0])
|
||||
} else {
|
||||
(hash_pieces[0], hash_pieces[1])
|
||||
};
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
}
|
||||
let name = if !hash_name.is_empty() {
|
||||
hash_name.to_owned()
|
||||
} else {
|
||||
inferred_name.to_owned()
|
||||
};
|
||||
|
||||
let version = if !hash_version.is_empty() {
|
||||
Some(hash_version.to_owned())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
(name, version)
|
||||
};
|
||||
|
||||
Some(PkgId{
|
||||
path: path.to_owned(),
|
||||
name: name.to_owned(),
|
||||
Some(PkgId {
|
||||
path: path,
|
||||
name: name,
|
||||
version: version,
|
||||
})
|
||||
}
|
||||
@ -96,7 +100,7 @@ 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, ~"");
|
||||
assert_eq!(pkgid.path, ~"foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -104,7 +108,7 @@ 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, ~"");
|
||||
assert_eq!(pkgid.path, ~"f");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -118,7 +122,7 @@ 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");
|
||||
assert_eq!(pkgid.path, ~"example.com/foo/bar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -126,7 +130,7 @@ 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, ~"");
|
||||
assert_eq!(pkgid.path, ~"foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -135,12 +139,18 @@ fn absolute_path() {
|
||||
assert!(pkgid.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_ends_with_slash() {
|
||||
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");
|
||||
assert_eq!(pkgid.path, ~"example.com/foo/bar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -148,7 +158,7 @@ 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");
|
||||
assert_eq!(pkgid.path, ~"a/b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -156,5 +166,21 @@ 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, ~"");
|
||||
}
|
||||
assert_eq!(pkgid.path, ~"foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_and_name() {
|
||||
let pkgid: PkgId = from_str("foo/rust-bar#bar:1.0").expect("valid pkgid");
|
||||
assert_eq!(pkgid.name, ~"bar");
|
||||
assert_eq!(pkgid.version, Some(~"1.0"));
|
||||
assert_eq!(pkgid.path, ~"foo/rust-bar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_name() {
|
||||
let pkgid: PkgId = from_str("foo/bar#:1.0").expect("valid pkgid");
|
||||
assert_eq!(pkgid.name, ~"bar");
|
||||
assert_eq!(pkgid.version, Some(~"1.0"));
|
||||
assert_eq!(pkgid.path, ~"foo/bar");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user