1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-02 14:07:46 +00:00

Merge branch 'master' of github.com:uutils/coreutils into hbina-tr-reimplement-expansion

Signed-off-by: Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com>
This commit is contained in:
Hanif Bin Ariffin 2021-10-12 07:39:00 +08:00
commit c4de592e90
34 changed files with 227 additions and 154 deletions

View file

@ -6,9 +6,6 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
#[macro_use]
extern crate uucore;
use platform_info::*;
use clap::{crate_version, App};

View file

@ -5,9 +5,6 @@
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.
#[macro_use]
extern crate uucore;
use std::io::{stdin, Read};
use clap::App;

View file

@ -6,9 +6,6 @@
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.
#[macro_use]
extern crate uucore;
use uu_base32::base_common;
pub use uu_base32::uu_app;

View file

@ -8,9 +8,6 @@
//spell-checker:ignore (args) lsbf msbf
#[macro_use]
extern crate uucore;
use clap::{App, Arg};
use uu_base32::base_common::{self, Config, BASE_CMD_PARSE_ERROR};

View file

@ -12,8 +12,6 @@
#[cfg(unix)]
extern crate unix_socket;
#[macro_use]
extern crate uucore;
// last synced with: cat (GNU coreutils) 8.13
use clap::{crate_version, App, Arg};

View file

@ -7,8 +7,6 @@
// spell-checker:ignore (ToDO) COMFOLLOW Chowner RFILE RFILE's derefer dgid nonblank nonprint nonprinting
#[macro_use]
extern crate uucore;
use uucore::display::Quotable;
pub use uucore::entries;
use uucore::error::{FromIo, UResult, USimpleError};

View file

@ -7,8 +7,6 @@
// spell-checker:ignore (ToDO) COMFOLLOW Passwd RFILE RFILE's derefer dgid duid groupname
#[macro_use]
extern crate uucore;
use uucore::display::Quotable;
pub use uucore::entries::{self, Group, Locate, Passwd};
use uucore::perms::{chown_base, options, IfFrom};

View file

