Skip to content

Commit 2830d7d

Browse files
committed
auto merge of #8032 : catamorphism/rust/rustpkg-tags, r=graydon
r? @graydon Package IDs can now be of the form a/b/c#FOO, where (if a/b/c is a git repository) FOO is any tag in the repository. Non-numeric tags only match against package IDs with the same tag, and aren't compared linearly like numeric versions. While I was at it, refactored the code that calls `git clone`, and segregated build output properly for different packages.
2 parents fddb35e + 7079ec6 commit 2830d7d

File tree

7 files changed

+140
-80
lines changed

7 files changed

+140
-80
lines changed

doc/rustpkg.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ A package ID can also specify a version, like:
7676
`github.com/mozilla/rust#0.3`.
7777
In this case, `rustpkg` will check that the repository `github.com/mozilla/rust` has a tag named `0.3`,
7878
and report an error otherwise.
79+
A package ID can also specify a particular revision of a repository, like:
80+
`github.com/mozilla/rust#release-0.7`.
81+
When the refspec (portion of the package ID after the `#`) can't be parsed as a decimal number,
82+
rustpkg passes the refspec along to the version control system without interpreting it.
83+
rustpkg also interprets any dependencies on such a package ID literally
84+
(as opposed to versions, where a newer version satisfies a dependency on an older version).
85+
Thus, `github.com/mozilla/rust#5c4cd30f80` is also a valid package ID,
86+
since git can deduce that 5c4cd30f80 refers to a revision of the desired repository.
7987

8088
## Source files
8189

src/librustpkg/package_source.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@
1111
use target::*;
1212
use package_id::PkgId;
1313
use std::path::Path;
14-
use std::{os, run, str};
14+
use std::{os, str};
1515
use context::*;
1616
use crate::Crate;
1717
use messages::*;
18-
use source_control::git_clone;
18+
use source_control::{git_clone, git_clone_general};
1919
use path_util::pkgid_src_in_workspace;
2020
use util::compile_crate;
21-
use version::{ExactRevision, SemanticVersion, NoVersion};
2221

2322
// An enumeration of the unpacked source of a package workspace.
2423
// This contains a list of files found in the source workspace.
@@ -102,22 +101,13 @@ impl PkgSrc {
102101
}
103102

104103
let url = fmt!("https://%s", self.id.remote_path.to_str());
105-
let branch_args = match self.id.version {
106-
NoVersion => ~[],
107-
ExactRevision(ref s) => ~[~"--branch", (*s).clone()],
108-
SemanticVersion(ref s) => ~[~"--branch", s.to_str()]
109-
};
110-
111-
112-
note(fmt!("Fetching package: git clone %s %s %?", url, local.to_str(), branch_args));
113-
114-
if run::process_output("git",
115-
~[~"clone", url.clone(), local.to_str()] + branch_args).status != 0 {
116-
note(fmt!("fetching %s failed: can't clone repository", url));
117-
None
104+
note(fmt!("Fetching package: git clone %s %s [version=%s]",
105+
url, local.to_str(), self.id.version.to_str()));
106+
if git_clone_general(url, &local, &self.id.version) {
107+
Some(local)
118108
}
119109
else {
120-
Some(local)
110+
None
121111
}
122112
}
123113

