Skip to content

Commit

Permalink
rustpkg: Accept package IDs like github.com/foo/bar#0.3
Browse files Browse the repository at this point in the history
If the package ID is of the form s#v, where v is a valid version
string, fetch tag v of that package.
  • Loading branch information
catamorphism committed Jun 9, 2013
1 parent 53b8352 commit d92b435
Show file tree
Hide file tree
Showing 8 changed files with 542 additions and 341 deletions.
58 changes: 58 additions & 0 deletions src/librustpkg/crate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2012-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.

use core::path::Path;
use core::vec;

/// A crate is a unit of Rust code to be compiled into a binary or library
pub struct Crate {
file: Path,
flags: ~[~str],
cfgs: ~[~str]
}

impl Crate {

pub fn new(p: &Path) -> Crate {
Crate {
file: copy *p,
flags: ~[],
cfgs: ~[]
}
}

fn flag(&self, flag: ~str) -> Crate {
Crate {
flags: vec::append(copy self.flags, [flag]),
.. copy *self
}
}

fn flags(&self, flags: ~[~str]) -> Crate {
Crate {
flags: vec::append(copy self.flags, flags),
.. copy *self
}
}

fn cfg(&self, cfg: ~str) -> Crate {
Crate {
cfgs: vec::append(copy self.cfgs, [cfg]),
.. copy *self
}
}

fn cfgs(&self, cfgs: ~[~str]) -> Crate {
Crate {
cfgs: vec::append(copy self.cfgs, cfgs),
.. copy *self
}
}
}
35 changes: 27 additions & 8 deletions src/librustpkg/package_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@
// except according to those terms.

