about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustpkg/package_id.rs69
-rw-r--r--src/librustpkg/rustpkg.rc2
-rw-r--r--src/librustpkg/tests.rs28
-rw-r--r--src/librustpkg/version.rs140
4 files changed, 178 insertions, 61 deletions
diff --git a/src/librustpkg/package_id.rs b/src/librustpkg/package_id.rs
index 85c82787f26..9b05c848b6e 100644
--- a/src/librustpkg/package_id.rs
+++ b/src/librustpkg/package_id.rs
@@ -12,9 +12,8 @@ pub use package_path::{RemotePath, LocalPath, normalize, hash};
 use extra::semver;
 use core::prelude::*;
 use core::result;
-
-/// Placeholder
-pub fn default_version() -> Version { ExactRevision(0.1) }
+use core::prelude::*;
+use version::{default_version, try_getting_version, Version};
 
 /// Path-fragment identifier of a package such as
 /// 'github.com/graydon/test'; path must be a relative
@@ -49,11 +48,17 @@ impl PkgId {
         let remote_path = RemotePath(p);
         let local_path = normalize(copy remote_path);
         let short_name = (copy local_path).filestem().expect(fmt!("Strange path! %s", s));
+
+        let version = match try_getting_version(remote_path) {
+            Some(v) => v,
+            None => default_version()
+        };
+
         PkgId {
             local_path: local_path,
             remote_path: remote_path,
             short_name: short_name,
-            version: default_version()
+            version: version
         }
     }
 
@@ -74,59 +79,3 @@ impl ToStr for PkgId {
         fmt!("%s-%s", self.local_path.to_str(), self.version.to_str())
     }
 }
-
-/// A version is either an exact revision,
-/// or a semantic version
-pub enum Version {
-    ExactRevision(float),
-    SemVersion(semver::Version)
-}
-
-
-impl Ord for Version {
-    fn lt(&self, other: &Version) -> bool {
-        match (self, other) {
-            (&ExactRevision(f1), &ExactRevision(f2)) => f1 < f2,
-            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 < v2,
-            _ => false // incomparable, really
-        }
-    }
-    fn le(&self, other: &Version) -> bool {
-        match (self, other) {
-            (&ExactRevision(f1), &ExactRevision(f2)) => f1 <= f2,
-            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 <= v2,
-            _ => false // incomparable, really
-        }
-    }
-    fn ge(&self, other: &Version) -> bool {
-        match (self, other) {
-            (&ExactRevision(f1), &ExactRevision(f2)) => f1 > f2,
-            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 > v2,
-            _ => false // incomparable, really
-        }
-    }
-    fn gt(&self, other: &Version) -> bool {
-        match (self, other) {
-            (&ExactRevision(f1), &ExactRevision(f2)) => f1 >= f2,
-            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 >= v2,
-            _ => false // incomparable, really
-        }
-    }
-
-}
-
-impl ToStr for Version {
-    fn to_str(&self) -> ~str {
-        match *self {
-            ExactRevision(ref n) => n.to_str(),
-            SemVersion(ref v) => v.to_str()
-        }
-    }
-}
-
-pub fn parse_vers(vers: ~str) -> result::Result<semver::Version, ~str> {
-    match semver::parse(vers) {
-        Some(vers) => result::Ok(vers),
-        None => result::Err(~"could not parse version: invalid")
-    }
-}
diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc
index 5bc52b1eb35..8591251d4cd 100644
--- a/src/librustpkg/rustpkg.rc
+++ b/src/librustpkg/rustpkg.rc
@@ -18,6 +18,7 @@
 #[license = "MIT/ASL2"];
 #[crate_type = "lib"];
 
+#[no_core];
 #[no_std];
 
 extern mod core(name = "std");
@@ -53,6 +54,7 @@ mod target;
 #[cfg(test)]
 mod tests;
 mod util;
+mod version;
 mod workspace;
 
 pub mod usage;
diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs
index a96a7a0a5fc..e897f757ec2 100644
--- a/src/librustpkg/tests.rs
+++ b/src/librustpkg/tests.rs
@@ -18,7 +18,8 @@ use core::prelude::*;
 use core::result;
 use extra::tempfile::mkdtemp;
 use package_path::*;
-use package_id::{PkgId, default_version};
+use package_id::PkgId;
+use version::{default_version, ExactRevision};
 use path_util::{target_executable_in_workspace, target_library_in_workspace,
                target_test_in_workspace, target_bench_in_workspace,
                make_dir_rwx, u_rwx,
@@ -53,6 +54,16 @@ fn remote_pkg() -> PkgId {
     }
 }
 
