From 015e79728c972036e125916cee76e6460da51493 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Hern=C3=A1ndez?= <juan.hernandez.babon@gmail.com>
Date: Wed, 14 Sep 2016 15:02:47 -0400
Subject: [PATCH] FIX: Don't try to generate Gargo.lock on empty workspaces.

There was a panic! when the command `cargo update` was
executed in a workspace like this:

    mkdir ws
    cd ws
    echo '[workspace]' > Cargo.toml
    cargo new p1
    cargo new p2
    cargo update

The problem is that cargo tries to generate the Cargo.lock file
even if there aren't any members on the workspace.

This fix checks the existence of members in the workspace before trying
to do anything so at least we report an error instead of throwing a
panic!
---
 src/cargo/core/workspace.rs              |  8 +++++++-
 src/cargo/ops/cargo_generate_lockfile.rs |  4 ++++
 tests/workspaces.rs                      | 22 ++++++++++++++++++++++
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs
index bdf00a44e83..afa6e3bf2b1 100644
--- a/src/cargo/core/workspace.rs
+++ b/src/cargo/core/workspace.rs
@@ -101,7 +101,7 @@ impl<'cfg> Workspace<'cfg> {
         Ok(ws)
     }
 
-    /// Creates a "tempoarary workspace" from one package which only contains
+    /// Creates a "temporary workspace" from one package which only contains
     /// that package.
     ///
     /// This constructor will not touch the filesystem and only creates an
@@ -464,6 +464,12 @@ impl<'cfg> Packages<'cfg> {
     }
 }
 
+impl<'a, 'cfg> Members<'a, 'cfg> {
+    pub fn is_empty(self) -> bool {
+        self.count() == 0
+    }
+}
+
 impl<'a, 'cfg> Iterator for Members<'a, 'cfg> {
     type Item = &'a Package;
 
diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs
index 45ee2b10111..6a6d198b35b 100644
--- a/src/cargo/ops/cargo_generate_lockfile.rs
+++ b/src/cargo/ops/cargo_generate_lockfile.rs
@@ -31,6 +31,10 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions)
         bail!("cannot specify both aggressive and precise simultaneously")
     }
 
+    if ws.members().is_empty() {
+        bail!("you can't generate a lockfile for an empty workspace.")
+    }
+
     let previous_resolve = match try!(ops::load_pkg_lockfile(ws)) {
         Some(resolve) => resolve,
         None => return generate_lockfile(ws),
diff --git a/tests/workspaces.rs b/tests/workspaces.rs
index ab3b117fab8..08be87bf4cf 100644
--- a/tests/workspaces.rs
+++ b/tests/workspaces.rs
@@ -940,3 +940,25 @@ fn lockfile_can_specify_nonexistant_members() {
 
     assert_that(p.cargo("build").cwd(p.root().join("a")), execs().with_status(0));
 }
+
+#[test]
+fn you_cannot_generate_lockfile_for_empty_workspaces() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [workspace]
+        "#)
+        .file("bar/Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.1.0"
+            authors = []
+        "#)
+        .file("bar/src/main.rs", "fn main() {}");
+    p.build();
+
+    assert_that(p.cargo("update"),
+                execs().with_status(101)
+                       .with_stderr("\
+error: you can't generate a lockfile for an empty workspace.
+"));
+}