pub use package_path::{RemotePath, LocalPath, normalize, hash};
use extra::semver;
use core::prelude::*;
use core::result;
use core::prelude::*;
use version::{default_version, try_getting_version, Version};
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
Expand All @@ -38,6 +35,21 @@ 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"));
Expand All @@ -49,9 +61,12 @@ impl PkgId {
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) {
let version = match given_version {
Some(v) => v,
None => default_version()
None => match try_getting_version(&remote_path) {
Some(v) => v,
None => NoVersion
}
};

PkgId {
Expand All @@ -69,13 +84,17 @@ impl PkgId {
}

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

impl ToStr for PkgId {
fn to_str(&self) -> ~str {
let maybe_dash = match self.version {
NoVersion => "",
_ => "-"
};
// should probably use the filestem and not the whole path
fmt!("%s-%s", self.local_path.to_str(), self.version.to_str())
fmt!("%s%s%s", self.local_path.to_str(), maybe_dash, self.version.to_str())
}
}
239 changes: 239 additions & 0 deletions src/librustpkg/package_source.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
// Copyright 2012-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.

use target::*;
use package_id::PkgId;
use core::path::Path;
use core::option::*;
use core::{os, run, str, vec};
use context::*;
use crate::Crate;
use path_util::pkgid_src_in_workspace;
use util::{compile_crate, note};
use version::{ExactRevision, SemanticVersion, NoVersion};

// An enumeration of the unpacked source of a package workspace.
// This contains a list of files found in the source workspace.
pub struct PkgSrc {
root: Path, // root of where the package source code lives
dst_dir: Path, // directory where we will put the compiled output
id: PkgId,
libs: ~[Crate],
mains: ~[Crate],
tests: ~[Crate],
benchs: ~[Crate],
}

condition! {
build_err: (~str) -> ();
}

impl PkgSrc {

pub fn new(src_dir: &Path, dst_dir: &Path,
id: &PkgId) -> PkgSrc {
PkgSrc {
root: copy *src_dir,
dst_dir: copy *dst_dir,
id: copy *id,
libs: ~[],
mains: ~[],
tests: ~[],
benchs: ~[]
}
}


fn check_dir(&self) -> Path {
use conditions::nonexistent_package::cond;

debug!("Pushing onto root: %s | %s", self.id.remote_path.to_str(),
self.root.to_str());
let dir;
let dirs = pkgid_src_in_workspace(&self.id, &self.root);
debug!("Checking dirs: %?", dirs);
let path = dirs.find(|d| os::path_exists(d));
match path {
Some(d) => dir = d,
None => dir = match self.fetch_git() {
None => cond.raise((copy self.id, ~"supplied path for package dir does not \
exist, and couldn't interpret it as a URL fragment")),
Some(d) => d
}
}
if !os::path_is_dir(&dir) {
cond.raise((copy self.id, ~"supplied path for package dir is a \
non-directory"));
}

dir
}

/// Try interpreting self's package id as a remote package, and try
/// fetching it and caching it in a local directory. Return the cached directory
/// if this was successful, None otherwise
/// (right now we only support git)
pub fn fetch_git(&self) -> Option<Path> {

let mut local = self.root.push("src");
local = local.push(self.id.to_str());
// Git can't clone into a non-empty directory
os::remove_dir_recursive(&local);

let url = fmt!("https://%s", self.id.remote_path.to_str());
let branch_args = match self.id.version {
NoVersion => ~[],
ExactRevision(ref s) => ~[~"--branch", copy *s],
SemanticVersion(ref s) => ~[~"--branch", s.to_str()]
};


note(fmt!("git clone %s %s %?", url, local.to_str(), branch_args));

if run::process_output("git",
~[~"clone", copy url, local.to_str()] + branch_args).status != 0 {
note(fmt!("fetching %s failed: can't clone repository", url));
None
}
else {
Some(local)
}
}


// If a file named "pkg.rs" in the current directory exists,
// return the path for it. Otherwise, None
pub fn package_script_option(&self, cwd: &Path) -> Option<Path> {
let maybe_path = cwd.push("pkg.rs");
if os::path_exists(&maybe_path) {
Some(maybe_path)
}
else {
None
}
}

/// True if the given path's stem is self's pkg ID's stem
/// or if the pkg ID's stem is <rust-foo> and the given path's
/// stem is foo
/// Requires that dashes in p have already been normalized to
/// underscores
fn stem_matches(&self, p: &Path) -> bool {
let self_id = self.id.local_path.filestem();
if self_id == p.filestem() {
return true;
}
else {
for self_id.each |pth| {
if pth.starts_with("rust_") // because p is already normalized
&& match p.filestem() {
Some(s) => str::eq_slice(s, pth.slice(5, pth.len())),
None => false
} { return true; }
}
}
false
}

fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) {
assert!(p.components.len() > prefix);
let mut sub = Path("");
for vec::slice(p.components, prefix,
p.components.len()).each |c| {
sub = sub.push(*c);
}
debug!("found crate %s", sub.to_str());
cs.push(Crate::new(&sub));
}

/// Infers crates to build. Called only in the case where there
/// is no custom build logic
pub fn find_crates(&mut self) {
use conditions::missing_pkg_files::cond;

let dir = self.check_dir();
debug!("Called check_dir, I'm in %s", dir.to_str());
let prefix = dir.components.len();
debug!("Matching against %?", self.id.local_path.filestem());
for os::walk_dir(&dir) |pth| {
match pth.filename() {
Some(~"lib.rs") => PkgSrc::push_crate(&mut self.libs,
prefix,
pth),
Some(~"main.rs") => PkgSrc::push_crate(&mut self.mains,
prefix,
pth),
Some(~"test.rs") => PkgSrc::push_crate(&mut self.tests,
prefix,
pth),
Some(~"bench.rs") => PkgSrc::push_crate(&mut self.benchs,
prefix,
pth),
_ => ()
}
}

if self.libs.is_empty() && self.mains.is_empty()
&& self.tests.is_empty() && self.benchs.is_empty() {

note(~"Couldn't infer any crates to build.\n\
Try naming a crate `main.rs`, `lib.rs`, \
`test.rs`, or `bench.rs`.");
cond.raise(copy self.id);
}

debug!("found %u libs, %u mains, %u tests, %u benchs",
self.libs.len(),
self.mains.len(),
self.tests.len(),
self.benchs.len())
}

fn build_crates(&self,
ctx: &Ctx,
dst_dir: &Path,
src_dir: &Path,
crates: &[Crate],
cfgs: &[~str],
what: OutputType) {
for crates.each |&crate| {
let path = &src_dir.push_rel(&crate.file).normalize();
note(fmt!("build_crates: compiling %s", path.to_str()));
note(fmt!("build_crates: destination dir is %s", dst_dir.to_str()));

let result = compile_crate(ctx,
&self.id,
path,
dst_dir,
crate.flags,
crate.cfgs + cfgs,
false,
what);
if !result {
build_err::cond.raise(fmt!("build failure on %s",
path.to_str()));
}
debug!("Result of compiling %s was %?",
path.to_str(), result);
}
}

pub fn build(&self, ctx: &Ctx, dst_dir: Path, cfgs: ~[~str]) {
let dir = self.check_dir();
debug!("Building libs in %s", dir.to_str());
self.build_crates(ctx, &dst_dir, &dir, self.libs, cfgs, Lib);
debug!("Building mains");
self.build_crates(ctx, &dst_dir, &dir, self.mains, cfgs, Main);
debug!("Building tests");
self.build_crates(ctx, &dst_dir, &dir, self.tests, cfgs, Test);
debug!("Building benches");
self.build_crates(ctx, &dst_dir, &dir, self.benchs, cfgs, Bench);
}
}
16 changes: 11 additions & 5 deletions src/librustpkg/path_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

use core::prelude::*;
pub use package_path::{RemotePath, LocalPath};
pub use package_id::{PkgId, Version};
pub use package_id::PkgId;
pub use target::{OutputType, Main, Lib, Test, Bench, Target, Build, Install};
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
use core::os::mkdir_recursive;
Expand Down Expand Up @@ -210,11 +210,17 @@ pub fn target_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
}


/// Returns the executable that would be installed for <pkgid>
/// in <workspace>
/// Returns the installed path for <built_library> in <workspace>
/// As a side effect, creates the lib-dir if it doesn't exist
pub fn target_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
target_file_in_workspace(pkgid, workspace, Lib, Install)
pub fn target_library_in_workspace(workspace: &Path,
built_library: &Path) -> Path {
use conditions::bad_path::cond;
let result = workspace.push("lib");
if !os::path_exists(&result) && !mkdir_recursive(&result, u_rwx) {
cond.raise((copy result, ~"I couldn't create the library directory"));
}
result.push(built_library.filename().expect(fmt!("I don't know how to treat %s as a library",
built_library.to_str())))
}

/// Returns the test executable that would be installed for <pkgid>
Expand Down
Loading

5 comments on commit d92b435

@bors
Copy link
Contributor

@bors bors commented on d92b435 Jun 9, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from catamorphism
at catamorphism@d92b435

@bors
Copy link
Contributor

@bors bors commented on d92b435 Jun 9, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging catamorphism/rust/rustpkg_version_vcs = d92b435 into auto

@bors
Copy link
Contributor

@bors bors commented on d92b435 Jun 9, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

catamorphism/rust/rustpkg_version_vcs = d92b435 merged ok, testing candidate = 94f72dd

@bors
Copy link
Contributor

@bors bors commented on d92b435 Jun 9, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on d92b435 Jun 9, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding incoming to auto = 94f72dd

Please sign in to comment.