src/librustpkg/path_util.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub fn rust_path() -> ~[Path] {
5252
}
5353
None => ~[]
5454
};
55+
debug!("RUST_PATH entries from environment: %?", env_rust_path);
5556
let cwd = os::getcwd();
5657
// now add in default entries
5758
env_rust_path.push(cwd.clone());
@@ -345,7 +346,12 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
345346
let subdir = match what {
346347
Lib => "lib", Main | Test | Bench => "bin"
347348
};
348-
let result = workspace.push(subdir);
349+
// Artifacts in the build directory live in a package-ID-specific subdirectory,
350+
// but installed ones don't.
351+
let result = match where {
352+
Build => workspace.push(subdir).push_rel(&*pkgid.local_path),
353+
_ => workspace.push(subdir)
354+
};
349355
if !os::path_exists(&result) && !mkdir_recursive(&result, U_RWX) {
350356
cond.raise((result.clone(), fmt!("target_file_in_workspace couldn't \
351357
create the %s dir (pkgid=%s, workspace=%s, what=%?, where=%?",

src/librustpkg/source_control.rs

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,23 @@
1010

1111
// Utils for working with version control repositories. Just git right now.
1212

13-
use std::{io, os, run, str};
13+
use std::{os, run, str};
14+
use std::run::{ProcessOutput, ProcessOptions, Process};
1415
use version::*;
1516

1617
/// For a local git repo
1718
pub fn git_clone(source: &Path, target: &Path, v: &Version) {
1819
assert!(os::path_is_dir(source));
1920
assert!(is_git_dir(source));
2021
if !os::path_exists(target) {
21-
let version_args = match v {
22-
&ExactRevision(ref s) => ~[~"--branch", s.to_owned()],
23-
_ => ~[]
24-
};
25-
debug!("Running: git clone %s %s %s", version_args.to_str(), source.to_str(),
22+
debug!("Running: git clone %s %s", source.to_str(),
2623
target.to_str());
27-
let outp = run::process_output("git", ~[~"clone"] + version_args +
28-
~[source.to_str(), target.to_str()]);
29-
if outp.status != 0 {
30-
io::println(str::from_bytes_owned(outp.output.clone()));
31-
io::println(str::from_bytes_owned(outp.error));
32-
fail!("Couldn't `git clone` %s", source.to_str());
33-
}
24+
assert!(git_clone_general(source.to_str(), target, v));
3425
}
3526
else {
3627
// Pull changes
28+
// Note that this ignores tags, which is probably wrong. There are no tests for
29+
// it, though.
3730
debug!("Running: git --work-tree=%s --git-dir=%s pull --no-edit %s",
3831
target.to_str(), target.push(".git").to_str(), source.to_str());
3932
let outp = run::process_output("git", [fmt!("--work-tree=%s", target.to_str()),
@@ -43,6 +36,40 @@ pub fn git_clone(source: &Path, target: &Path, v: &Version) {
4336
}
4437
}
4538

39+
/// Source can be either a URL or a local file path.
40+
/// true if successful
41+
pub fn git_clone_general(source: &str, target: &Path, v: &Version) -> bool {
42+
let outp = run::process_output("git", [~"clone", source.to_str(), target.to_str()]);
43+
if outp.status != 0 {
44+
debug!(str::from_bytes_owned(outp.output.clone()));
45+
debug!(str::from_bytes_owned(outp.error));
46+
false
47+
}
48+
else {
49+
match v {
50+
&ExactRevision(ref s) | &Tagged(ref s) => {
51+
let outp = process_output_in_cwd("git", [~"checkout", fmt!("%s", *s)],
52+
target);
53+
if outp.status != 0 {
54+
debug!(str::from_bytes_owned(outp.output.clone()));
55+
debug!(str::from_bytes_owned(outp.error));
56+
false
57+
}
58+
else {
59+
true
60+
}
61+
}
62+
_ => true
63+
}
64+
}
65+
}
66+
67+
fn process_output_in_cwd(prog: &str, args: &[~str], cwd: &Path) -> ProcessOutput {
68+
let mut prog = Process::new(prog, args, ProcessOptions{ dir: Some(cwd)
69+
,..ProcessOptions::new()});
70+
prog.finish_with_output()
71+
}
72+
4673
pub fn is_git_dir(p: &Path) -> bool {
4774
os::path_is_dir(&p.push(".git"))
4875
}

src/librustpkg/tests.rs

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::run::ProcessOutput;
1818
use installed_packages::list_installed_packages;
1919
use package_path::*;
2020
use package_id::{PkgId};
21-
use version::{ExactRevision, NoVersion, Version};
21+
use version::{ExactRevision, NoVersion, Version, Tagged};
2222
use path_util::{target_executable_in_workspace, target_library_in_workspace,
2323
target_test_in_workspace, target_bench_in_workspace,
2424
make_dir_rwx, U_RWX, library_in_workspace,
@@ -61,6 +61,16 @@ fn git_repo_pkg() -> PkgId {
6161
}
6262
}
6363

64+
fn git_repo_pkg_with_tag(a_tag: ~str) -> PkgId {
65+
let remote = RemotePath(Path("mockgithub.com/catamorphism/test-pkg"));
66+
PkgId {
67+
local_path: normalize(remote.clone()),
68+
remote_path: remote,
69+
short_name: ~"test_pkg",
70+
version: Tagged(a_tag)
71+
}
72+
}
73+
6474
fn writeFile(file_path: &Path, contents: &str) {
6575
let out = io::file_writer(file_path, [io::Create, io::Truncate]).unwrap();
6676
out.write_line(contents);
@@ -148,9 +158,13 @@ fn init_git_repo(p: &Path) -> Path {
148158
}
149159
}
150160

151-
fn add_git_tag(repo: &Path, tag: ~str) {
152-
assert!(repo.is_absolute());
153-
let mut prog = run::Process::new("git", [~"add", ~"-A"],
161+
fn add_all_and_commit(repo: &Path) {
162+
git_add_all(repo);
163+
git_commit(repo, ~"floop");
164+
}
165+
166+
fn git_commit(repo: &Path, msg: ~str) {
167+
let mut prog = run::Process::new("git", [~"commit", ~"-m", msg],
154168
run::ProcessOptions { env: None,
155169
dir: Some(repo),
156170
in_fd: None,
@@ -159,9 +173,14 @@ fn add_git_tag(repo: &Path, tag: ~str) {
159173
});
160174
let output = prog.finish_with_output();
161175
if output.status != 0 {
162-
fail!("Couldn't add all files in %s", repo.to_str())
176+
fail!("Couldn't commit in %s: output was %s", repo.to_str(),
177+
str::from_bytes(output.output + output.error))
163178
}
164-
prog = run::Process::new("git", [~"commit", ~"-m", ~"whatever"],
179+
180+
}
181+
182+
fn git_add_all(repo: &Path) {
183+
let mut prog = run::Process::new("git", [~"add", ~"-A"],
165184
run::ProcessOptions { env: None,
166185
dir: Some(repo),
167186
in_fd: None,
@@ -170,10 +189,16 @@ fn add_git_tag(repo: &Path, tag: ~str) {
170189
});
171190
let output = prog.finish_with_output();
172191
if output.status != 0 {
173-
fail!("Couldn't commit in %s", repo.to_str())
192+
fail!("Couldn't add all files in %s: output was %s",
193+
repo.to_str(), str::from_bytes(output.output + output.error))
174194
}
195+
}
175196

176-
prog = run::Process::new("git", [~"tag", tag.clone()],
197+
fn add_git_tag(repo: &Path, tag: ~str) {
198+
assert!(repo.is_absolute());
199+
git_add_all(repo);
200+
git_commit(repo, ~"whatever");
201+
let mut prog = run::Process::new("git", [~"tag", tag.clone()],
177202
run::ProcessOptions { env: None,
178203
dir: Some(repo),
179204
in_fd: None,
@@ -622,31 +647,6 @@ fn test_package_request_version() {
622647
writeFile(&repo_subdir.push("version-0.4-file.txt"), "hello");
623648
add_git_tag(&repo_subdir, ~"0.4");
624649
625-
/*
626-
627-
let pkg_src = PkgSrc::new(&repo, &repo, &temp_pkg_id);
628-
match temp_pkg_id.version {
629-
ExactRevision(~"0.3") => {
630-
debug!("Version matches, calling fetch_git");
631-
match pkg_src.fetch_git() {
632-
Some(p) => {
633-
debug!("does version-0.3-file exist?");
634-
assert!(os::path_exists(&p.push("version-0.3-file.txt")));
635-
debug!("does version-0.4-file exist?");
636-
assert!(!os::path_exists(&p.push("version-0.4-file.txt")));
637-
638-
}
639-
None => fail!("test_package_request_version: fetch_git failed")
640-
}
641-
}
642-
ExactRevision(n) => {
643-
fail!("n is %? and %? %s %?", n, n, if n == ~"0.3" { "==" } else { "!=" }, "0.3");
644-
}
645-
_ => fail!(fmt!("test_package_version: package version was %?, expected ExactRevision(0.3)",
646-
temp_pkg_id.version))
647-
}
648-
*/
649-
650650
command_line_test([~"install", fmt!("%s#0.3", local_path)], &repo);
651651
652652
assert!(match installed_library_in_workspace("test_pkg_version", &repo.push(".rust")) {
@@ -679,6 +679,7 @@ fn rustpkg_install_url_2() {
679679
}
680680
681681
// FIXME: #7956: temporarily disabled
682+
#[test]
682683
fn rustpkg_library_target() {
683684
let foo_repo = init_git_repo(&Path("foo"));
684685
let package_dir = foo_repo.push("foo");
@@ -705,8 +706,10 @@ fn rustpkg_local_pkg() {
705706
assert_executable_exists(&dir, "foo");
706707
}
707708
709+
// FIXME: #7956: temporarily disabled
710+
// Failing on dist-linux bot
708711
#[test]
709-
#[ignore] // XXX Failing on dist-linux bot
712+
#[ignore]
710713
fn package_script_with_default_build() {
711714
let dir = create_local_package(&PkgId::new("fancy-lib", &os::getcwd()));
712715
debug!("dir = %s", dir.to_str());
@@ -765,7 +768,7 @@ fn rustpkg_clean_no_arg() {
765768
}
766769
767770
#[test]
768-
#[ignore (reason = "Un-ignore when #7071 is fixed")]
771+
#[ignore (reason = "Specifying env doesn't work -- see #8028")]
769772
fn rust_path_test() {
770773
let dir_for_path = mkdtemp(&os::tmpdir(), "more_rust").expect("rust_path_test failed");
771774
let dir = mk_workspace(&dir_for_path, &normalize(RemotePath(Path("foo"))), &NoVersion);
@@ -774,9 +777,13 @@ fn rust_path_test() {
774777
775778
let cwd = os::getcwd();
776779
debug!("cwd = %s", cwd.to_str());
780+
debug!("Running command: cd %s; RUST_LOG=rustpkg RUST_PATH=%s rustpkg install foo",
781+
cwd.to_str(), dir_for_path.to_str());
777782
let mut prog = run::Process::new("rustpkg",
778783
[~"install", ~"foo"],
779-
run::ProcessOptions { env: Some(&[(~"RUST_PATH",
784+
run::ProcessOptions { env: Some(&[(~"RUST_LOG",
785+
~"rustpkg"),
786+
(~"RUST_PATH",
780787
dir_for_path.to_str())]),
781788
dir: Some(&cwd),
782789
in_fd: None,
@@ -954,7 +961,6 @@ fn do_rebuild_dep_only_contents_change() {
954961
}
955962
956963
#[test]
957-
#[ignore(reason = "list not yet implemented")]
958964
fn test_versions() {
959965
let workspace = create_local_package(&PkgId::new("foo#0.1", &os::getcwd()));
960966
create_local_package(&PkgId::new("foo#0.2", &os::getcwd()));
@@ -992,11 +998,35 @@ fn test_rustpkg_test() {
992998
}
993999
9941000
#[test]
995-
#[ignore(reason = "uninstall not yet implemented")]
9961001
fn test_uninstall() {
9971002
let workspace = create_local_package(&PkgId::new("foo", &os::getcwd()));
9981003
let _output = command_line_test([~"info", ~"foo"], &workspace);
9991004
command_line_test([~"uninstall", ~"foo"], &workspace);
10001005
let output = command_line_test([~"list"], &workspace);
10011006
assert!(!str::from_bytes(output.output).contains("foo"));
10021007
}
1008+
1009+
#[test]
1010+
fn test_non_numeric_tag() {
1011+
let temp_pkg_id = git_repo_pkg();
1012+
let repo = init_git_repo(&Path(temp_pkg_id.local_path.to_str()));
1013+
let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg");
1014+
writeFile(&repo_subdir.push("foo"), "foo");
1015+
writeFile(&repo_subdir.push("lib.rs"),
1016+
"pub fn f() { let _x = (); }");
1017+
add_git_tag(&repo_subdir, ~"testbranch");
1018+
writeFile(&repo_subdir.push("testbranch_only"), "hello");
1019+
add_git_tag(&repo_subdir, ~"another_tag");
1020+
writeFile(&repo_subdir.push("not_on_testbranch_only"), "bye bye");
1021+
add_all_and_commit(&repo_subdir);
1022+
1023+
1024+
command_line_test([~"install", fmt!("%s#testbranch", temp_pkg_id.remote_path.to_str())],
1025+
&repo);
1026+
let file1 = repo.push_many(["mockgithub.com", "catamorphism",
1027+
"test_pkg", "testbranch_only"]);
1028+
let file2 = repo.push_many(["mockgithub.com", "catamorphism", "test_pkg",
1029+
"master_only"]);
1030+
assert!(os::path_exists(&file1));
1031+
assert!(!os::path_exists(&file2));
1032+
}

src/librustpkg/usage.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,17 @@ List all installed packages.");
6363
}
6464

6565
pub fn install() {
66-
io::println("rustpkg [options..] install [url] [target]
66+
io::println("rustpkg [options..] install [package-ID]
6767
68-
Install a package from a URL by Git or cURL (FTP, HTTP, etc.).
69-
If target is provided, Git will checkout the branch or tag before
70-
continuing. If the URL is a TAR file (with or without compression),
71-
extract it before installing. If a URL isn't provided, the package will
72-
be built and installed from the current directory (which is
73-
functionally the same as `rustpkg build` and installing the result).
68+
Install the given package ID if specified. With no package ID
69+
argument, install the package in the current directory.
70+
In that case, the current directory must be a direct child of a
71+
`src` directory in a workspace.
7472
7573
Examples:
7674
rustpkg install
77-
rustpkg install git://github.com/mozilla/servo.git
78-
rustpkg install git://github.com/mozilla/servo.git v0.1.2
79-
rustpkg install http://rust-lang.org/servo-0.1.2.tar.gz
75+
rustpkg install github.com/mozilla/servo
76+
rustpkg install github.com/mozilla/servo#0.1.2
8077
8178
Options:
8279
-c, --cfg Pass a cfg flag to the package script");

0 commit comments

Comments
 (0)