+fn remote_versioned_pkg() -> PkgId {
+    let remote = RemotePath(Path("github.com/catamorphism/test_pkg_version"));
+    PkgId {
+        local_path: normalize(copy remote),
+        remote_path: remote,
+        short_name: ~"test_pkg_version",
+        version: default_version()
+    }
+}
+
 fn writeFile(file_path: &Path, contents: &str) {
     let out: @io::Writer =
         result::get(&io::file_writer(file_path,
@@ -242,3 +253,18 @@ fn test_package_ids_must_be_relative_path_like() {
     }
 
 }
+
+#[test]
+fn test_package_version() {
+    let workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
+    let sysroot = test_sysroot();
+    debug!("sysroot = %s", sysroot.to_str());
+    let ctxt = fake_ctxt(Some(@sysroot));
+    let temp_pkg_id = PkgId::new("github.com/catamorphism/test_pkg_version");
+    match temp_pkg_id.version {
+        ExactRevision(0.2) => (),
+        _ => fail!(fmt!("test_package_version: package version was %?, expected Some(0.2)",
+                        temp_pkg_id.version))
+    }
+    // also check that file paths are right
+}
diff --git a/src/librustpkg/version.rs b/src/librustpkg/version.rs
new file mode 100644
index 00000000000..2de02097021
--- /dev/null
+++ b/src/librustpkg/version.rs
@@ -0,0 +1,140 @@
+// 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.
+
+/// A version is either an exact revision,
+/// or a semantic version
+
+extern mod std;
+
+use std::semver;
+use core::prelude::*;
+use core::run;
+use package_path::RemotePath;
+use std::tempfile::mkdtemp;
+
+pub enum Version {
+    ExactRevision(float),
+    SemVersion(semver::Version)
+}
+
+
+impl Ord for Version {
+    fn lt(&self, other: &Version) -> bool {
+        match (self, other) {
+            (&ExactRevision(f1), &ExactRevision(f2)) => f1 < f2,
+            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 < v2,
+            _ => false // incomparable, really
+        }
+    }
+    fn le(&self, other: &Version) -> bool {
+        match (self, other) {
+            (&ExactRevision(f1), &ExactRevision(f2)) => f1 <= f2,
+            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 <= v2,
+            _ => false // incomparable, really
+        }
+    }
+    fn ge(&self, other: &Version) -> bool {
+        match (self, other) {
+            (&ExactRevision(f1), &ExactRevision(f2)) => f1 > f2,
+            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 > v2,
+            _ => false // incomparable, really
+        }
+    }
+    fn gt(&self, other: &Version) -> bool {
+        match (self, other) {
+            (&ExactRevision(f1), &ExactRevision(f2)) => f1 >= f2,
+            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 >= v2,
+            _ => false // incomparable, really
+        }
+    }
+
+}
+
+impl ToStr for Version {
+    fn to_str(&self) -> ~str {
+        match *self {
+            ExactRevision(ref n) => n.to_str(),
+            SemVersion(ref v) => v.to_str()
+        }
+    }
+}
+
+pub fn parse_vers(vers: ~str) -> result::Result<semver::Version, ~str> {
+    match semver::parse(vers) {
+        Some(vers) => result::Ok(vers),
+        None => result::Err(~"could not parse version: invalid")
+    }
+}
+
+
+/// If `remote_path` refers to a git repo that can be downloaded,
+/// and the most recent tag in that repo denotes a version, return it;
+/// otherwise, `None`
+pub fn try_getting_version(remote_path: &RemotePath) -> Option<Version> {
+    debug!("try_getting_version: %s", remote_path.to_str());
+    if is_url_like(remote_path) {
+        debug!("Trying to fetch its sources..");
+        let tmp_dir = mkdtemp(&os::tmpdir(),
+                              "test").expect("try_getting_version: couldn't create temp dir");
+        debug!("executing {git clone https://%s %s}", remote_path.to_str(), tmp_dir.to_str());
+        let outp  = run::process_output("git", [~"clone", fmt!("https://%s", remote_path.to_str()),
+                                                tmp_dir.to_str()]);
+        if outp.status == 0 {
+            debug!("Cloned it... ( %s, %s )", str::from_bytes(outp.output), str::from_bytes(outp.error));
+            let mut output = None;
+            debug!("executing {git --git-dir=%s tag -l}", tmp_dir.push(".git").to_str());
+            let outp = run::process_output("git", [fmt!("--git-dir=%s", tmp_dir.push(".git").to_str()),
+                                                           ~"tag", ~"-l"]);
+            let output_text = str::from_bytes(outp.output);
+            debug!("Full output: ( %s ) [%?]", output_text, outp.status);
+            for output_text.each_split_char('\n') |l| {
+                debug!("A line of output: %s", l);
+                if !l.is_whitespace() {
+                    output = Some(l);
+                }
+            }
+
+            output.chain(try_parsing_version)
+        }
+        else {
+            None
+        }
+    }
+    else {
+        None
+    }
+}
+    
+fn try_parsing_version(s: &str) -> Option<Version> {
+    let s = s.trim();
+    debug!("Attempting to parse: %s", s);
+    match float::from_str(s) {
+        Some(f) => {
+            debug!("%s -> %f", s, f);
+            Some(ExactRevision(f)) // semver not handled yet
+        }
+        None => {
+            debug!("None!!");
+            None
+        }
+    }
+}
+
+/// Placeholder
+pub fn default_version() -> Version { ExactRevision(0.1) }
+
+/// Just an approximation
+fn is_url_like(p: &RemotePath) -> bool {
+    let mut n = 0;
+    for p.to_str().each_split_char('/') |_| {
+        n += 1;
+    }
+    n > 2
+}
\ No newline at end of file