diff options
| author | bors <bors@rust-lang.org> | 2013-12-17 07:41:40 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-12-17 07:41:40 -0800 |
| commit | d5798b3902c4af50bf0f24e1c4bbf5e4a4dcc6ca (patch) | |
| tree | 91c5eff1ccbe19cda325df92a91ad78c75b1e351 /src/libsyntax | |
| parent | 1a26bd166a3c029a17f4a5fdb6021d7de7c7eb48 (diff) | |
| parent | 262cc4a2bcc0e1465ed0c88722d5adfa80a184d9 (diff) | |
| download | rust-d5798b3902c4af50bf0f24e1c4bbf5e4a4dcc6ca.tar.gz rust-d5798b3902c4af50bf0f24e1c4bbf5e4a4dcc6ca.zip | |
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.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/pkgid.rs | 128 |
1 files changed, 77 insertions, 51 deletions
diff --git a/src/libsyntax/pkgid.rs b/src/libsyntax/pkgid.rs index 1e840ca700b..3c10e5199c9 100644 --- a/src/libsyntax/pkgid.rs +++ b/src/libsyntax/pkgid.rs @@ -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 @@ impl ToStr for PkgId { 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 { - return None; - } + let pieces: ~[&str] = s.splitn('#', 1).collect(); + let path = pieces[0].to_owned(); - let path = if name_idx == 0 { - "" - } else { - prefix.slice_to(name_idx - 1) - }; - let check_path = Path::new(path); - if !check_path.is_relative() { + if path.starts_with("/") || path.ends_with("/") || + path.starts_with(".") || path.is_empty() { 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()) - } - } - } + 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 { + 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 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] @@ -136,11 +140,17 @@ fn absolute_path() { } #[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, ~""); -} \ No newline at end of file + 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"); +} |