@ -67,7 +67,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
// TODO: refactor the args and command matching
// See: https://github.com/uutils/coreutils/pull/2365#discussion_r647849967
let command: Vec<&str> = match commands.len() {
1 => {
0 => {
let shell: &str = match user_shell {
Err(_) => default_shell,
Ok(ref s) => s.as_ref(),
@ -77,12 +77,28 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
_ => commands,
};
assert!(!command.is_empty());
let chroot_command = command[0];
let chroot_args = &command[1..];
// NOTE: Tests can only trigger code beyond this point if they're invoked with root permissions
set_context(newroot, &matches);
let pstatus = Command::new(command[0])
.args(&command[1..])
let pstatus = Command::new(chroot_command)
.args(chroot_args)
.status()
.unwrap_or_else(|e| crash!(1, "Cannot exec: {}", e));
.unwrap_or_else(|e| {
// TODO: Exit status:
// 125 if chroot itself fails
// 126 if command is found but cannot be invoked
// 127 if command cannot be found
crash!(
1,
"failed to run command {}: {}",
command[0].to_string().quote(),
e
)
});
if pstatus.success() {
0

View file

@ -49,6 +49,7 @@ use std::path::{Path, PathBuf, StripPrefixError};
use std::str::FromStr;
use std::string::ToString;
use uucore::backup_control::{self, BackupMode};
use uucore::error::{set_exit_code, ExitCode, UError, UResult};
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
use walkdir::WalkDir;
@ -105,6 +106,12 @@ quick_error! {
}
}
impl UError for Error {
fn code(&self) -> i32 {
EXIT_ERR
}
}
/// Continue next iteration of loop if result of expression is error
macro_rules! or_continue(
($expr:expr) => (match $expr {
@ -220,7 +227,6 @@ pub struct Options {
static ABOUT: &str = "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.";
static LONG_HELP: &str = "";
static EXIT_OK: i32 = 0;
static EXIT_ERR: i32 = 1;
fn usage() -> String {
@ -446,7 +452,8 @@ pub fn uu_app() -> App<'static, 'static> {
.multiple(true))
}
pub fn uumain(args: impl uucore::Args) -> i32 {
#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let usage = usage();
let matches = uu_app()
.after_help(&*format!(
@ -457,11 +464,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.usage(&usage[..])
.get_matches_from(args);
let options = crash_if_err!(EXIT_ERR, Options::from_matches(&matches));
let options = Options::from_matches(&matches)?;
if options.overwrite == OverwriteMode::NoClobber && options.backup != BackupMode::NoBackup {
show_usage_error!("options --backup and --no-clobber are mutually exclusive");
return 1;
return Err(ExitCode(EXIT_ERR).into());
}
let paths: Vec<String> = matches
@ -469,7 +476,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let (sources, target) = crash_if_err!(EXIT_ERR, parse_path_args(&paths, &options));
let (sources, target) = parse_path_args(&paths, &options)?;
if let Err(error) = copy(&sources, &target, &options) {
match error {
@ -479,10 +486,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
// Else we caught a fatal bubbled-up error, log it to stderr
_ => show_error!("{}", error),
};
return EXIT_ERR;
set_exit_code(EXIT_ERR);
}
EXIT_OK
Ok(())
}
impl ClobberMode {
@ -1124,7 +1131,7 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu
let xattrs = xattr::list(source)?;
for attr in xattrs {
if let Some(attr_value) = xattr::get(source, attr.clone())? {
crash_if_err!(EXIT_ERR, xattr::set(dest, attr, &attr_value[..]));
xattr::set(dest, attr, &attr_value[..])?;
}
}
}

View file

@ -6,8 +6,6 @@
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.
#[macro_use]
extern crate uucore;
use uucore::error::UError;
use uucore::error::UResult;
#[cfg(unix)]

View file

@ -5,9 +5,6 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
#[macro_use]
extern crate uucore;
use clap::{crate_version, App, Arg};
use std::path::Path;
use uucore::display::print_verbatim;

View file

@ -6,9 +6,6 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
#[macro_use]
extern crate uucore;
use clap::{crate_version, App, Arg};
use std::io::{self, Write};
use std::iter::Peekable;

View file

@ -5,9 +5,6 @@
//* For the full copyright and license information, please view the LICENSE
//* file that was distributed with this source code.
#[macro_use]
extern crate uucore;
use clap::{crate_version, App, Arg};
use uucore::error::{UResult, USimpleError};
use uucore::InvalidEncodingHandling;

View file

@ -5,9 +5,6 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
#[macro_use]
extern crate uucore;
use clap::App;
use uucore::error::UResult;

View file

@ -7,9 +7,6 @@
// spell-checker:ignore (ToDO) gethostid
#[macro_use]
extern crate uucore;
use clap::{crate_version, App};
use libc::c_long;
use uucore::error::UResult;

View file

@ -7,9 +7,6 @@
// spell-checker:ignore (ToDO) MAKEWORD addrs hashset
#[macro_use]
extern crate uucore;
use std::collections::hash_set::HashSet;
use std::net::ToSocketAddrs;
use std::str;

View file

@ -8,9 +8,6 @@
// spell-checker:ignore (paths) GPGHome
#[macro_use]
extern crate uucore;
use clap::{crate_version, App, Arg};
use uucore::display::{println_verbatim, Quotable};
use uucore::error::{FromIo, UError, UResult};

View file

@ -20,7 +20,7 @@ use quick_error::ResultExt;
use regex::Regex;
use std::convert::From;
use std::fs::{metadata, File};
use std::io::{stdin, stdout, BufRead, BufReader, Lines, Read, Stdout, Write};
use std::io::{stdin, stdout, BufRead, BufReader, Lines, Read, Write};
#[cfg(unix)]
use std::os::unix::fs::FileTypeExt;
@ -1036,15 +1036,16 @@ fn print_page(lines: &[FileLine], options: &OutputOptions, page: usize) -> Resul
let header = header_content(options, page);
let trailer_content = trailer_content(options);
let out = &mut stdout();
out.lock();
let out = stdout();
let mut out = out.lock();
for x in header {
out.write_all(x.as_bytes())?;
out.write_all(line_separator)?;
}
let lines_written = write_columns(lines, options, out)?;
let lines_written = write_columns(lines, options, &mut out)?;
for (index, x) in trailer_content.iter().enumerate() {
out.write_all(x.as_bytes())?;
@ -1060,7 +1061,7 @@ fn print_page(lines: &[FileLine], options: &OutputOptions, page: usize) -> Resul
fn write_columns(
lines: &[FileLine],
options: &OutputOptions,
out: &mut Stdout,
out: &mut impl Write,
) -> Result<usize, IOError> {
let line_separator = options.content_line_separator.as_bytes();

View file

@ -5,9 +5,6 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
#[macro_use]
extern crate uucore;
use clap::{crate_version, App, Arg};
use std::env;
use std::io;

View file

@ -88,30 +88,65 @@ impl FromStr for Number {
if s.starts_with('+') {
s = &s[1..];
}
let is_neg = s.starts_with('-');
match s.parse::<BigInt>() {
Ok(n) => {
// If `s` is '-0', then `parse()` returns
// `BigInt::zero()`, but we need to return
// `Number::MinusZero` instead.
if n == BigInt::zero() && s.starts_with('-') {
Ok(Number::MinusZero)
} else {
Ok(Number::BigInt(n))
match s.to_lowercase().find("0x") {
Some(i) if i <= 1 => match &s.as_bytes()[i + 2] {
b'-' | b'+' => Err(format!(
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
s.quote(),
uucore::execution_phrase(),
)),
// TODO: hexadecimal floating point parsing (see #2660)
b'.' => Err(format!(
"NotImplemented: hexadecimal floating point numbers: {}\nTry '{} --help' for more information.",
s.quote(),
uucore::execution_phrase(),
)),
_ => {
let num = BigInt::from_str_radix(&s[i + 2..], 16)
.map_err(|_| format!(
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
s.quote(),
uucore::execution_phrase(),
))?;
match (is_neg, num == BigInt::zero()) {
(true, true) => Ok(Number::MinusZero),
(true, false) => Ok(Number::BigInt(-num)),
(false, _) => Ok(Number::BigInt(num)),
}
}
},
Some(_) => Err(format!(
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
s.quote(),
uucore::execution_phrase(),
)),
None => match s.parse::<BigInt>() {
Ok(n) => {
// If `s` is '-0', then `parse()` returns
// `BigInt::zero()`, but we need to return
// `Number::MinusZero` instead.
if n == BigInt::zero() && is_neg {
Ok(Number::MinusZero)
} else {
Ok(Number::BigInt(n))
}
}
}
Err(_) => match s.parse::<f64>() {
Ok(value) if value.is_nan() => Err(format!(
Err(_) => match s.parse::<f64>() {
Ok(value) if value.is_nan() => Err(format!(
"invalid 'not-a-number' argument: {}\nTry '{} --help' for more information.",
s.quote(),
uucore::execution_phrase(),
)),
Ok(value) => Ok(Number::F64(value)),
Err(_) => Err(format!(
Ok(value) => Ok(Number::F64(value)),
Err(_) => Err(format!(
"invalid floating point argument: {}\nTry '{} --help' for more information.",
s.quote(),
uucore::execution_phrase(),
)),
},
},
}
}

View file

@ -5,9 +5,6 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
#[macro_use]
extern crate uucore;
use std::thread;
use std::time::Duration;

View file

@ -5,9 +5,6 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
#[macro_use]
extern crate uucore;
use clap::App;
use uucore::error::UResult;

View file

@ -7,9 +7,6 @@
/* last synced with: unlink (GNU coreutils) 8.21 */
#[macro_use]
extern crate uucore;
use std::fs::remove_file;
use std::path::Path;

View file

@ -11,8 +11,6 @@
use chrono::{Local, TimeZone, Utc};
use clap::{crate_version, App, Arg};
#[macro_use]
extern crate uucore;
// import crate time from utmpx
pub use uucore::libc;
use uucore::libc::time_t;

View file

@ -11,6 +11,7 @@
use std::path::Path;
use clap::{crate_version, App, Arg};
use uucore::error::UResult;
use uucore::utmpx::{self, Utmpx};
static ABOUT: &str = "Print the user names of users currently logged in to the current host";
@ -29,7 +30,8 @@ If FILE is not specified, use {}. /var/log/wtmp as FILE is common.",
)
}
pub fn uumain(args: impl uucore::Args) -> i32 {
#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let usage = usage();
let after_help = get_long_usage();
@ -59,7 +61,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
println!("{}", users.join(" "));
}
0
Ok(())
}
pub fn uu_app() -> App<'static, 'static> {

View file

@ -9,8 +9,6 @@
#[macro_use]
extern crate clap;
#[macro_use]
extern crate uucore;
use clap::App;

View file

@ -12,8 +12,6 @@ use std::io::{self, Write};
#[macro_use]
extern crate clap;
#[macro_use]
extern crate uucore;
use clap::{App, Arg};
use uucore::error::{UResult, USimpleError};

View file

@ -101,7 +101,7 @@ pub fn gen_uumain(_args: TokenStream, stream: TokenStream) -> TokenStream {
Err(e) => {
let s = format!("{}", e);
if s != "" {
show_error!("{}", s);
uucore::show_error!("{}", s);
}
if e.usage() {
eprintln!("Try '{} --help' for more information.", uucore::execution_phrase());

View file

@ -15,6 +15,7 @@ fn test_missing_operand() {
#[test]
fn test_enter_chroot_fails() {
// NOTE: since #2689 this test also ensures that we don't regress #2687
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir("jail");
@ -89,3 +90,26 @@ fn test_preference_of_userspec() {
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
}
#[test]
fn test_default_shell() {
// NOTE: This test intends to trigger code which can only be reached with root permissions.
let ts = TestScenario::new(util_name!());
let at = &ts.fixtures;
let dir = "CHROOT_DIR";
at.mkdir(dir);
let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string());
let _expected = format!(
"chroot: failed to run command '{}': No such file or directory",
shell
);
// TODO: [2021-09; jhscheer] uncomment if/when #2692 gets merged
// if let Ok(result) = run_ucmd_as_root(&ts, &[dir]) {
// result.stderr_contains(expected);
// } else {
// print!("TEST SKIPPED");
// }
}

View file

@ -28,9 +28,7 @@ macro_rules! fixture_path {
macro_rules! assert_fixture_exists {
($fname:expr) => {{
let fpath = fixture_path!($fname);
if !fpath.exists() {
panic!("Fixture missing: {:?}", fpath);
}
assert!(fpath.exists(), "Fixture missing: {:?}", fpath);
}};
}
@ -38,9 +36,7 @@ macro_rules! assert_fixture_exists {
macro_rules! assert_fixture_not_exists {
($fname:expr) => {{
let fpath = PathBuf::from(format!("./fixtures/dd/{}", $fname));
if fpath.exists() {
panic!("Fixture present: {:?}", fpath);
}
assert!(!fpath.exists(), "Fixture present: {:?}", fpath);
}};
}

View file

@ -1,3 +1,4 @@
// spell-checker:ignore abcdefghijklmnopqrstuvwxyz
// * This file is part of the uutils coreutils package.
// *
// * For the full copyright and license information, please view the LICENSE
@ -35,9 +36,10 @@ fn test_file() {
{
let mut f = File::create(&file).unwrap();
// spell-checker:disable-next-line
if f.write_all(b"abcdefghijklmnopqrstuvwxyz\n").is_err() {
panic!("Test setup failed - could not write file");
}
assert!(
!f.write_all(b"abcdefghijklmnopqrstuvwxyz\n").is_err(),
"Test setup failed - could not write file"
);
}
new_ucmd!()
@ -75,9 +77,10 @@ fn test_2files() {
// spell-checker:disable-next-line
for &(path, data) in &[(&file1, "abcdefghijklmnop"), (&file2, "qrstuvwxyz\n")] {
let mut f = File::create(&path).unwrap();
if f.write_all(data.as_bytes()).is_err() {
panic!("Test setup failed - could not write file");
}
assert!(
!f.write_all(data.as_bytes()).is_err(),
"Test setup failed - could not write file"
);
}
new_ucmd!()
@ -126,9 +129,10 @@ fn test_from_mixed() {
let (data1, data2, data3) = ("abcdefg", "hijklmnop", "qrstuvwxyz\n");
for &(path, data) in &[(&file1, data1), (&file3, data3)] {
let mut f = File::create(&path).unwrap();
if f.write_all(data.as_bytes()).is_err() {
panic!("Test setup failed - could not write file");
}
assert!(
!f.write_all(data.as_bytes()).is_err(),
"Test setup failed - could not write file"
);
}
new_ucmd!()

View file

@ -1,6 +1,69 @@
use crate::common::util::*;
use std::io::Read;
#[test]
fn test_hex_rejects_sign_after_identifier() {
new_ucmd!()
.args(&["0x-123ABC"])
.fails()
.no_stdout()
.stderr_contains("invalid hexadecimal argument: '0x-123ABC'")
.stderr_contains("for more information.");
new_ucmd!()
.args(&["0x+123ABC"])
.fails()
.no_stdout()
.stderr_contains("invalid hexadecimal argument: '0x+123ABC'")
.stderr_contains("for more information.");
new_ucmd!()
.args(&["-0x-123ABC"])
.fails()
.no_stdout()
.stderr_contains("invalid hexadecimal argument: '-0x-123ABC'")
.stderr_contains("for more information.");
new_ucmd!()
.args(&["-0x+123ABC"])
.fails()
.no_stdout()
.stderr_contains("invalid hexadecimal argument: '-0x+123ABC'")
.stderr_contains("for more information.");
}
#[test]
fn test_hex_lowercase_uppercase() {
new_ucmd!()
.args(&["0xa", "0xA"])
.succeeds()
.stdout_is("10\n");
new_ucmd!()
.args(&["0Xa", "0XA"])
.succeeds()
.stdout_is("10\n");
}
#[test]
fn test_hex_big_number() {
new_ucmd!()
.args(&[
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
"0x100000000000000000000000000000000",
])
.succeeds()
.stdout_is(
"340282366920938463463374607431768211455\n340282366920938463463374607431768211456\n",
);
}
#[test]
fn test_hex_identifier_in_wrong_place() {
new_ucmd!()
.args(&["1234ABCD0x"])
.fails()
.no_stdout()
.stderr_contains("invalid hexadecimal argument: '1234ABCD0x'")
.stderr_contains("for more information.");
}
#[test]
fn test_rejects_nan() {
let ts = TestScenario::new(util_name!());

View file

@ -163,25 +163,23 @@ impl CmdResult {
/// asserts that the command resulted in a success (zero) status code
pub fn success(&self) -> &CmdResult {
if !self.success {
panic!(
"Command was expected to succeed.\nstdout = {}\n stderr = {}",
self.stdout_str(),
self.stderr_str()
);
}
assert!(
self.success,
"Command was expected to succeed.\nstdout = {}\n stderr = {}",
self.stdout_str(),
self.stderr_str()
);
self
}
/// asserts that the command resulted in a failure (non-zero) status code
pub fn failure(&self) -> &CmdResult {
if self.success {
panic!(
"Command was expected to fail.\nstdout = {}\n stderr = {}",
self.stdout_str(),
self.stderr_str()
);
}
assert!(
!self.success,
"Command was expected to fail.\nstdout = {}\n stderr = {}",
self.stdout_str(),
self.stderr_str()
);
self
}
@ -197,12 +195,11 @@ impl CmdResult {
/// 1. you can not know exactly what stdout will be or
/// 2. you know that stdout will also be empty
pub fn no_stderr(&self) -> &CmdResult {
if !self.stderr.is_empty() {
panic!(
"Expected stderr to be empty, but it's:\n{}",
self.stderr_str()
);
}
assert!(
self.stderr.is_empty(),
"Expected stderr to be empty, but it's:\n{}",
self.stderr_str()
);
self
}
@ -213,12 +210,11 @@ impl CmdResult {
/// 1. you can not know exactly what stderr will be or
/// 2. you know that stderr will also be empty
pub fn no_stdout(&self) -> &CmdResult {
if !self.stdout.is_empty() {
panic!(
"Expected stdout to be empty, but it's:\n{}",
self.stderr_str()
);
}
assert!(
self.stdout.is_empty(),
"Expected stdout to be empty, but it's:\n{}",
self.stderr_str()
);
self
}
@ -868,9 +864,7 @@ impl UCommand {
/// Add a parameter to the invocation. Path arguments are treated relative
/// to the test environment directory.
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut UCommand {
if self.has_run {
panic!("{}", ALREADY_RUN);
}
assert!(!self.has_run, ALREADY_RUN);
self.comm_string.push(' ');
self.comm_string
.push_str(arg.as_ref().to_str().unwrap_or_default());
@ -881,9 +875,7 @@ impl UCommand {
/// Add multiple parameters to the invocation. Path arguments are treated relative
/// to the test environment directory.
pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut UCommand {
if self.has_run {
panic!("{}", MULTIPLE_STDIN_MEANINGLESS);
}
assert!(!self.has_run, MULTIPLE_STDIN_MEANINGLESS);
let strings = args
.iter()
.map(|s| s.as_ref().to_os_string())
@ -901,9 +893,7 @@ impl UCommand {
/// provides standard input to feed in to the command when spawned
pub fn pipe_in<T: Into<Vec<u8>>>(&mut self, input: T) -> &mut UCommand {
if self.bytes_into_stdin.is_some() {
panic!("{}", MULTIPLE_STDIN_MEANINGLESS);
}
assert!(!self.bytes_into_stdin.is_some(), MULTIPLE_STDIN_MEANINGLESS);
self.bytes_into_stdin = Some(input.into());
self
}
@ -918,9 +908,7 @@ impl UCommand {
/// This is typically useful to test non-standard workflows
/// like feeding something to a command that does not read it
pub fn ignore_stdin_write_error(&mut self) -> &mut UCommand {
if self.bytes_into_stdin.is_none() {
panic!("{}", NO_STDIN_MEANINGLESS);
}
assert!(!self.bytes_into_stdin.is_none(), NO_STDIN_MEANINGLESS);
self.ignore_stdin_write_error = true;
self
}
@ -930,9 +918,7 @@ impl UCommand {
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
if self.has_run {
panic!("{}", ALREADY_RUN);
}
assert!(!self.has_run, ALREADY_RUN);
self.raw.env(key, val);
self
}
@ -951,9 +937,7 @@ impl UCommand {
/// Spawns the command, feeds the stdin if any, and returns the
/// child process immediately.
pub fn run_no_wait(&mut self) -> Child {
if self.has_run {
panic!("{}", ALREADY_RUN);
}
assert!(!self.has_run, ALREADY_RUN);
self.has_run = true;
log_info("run", &self.comm_string);
let mut child = self

View file

@ -5,12 +5,12 @@
set -e
if test ! -d ../gnu; then
echo "Could not find ../gnu"
echo "git clone git@github.com:coreutils/coreutils.git gnu"
echo "git clone https://github.com:coreutils/coreutils.git gnu"
exit 1
fi
if test ! -d ../gnulib; then
echo "Could not find ../gnulib"
echo "git clone git@github.com:coreutils/gnulib.git gnulib"
echo "git clone https://github.com/coreutils/gnulib.git gnulib"
exit 1
fi