Bug 1379482 - Upgrade mozrunner to 0.4.1; r?jgraham draft
authorAndreas Tolfsen <ato@sny.no>
Mon, 10 Jul 2017 16:52:41 +0100
changeset 606211 9c05f293fd0ce420790f5a043e6f4e4b29336df7
parent 606210 a1576cf3373da124bec3c64ff18d00cc7fb27aa7
child 606212 8c09ccb83024b38b2b9414ae549eb68f64928908
push id67641
push userbmo:ato@sny.no
push dateMon, 10 Jul 2017 17:24:19 +0000
reviewersjgraham
bugs1379482
milestone56.0a1
Bug 1379482 - Upgrade mozrunner to 0.4.1; r?jgraham Upgrades the mozrunner crate dependency by pinning it to 0.4.1. With `./mach vendor rust' I could not find any other way to force a new version to be downloaded because cargo, as far as I understand, does not yet support using crates.io as a fallback. This patch also pins the mozprofile and mozversion dependencies exactly, although this is strictly not needed yet because they we have the latest versions vendored in-tree. MozReview-Commit-ID: 8emDKbiYd0S
testing/geckodriver/Cargo.lock
testing/geckodriver/Cargo.toml
third_party/rust/mozrunner/.cargo-checksum.json
third_party/rust/mozrunner/Cargo.toml
third_party/rust/mozrunner/src/lib.rs
third_party/rust/mozrunner/src/runner.rs
--- a/testing/geckodriver/Cargo.lock
+++ b/testing/geckodriver/Cargo.lock
@@ -3,17 +3,17 @@ name = "geckodriver"
 version = "0.17.0"
 dependencies = [
  "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozprofile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "mozrunner 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mozrunner 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozversion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "slog 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "slog-atomic 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "slog-stdlog 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "slog-stream 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -291,17 +291,17 @@ name = "mozprofile"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mozrunner"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozprofile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winreg 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -713,17 +713,17 @@ dependencies = [
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
 "checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc"
 "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
 "checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1"
 "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
 "checksum mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d69889cdc6336ed56b174514ce876c4c3dc564cc23dd872e7bca589bb2a36c8"
 "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726"
 "checksum mozprofile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a17b8bbde1dc0fbf1c8b073192d7c6f89baa932173ece7c1447de5e9cc7cd7e"
-"checksum mozrunner 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a568168329fc285ad6d04dfbe058ea20ff842f4301fe9205c6cbd4ed3be85378"
+"checksum mozrunner 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "68e6a21ef32a737399a34d9a89640b350d8b47ef03457225c0c223842cf2311f"
 "checksum mozversion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9fb3a40135553611560d3eb4a49479beaf0c91c5a93f723338c5b0edddf08f26"
 "checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958"
 "checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40"
 "checksum num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "21e4df1098d1d797d27ef0c69c178c3fab64941559b290fcae198e0825c9c8b5"
 "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
 "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
 "checksum num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a225d1e2717567599c24f88e49f00856c6e825a12125181ee42c4257e3688d39"
 "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
--- a/testing/geckodriver/Cargo.toml
+++ b/testing/geckodriver/Cargo.toml
@@ -12,19 +12,19 @@ readme = "README.md"
 license = "MPL-2.0"
 
 [dependencies]
 chrono = "^0.2"
 clap = {version = "^2.19", default-features = false, features = ["suggestions", "wrap_help"]}
 hyper = "0.10"
 lazy_static = "0.1"
 log = "0.3"
-mozprofile = "0.3"
-mozrunner = "0.4"
-mozversion = "0.1"
+mozprofile = "0.3.0"
+mozrunner = "0.4.1"
+mozversion = "0.1.2"
 regex = "0.2"
 rustc-serialize = "0.3"
 slog = "1"
 slog-atomic = "0.4"
 slog-stdlog = "1"
 slog-stream = "1"
 uuid = "0.1.18"
 webdriver = "0.27.0"
--- a/third_party/rust/mozrunner/.cargo-checksum.json
+++ b/third_party/rust/mozrunner/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"25af4086ef96f79688c6888d88df053fc04d0ff8e3c4353a6aea91605afc58ef","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","src/bin/firefox-default-path.rs":"21f1aa96a4ffb368a4266e294bc4b1b17ff8229f2418af6679783f6d9c0280df","src/lib.rs":"3ed528f2069e810adb6f2ea0b248c4542de95f1cc305154f440877d4ee6d550c","src/runner.rs":"ed095febfb54c87648fecb4818e7726702f6e46053119ffd9316c664b7e93b3e"},"package":"a568168329fc285ad6d04dfbe058ea20ff842f4301fe9205c6cbd4ed3be85378"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"c9da3b2127ac20e0f3b7f87d7ee3a08a103f7893e92ee2835a3247af0389371f","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","src/bin/firefox-default-path.rs":"21f1aa96a4ffb368a4266e294bc4b1b17ff8229f2418af6679783f6d9c0280df","src/lib.rs":"26ea358c4bc1d45eb3b5ebc702b1a6bffdf5642acab9bbeffddb5be55ddb1b07","src/runner.rs":"ce33d910a0d63bb3673e159bc52f1fb4dafd9746415592f5f2bf792691f2adb2"},"package":"68e6a21ef32a737399a34d9a89640b350d8b47ef03457225c0c223842cf2311f"}
\ No newline at end of file
--- a/third_party/rust/mozrunner/Cargo.toml
+++ b/third_party/rust/mozrunner/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "mozrunner"
-version = "0.4.0"
+version = "0.4.1"
 authors = ["Mozilla Tools and Automation <auto-tools@mozilla.com>"]
 description = "Library for starting Firefox binaries."
 repository = "https://github.com/jgraham/rust_mozrunner"
 license = "MPL-2.0"
 
 [dependencies]
 log = "0.3"
 mozprofile = "0.3"
--- a/third_party/rust/mozrunner/src/lib.rs
+++ b/third_party/rust/mozrunner/src/lib.rs
@@ -1,8 +1,8 @@
-extern crate log;
+#[macro_use] extern crate log;
 extern crate mozprofile;
 #[cfg(target_os = "windows")]
 extern crate winreg;
 
 pub mod runner;
 
 pub use runner::platform::firefox_default_path;
--- a/third_party/rust/mozrunner/src/runner.rs
+++ b/third_party/rust/mozrunner/src/runner.rs
@@ -1,10 +1,11 @@
 use mozprofile::prefreader::PrefReaderError;
 use mozprofile::profile::Profile;
+use std::ascii::AsciiExt;
 use std::convert::From;
 use std::env;
 use std::error::Error;
 use std::fmt;
 use std::io::{Result as IoResult, Error as IoError, ErrorKind};
 use std::path::{Path, PathBuf};
 use std::process;
 use std::process::{Command, Stdio};
@@ -91,55 +92,111 @@ impl FirefoxRunner {
     }
 }
 
 impl Runner for FirefoxRunner {
     fn start(&mut self) -> Result<(), RunnerError> {
         let mut cmd = Command::new(&self.binary);
         self.build_command(&mut cmd);
 
+        debug!("Command {:?}", cmd);
+
         let prefs = try!(self.profile.user_prefs());
         try!(prefs.write());
 
         let process = try!(cmd.spawn());
         self.process = Some(process);
         Ok(())
     }
 
     fn args(&mut self) -> &mut Vec<String> {
         &mut self.args
     }
 
     fn build_command(&self, command: &mut Command) {
         command
             .env("MOZ_NO_REMOTE", "1")
             .env("NO_EM_RESTART", "1")
-            .args(&self.args[..])
-            .arg("-profile").arg(&self.profile.path)
-            .stdout(Stdio::inherit())
+            .args(&self.args[..]);
+
+        if !self.args.iter().any(|x| is_profile_arg(x)) {
+            command.arg("-profile").arg(&self.profile.path);
+        }
+        command.stdout(Stdio::inherit())
             .stderr(Stdio::inherit());
     }
 
     fn is_running(&self) -> bool {
         self.process.is_some() && self.ret_code.is_none()
     }
 
     fn stop(&mut self) -> IoResult<Option<process::ExitStatus>> {
-        match self.process.as_mut() {
-            Some(p) => {
-                try!(p.kill());
-                let status = try!(p.wait());
-                self.ret_code = Some(status);
-            },
-            None => {}
+        if let Some(p) = self.process.as_mut() {
+            try!(p.kill());
+            let status = try!(p.wait());
+            self.ret_code = Some(status);
         };
         Ok(self.ret_code)
     }
 }
 
+fn parse_arg_name(arg: &str) -> Option<&str> {
+    let mut start = 0;
+    let mut end = 0;
+
+    for (i, c) in arg.chars().enumerate() {
+        if i == 0 {
+            if !platform::arg_prefix_char(c) {
+                break;
+            }
+        } else if i == 1 {
+            if name_end_char(c) {
+                break;
+            } else if c != '-' {
+                start = i;
+                end = start + 1;
+            } else {
+                start = i + 1;
+                end = start;
+            }
+        } else {
+            end += 1;
+            if name_end_char(c) {
+                end -= 1;
+                break;
+            }
+        }
+    }
+
+    if start > 0 && end > start {
+        Some(&arg[start..end])
+    } else {
+        None
+    }
+}
+
+fn name_end_char(c: char) -> bool {
+    c == ' ' || c == '='
+}
+
+/// Check if an argument string affects the Firefox profile
+///
+/// Returns a boolean indicating whether a given string
+/// contains one of the `-P`, `-Profile` or `-ProfileManager`
+/// arguments, respecting the various platform-specific conventions.
+pub fn is_profile_arg(arg: &str) -> bool {
+    if let Some(name) = parse_arg_name(arg) {
+        name.eq_ignore_ascii_case("profile") ||
+            name.eq_ignore_ascii_case("p") ||
+            name.eq_ignore_ascii_case("profilemanager")
+    } else {
+        false
+    }
+}
+
 fn find_binary(name: &str) -> Option<PathBuf> {
     env::var("PATH")
         .ok()
         .and_then(|path_env| {
             for mut path in env::split_paths(&*path_env) {
                 path.push(name);
                 if path.exists() {
                     return Some(path)
@@ -152,16 +209,20 @@ fn find_binary(name: &str) -> Option<Pat
 #[cfg(target_os = "linux")]
 pub mod platform {
     use super::find_binary;
     use std::path::PathBuf;
 
     pub fn firefox_default_path() -> Option<PathBuf> {
         find_binary("firefox")
     }
+
+    pub fn arg_prefix_char(c: char) -> bool {
+        c == '-'
+    }
 }
 
 #[cfg(target_os = "macos")]
 pub mod platform {
     use super::find_binary;
     use std::env;
     use std::path::PathBuf;
 
@@ -179,16 +240,20 @@ pub mod platform {
                 (_, false) => PathBuf::from(trial_path)
             };
             if path.exists() {
                 return Some(path)
             }
         }
         None
     }
+
+    pub fn arg_prefix_char(c: char) -> bool {
+        c == '-'
+    }
 }
 
 #[cfg(target_os = "windows")]
 pub mod platform {
     use super::find_binary;
     use std::io::Error;
     use std::path::PathBuf;
     use winreg::RegKey;
@@ -229,18 +294,83 @@ pub mod platform {
                             }
                         }
                     }
                 }
             }
         }
         Ok(None)
     }
+
+    pub fn arg_prefix_char(c: char) -> bool {
+        c == '/' || c == '-'
+    }
 }
 
 #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
 pub mod platform {
     use std::path::PathBuf;
 
     pub fn firefox_default_path() -> Option<PathBuf> {
         None
     }
+
+    pub fn arg_prefix_char(c: char) -> bool {
+        c == '-'
+    }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::{parse_arg_name, is_profile_arg};
+
+    fn parse(arg: &str, name: Option<&str>) {
+        let result = parse_arg_name(arg);
+        assert_eq!(result, name);
+    }
+
+    #[test]
+    fn test_parse_arg_name() {
+        parse("-p", Some("p"));
+        parse("--p", Some("p"));
+        parse("--profile foo", Some("profile"));
+        parse("--profile", Some("profile"));
+        parse("--", None);
+        parse("", None);
+        parse("-=", None);
+        parse("--=", None);
+        parse("-- foo", None);
+        parse("foo", None);
+        parse("/ foo", None);
+        parse("/- foo", None);
+        parse("/=foo", None);
+        parse("foo", None);
+        parse("-profile", Some("profile"));
+        parse("-profile=foo", Some("profile"));
+        parse("-profile = foo", Some("profile"));
+        parse("-profile abc", Some("profile"));
+    }
+
+    #[cfg(target_os = "windows")]
+    #[test]
+    fn test_parse_arg_name_windows() {
+        parse("/profile", Some("profile"));
+    }
+
+    #[cfg(not(target_os = "windows"))]
+    #[test]
+    fn test_parse_arg_name_non_windows() {
+        parse("/profile", None);
+    }
+
+    #[test]
+    fn test_is_profile_arg() {
+        assert!(is_profile_arg("--profile"));
+        assert!(is_profile_arg("-p"));
+        assert!(is_profile_arg("-PROFILEMANAGER"));
+        assert!(is_profile_arg("-ProfileMANAGER"));
+        assert!(!is_profile_arg("-- profile"));
+        assert!(!is_profile_arg("-profiled"));
+        assert!(!is_profile_arg("-p1"));
+        assert!(is_profile_arg("-p test"));
+        assert!(is_profile_arg("-profile /foo"));
+    }
+}