summary refs log tree commit diff
path: root/src/librustpkg/package_id.rs
blob: ebe2aa6f92a63b1f3b79e28a2c6f1acc68429a09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// 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.

pub use package_path::{RemotePath, LocalPath, normalize, hash};
use version::{try_getting_version, Version, NoVersion, split_version};

/// Path-fragment identifier of a package such as
/// 'github.com/graydon/test'; path must be a relative
/// path with >=1 component.
pub struct PkgId {
    /// Remote path: for example, github.com/mozilla/quux-whatever
    remote_path: RemotePath,
    /// Local path: for example, /home/quux/github.com/mozilla/quux_whatever
    /// Note that '-' normalizes to '_' when mapping a remote path
    /// onto a local path
    /// Also, this will change when we implement #6407, though we'll still
    /// need to keep track of separate local and remote paths
    local_path: LocalPath,
    /// Short name. This is the local path's filestem, but we store it
    /// redundantly so as to not call get() everywhere (filestem() returns an
    /// option)
    short_name: ~str,
    version: Version
}

impl PkgId {
    pub fn new(s: &str) -> PkgId {
        use conditions::bad_pkg_id::cond;

        let mut given_version = None;

        // Did the user request a specific version?
        let s = match split_version(s) {
            Some((path, v)) => {
                debug!("s = %s, path = %s, v = %s", s, path, v.to_str());
                given_version = Some(v);
                path
            }
            None => {
                debug!("%s has no explicit version", s);
                s
            }
        };

        let p = Path(s);
        if p.is_absolute {
            return cond.raise((p, ~"absolute pkgid"));
        }
        if p.components.len() < 1 {
            return cond.raise((p, ~"0-length 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 given_version {
            Some(v) => v,
            None => match try_getting_version(&remote_path) {
                Some(v) => v,
                None => NoVersion
            }
        };

        debug!("local_path = %s, remote_path = %s", local_path.to_str(), remote_path.to_str());
        PkgId {
            local_path: local_path,
            remote_path: remote_path,
            short_name: short_name,
            version: version
        }
    }

    pub fn hash(&self) -> ~str {
        fmt!("%s-%s-%s", self.remote_path.to_str(),
             hash(self.remote_path.to_str() + self.version.to_str()),
             self.version.to_str())
    }

    pub fn short_name_with_version(&self) -> ~str {
        fmt!("%s%s", self.short_name, self.version.to_str())
    }
}

impl ToStr for PkgId {
    fn to_str(&self) -> ~str {
        // should probably use the filestem and not the whole path
        fmt!("%s-%s", self.local_path.to_str(), self.version.to_str())
    }
}