mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-03 06:27:45 +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:
commit
c4de592e90
34 changed files with 227 additions and 154 deletions
|
@ -6,9 +6,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use platform_info::*;
|
use platform_info::*;
|
||||||
|
|
||||||
use clap::{crate_version, App};
|
use clap::{crate_version, App};
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE file
|
// For the full copyright and license information, please view the LICENSE file
|
||||||
// that was distributed with this source code.
|
// that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use std::io::{stdin, Read};
|
use std::io::{stdin, Read};
|
||||||
|
|
||||||
use clap::App;
|
use clap::App;
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE file
|
// For the full copyright and license information, please view the LICENSE file
|
||||||
// that was distributed with this source code.
|
// that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use uu_base32::base_common;
|
use uu_base32::base_common;
|
||||||
pub use uu_base32::uu_app;
|
pub use uu_base32::uu_app;
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
|
|
||||||
//spell-checker:ignore (args) lsbf msbf
|
//spell-checker:ignore (args) lsbf msbf
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use uu_base32::base_common::{self, Config, BASE_CMD_PARSE_ERROR};
|
use uu_base32::base_common::{self, Config, BASE_CMD_PARSE_ERROR};
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
extern crate unix_socket;
|
extern crate unix_socket;
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
// last synced with: cat (GNU coreutils) 8.13
|
// last synced with: cat (GNU coreutils) 8.13
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) COMFOLLOW Chowner RFILE RFILE's derefer dgid nonblank nonprint nonprinting
|
// spell-checker:ignore (ToDO) COMFOLLOW Chowner RFILE RFILE's derefer dgid nonblank nonprint nonprinting
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
pub use uucore::entries;
|
pub use uucore::entries;
|
||||||
use uucore::error::{FromIo, UResult, USimpleError};
|
use uucore::error::{FromIo, UResult, USimpleError};
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) COMFOLLOW Passwd RFILE RFILE's derefer dgid duid groupname
|
// spell-checker:ignore (ToDO) COMFOLLOW Passwd RFILE RFILE's derefer dgid duid groupname
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
pub use uucore::entries::{self, Group, Locate, Passwd};
|
pub use uucore::entries::{self, Group, Locate, Passwd};
|
||||||
use uucore::perms::{chown_base, options, IfFrom};
|
use uucore::perms::{chown_base, options, IfFrom};
|
||||||
|
|
|
@ -67,7 +67,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
// TODO: refactor the args and command matching
|
// TODO: refactor the args and command matching
|
||||||
// See: https://github.com/uutils/coreutils/pull/2365#discussion_r647849967
|
// See: https://github.com/uutils/coreutils/pull/2365#discussion_r647849967
|
||||||
let command: Vec<&str> = match commands.len() {
|
let command: Vec<&str> = match commands.len() {
|
||||||
1 => {
|
0 => {
|
||||||
let shell: &str = match user_shell {
|
let shell: &str = match user_shell {
|
||||||
Err(_) => default_shell,
|
Err(_) => default_shell,
|
||||||
Ok(ref s) => s.as_ref(),
|
Ok(ref s) => s.as_ref(),
|
||||||
|
@ -77,12 +77,28 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
_ => commands,
|
_ => 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);
|
set_context(newroot, &matches);
|
||||||
|
|
||||||
let pstatus = Command::new(command[0])
|
let pstatus = Command::new(chroot_command)
|
||||||
.args(&command[1..])
|
.args(chroot_args)
|
||||||
.status()
|
.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() {
|
if pstatus.success() {
|
||||||
0
|
0
|
||||||
|
|
|
@ -49,6 +49,7 @@ use std::path::{Path, PathBuf, StripPrefixError};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
use uucore::backup_control::{self, BackupMode};
|
use uucore::backup_control::{self, BackupMode};
|
||||||
|
use uucore::error::{set_exit_code, ExitCode, UError, UResult};
|
||||||
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
|
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
|
||||||
use walkdir::WalkDir;
|
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
|
/// Continue next iteration of loop if result of expression is error
|
||||||
macro_rules! or_continue(
|
macro_rules! or_continue(
|
||||||
($expr:expr) => (match $expr {
|
($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 ABOUT: &str = "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.";
|
||||||
static LONG_HELP: &str = "";
|
static LONG_HELP: &str = "";
|
||||||
static EXIT_OK: i32 = 0;
|
|
||||||
static EXIT_ERR: i32 = 1;
|
static EXIT_ERR: i32 = 1;
|
||||||
|
|
||||||
fn usage() -> String {
|
fn usage() -> String {
|
||||||
|
@ -446,7 +452,8 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.multiple(true))
|
.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 usage = usage();
|
||||||
let matches = uu_app()
|
let matches = uu_app()
|
||||||
.after_help(&*format!(
|
.after_help(&*format!(
|
||||||
|
@ -457,11 +464,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
.usage(&usage[..])
|
.usage(&usage[..])
|
||||||
.get_matches_from(args);
|
.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 {
|
if options.overwrite == OverwriteMode::NoClobber && options.backup != BackupMode::NoBackup {
|
||||||
show_usage_error!("options --backup and --no-clobber are mutually exclusive");
|
show_usage_error!("options --backup and --no-clobber are mutually exclusive");
|
||||||
return 1;
|
return Err(ExitCode(EXIT_ERR).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let paths: Vec<String> = matches
|
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())
|
.map(|v| v.map(ToString::to_string).collect())
|
||||||
.unwrap_or_default();
|
.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) {
|
if let Err(error) = copy(&sources, &target, &options) {
|
||||||
match error {
|
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
|
// Else we caught a fatal bubbled-up error, log it to stderr
|
||||||
_ => show_error!("{}", error),
|
_ => show_error!("{}", error),
|
||||||
};
|
};
|
||||||
return EXIT_ERR;
|
set_exit_code(EXIT_ERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXIT_OK
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClobberMode {
|
impl ClobberMode {
|
||||||
|
@ -1124,7 +1131,7 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu
|
||||||
let xattrs = xattr::list(source)?;
|
let xattrs = xattr::list(source)?;
|
||||||
for attr in xattrs {
|
for attr in xattrs {
|
||||||
if let Some(attr_value) = xattr::get(source, attr.clone())? {
|
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[..])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE file
|
// For the full copyright and license information, please view the LICENSE file
|
||||||
// that was distributed with this source code.
|
// that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
use uucore::error::UError;
|
use uucore::error::UError;
|
||||||
use uucore::error::UResult;
|
use uucore::error::UResult;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use uucore::display::print_verbatim;
|
use uucore::display::print_verbatim;
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
//* For the full copyright and license information, please view the LICENSE
|
//* For the full copyright and license information, please view the LICENSE
|
||||||
//* file that was distributed with this source code.
|
//* file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use uucore::error::{UResult, USimpleError};
|
use uucore::error::{UResult, USimpleError};
|
||||||
use uucore::InvalidEncodingHandling;
|
use uucore::InvalidEncodingHandling;
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::App;
|
use clap::App;
|
||||||
use uucore::error::UResult;
|
use uucore::error::UResult;
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) gethostid
|
// spell-checker:ignore (ToDO) gethostid
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App};
|
use clap::{crate_version, App};
|
||||||
use libc::c_long;
|
use libc::c_long;
|
||||||
use uucore::error::UResult;
|
use uucore::error::UResult;
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) MAKEWORD addrs hashset
|
// spell-checker:ignore (ToDO) MAKEWORD addrs hashset
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use std::collections::hash_set::HashSet;
|
use std::collections::hash_set::HashSet;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (paths) GPGHome
|
// spell-checker:ignore (paths) GPGHome
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use uucore::display::{println_verbatim, Quotable};
|
use uucore::display::{println_verbatim, Quotable};
|
||||||
use uucore::error::{FromIo, UError, UResult};
|
use uucore::error::{FromIo, UError, UResult};
|
||||||
|
|
|
@ -20,7 +20,7 @@ use quick_error::ResultExt;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::fs::{metadata, File};
|
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)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::fs::FileTypeExt;
|
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 header = header_content(options, page);
|
||||||
let trailer_content = trailer_content(options);
|
let trailer_content = trailer_content(options);
|
||||||
let out = &mut stdout();
|
|
||||||
|
|
||||||
out.lock();
|
let out = stdout();
|
||||||
|
let mut out = out.lock();
|
||||||
|
|
||||||
for x in header {
|
for x in header {
|
||||||
out.write_all(x.as_bytes())?;
|
out.write_all(x.as_bytes())?;
|
||||||
out.write_all(line_separator)?;
|
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() {
|
for (index, x) in trailer_content.iter().enumerate() {
|
||||||
out.write_all(x.as_bytes())?;
|
out.write_all(x.as_bytes())?;
|
||||||
|
@ -1060,7 +1061,7 @@ fn print_page(lines: &[FileLine], options: &OutputOptions, page: usize) -> Resul
|
||||||
fn write_columns(
|
fn write_columns(
|
||||||
lines: &[FileLine],
|
lines: &[FileLine],
|
||||||
options: &OutputOptions,
|
options: &OutputOptions,
|
||||||
out: &mut Stdout,
|
out: &mut impl Write,
|
||||||
) -> Result<usize, IOError> {
|
) -> Result<usize, IOError> {
|
||||||
let line_separator = options.content_line_separator.as_bytes();
|
let line_separator = options.content_line_separator.as_bytes();
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
|
@ -88,30 +88,65 @@ impl FromStr for Number {
|
||||||
if s.starts_with('+') {
|
if s.starts_with('+') {
|
||||||
s = &s[1..];
|
s = &s[1..];
|
||||||
}
|
}
|
||||||
|
let is_neg = s.starts_with('-');
|
||||||
|
|
||||||
match s.parse::<BigInt>() {
|
match s.to_lowercase().find("0x") {
|
||||||
Ok(n) => {
|
Some(i) if i <= 1 => match &s.as_bytes()[i + 2] {
|
||||||
// If `s` is '-0', then `parse()` returns
|
b'-' | b'+' => Err(format!(
|
||||||
// `BigInt::zero()`, but we need to return
|
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
|
||||||
// `Number::MinusZero` instead.
|
s.quote(),
|
||||||
if n == BigInt::zero() && s.starts_with('-') {
|
uucore::execution_phrase(),
|
||||||
Ok(Number::MinusZero)
|
)),
|
||||||
} else {
|
// TODO: hexadecimal floating point parsing (see #2660)
|
||||||
Ok(Number::BigInt(n))
|
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>() {
|
||||||
Err(_) => match s.parse::<f64>() {
|
Ok(value) if value.is_nan() => Err(format!(
|
||||||
Ok(value) if value.is_nan() => Err(format!(
|
|
||||||
"invalid 'not-a-number' argument: {}\nTry '{} --help' for more information.",
|
"invalid 'not-a-number' argument: {}\nTry '{} --help' for more information.",
|
||||||
s.quote(),
|
s.quote(),
|
||||||
uucore::execution_phrase(),
|
uucore::execution_phrase(),
|
||||||
)),
|
)),
|
||||||
Ok(value) => Ok(Number::F64(value)),
|
Ok(value) => Ok(Number::F64(value)),
|
||||||
Err(_) => Err(format!(
|
Err(_) => Err(format!(
|
||||||
"invalid floating point argument: {}\nTry '{} --help' for more information.",
|
"invalid floating point argument: {}\nTry '{} --help' for more information.",
|
||||||
s.quote(),
|
s.quote(),
|
||||||
uucore::execution_phrase(),
|
uucore::execution_phrase(),
|
||||||
)),
|
)),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::App;
|
use clap::App;
|
||||||
use uucore::error::UResult;
|
use uucore::error::UResult;
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
|
|
||||||
/* last synced with: unlink (GNU coreutils) 8.21 */
|
/* last synced with: unlink (GNU coreutils) 8.21 */
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use std::fs::remove_file;
|
use std::fs::remove_file;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
use chrono::{Local, TimeZone, Utc};
|
use chrono::{Local, TimeZone, Utc};
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
// import crate time from utmpx
|
// import crate time from utmpx
|
||||||
pub use uucore::libc;
|
pub use uucore::libc;
|
||||||
use uucore::libc::time_t;
|
use uucore::libc::time_t;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
|
use uucore::error::UResult;
|
||||||
use uucore::utmpx::{self, Utmpx};
|
use uucore::utmpx::{self, Utmpx};
|
||||||
|
|
||||||
static ABOUT: &str = "Print the user names of users currently logged in to the current host";
|
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 usage = usage();
|
||||||
let after_help = get_long_usage();
|
let after_help = get_long_usage();
|
||||||
|
|
||||||
|
@ -59,7 +61,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
println!("{}", users.join(" "));
|
println!("{}", users.join(" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
0
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uu_app() -> App<'static, 'static> {
|
pub fn uu_app() -> App<'static, 'static> {
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::App;
|
use clap::App;
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,6 @@ use std::io::{self, Write};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use uucore::error::{UResult, USimpleError};
|
use uucore::error::{UResult, USimpleError};
|
||||||
|
|
|
@ -101,7 +101,7 @@ pub fn gen_uumain(_args: TokenStream, stream: TokenStream) -> TokenStream {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let s = format!("{}", e);
|
let s = format!("{}", e);
|
||||||
if s != "" {
|
if s != "" {
|
||||||
show_error!("{}", s);
|
uucore::show_error!("{}", s);
|
||||||
}
|
}
|
||||||
if e.usage() {
|
if e.usage() {
|
||||||
eprintln!("Try '{} --help' for more information.", uucore::execution_phrase());
|
eprintln!("Try '{} --help' for more information.", uucore::execution_phrase());
|
||||||
|
|
|
@ -15,6 +15,7 @@ fn test_missing_operand() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_enter_chroot_fails() {
|
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!();
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
|
||||||
at.mkdir("jail");
|
at.mkdir("jail");
|
||||||
|
@ -89,3 +90,26 @@ fn test_preference_of_userspec() {
|
||||||
println!("result.stdout = {}", result.stdout_str());
|
println!("result.stdout = {}", result.stdout_str());
|
||||||
println!("result.stderr = {}", result.stderr_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");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
|
@ -28,9 +28,7 @@ macro_rules! fixture_path {
|
||||||
macro_rules! assert_fixture_exists {
|
macro_rules! assert_fixture_exists {
|
||||||
($fname:expr) => {{
|
($fname:expr) => {{
|
||||||
let fpath = fixture_path!($fname);
|
let fpath = fixture_path!($fname);
|
||||||
if !fpath.exists() {
|
assert!(fpath.exists(), "Fixture missing: {:?}", fpath);
|
||||||
panic!("Fixture missing: {:?}", fpath);
|
|
||||||
}
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +36,7 @@ macro_rules! assert_fixture_exists {
|
||||||
macro_rules! assert_fixture_not_exists {
|
macro_rules! assert_fixture_not_exists {
|
||||||
($fname:expr) => {{
|
($fname:expr) => {{
|
||||||
let fpath = PathBuf::from(format!("./fixtures/dd/{}", $fname));
|
let fpath = PathBuf::from(format!("./fixtures/dd/{}", $fname));
|
||||||
if fpath.exists() {
|
assert!(!fpath.exists(), "Fixture present: {:?}", fpath);
|
||||||
panic!("Fixture present: {:?}", fpath);
|
|
||||||
}
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// spell-checker:ignore abcdefghijklmnopqrstuvwxyz
|
||||||
// * This file is part of the uutils coreutils package.
|
// * This file is part of the uutils coreutils package.
|
||||||
// *
|
// *
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * 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();
|
let mut f = File::create(&file).unwrap();
|
||||||
// spell-checker:disable-next-line
|
// spell-checker:disable-next-line
|
||||||
if f.write_all(b"abcdefghijklmnopqrstuvwxyz\n").is_err() {
|
assert!(
|
||||||
panic!("Test setup failed - could not write file");
|
!f.write_all(b"abcdefghijklmnopqrstuvwxyz\n").is_err(),
|
||||||
}
|
"Test setup failed - could not write file"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
@ -75,9 +77,10 @@ fn test_2files() {
|
||||||
// spell-checker:disable-next-line
|
// spell-checker:disable-next-line
|
||||||
for &(path, data) in &[(&file1, "abcdefghijklmnop"), (&file2, "qrstuvwxyz\n")] {
|
for &(path, data) in &[(&file1, "abcdefghijklmnop"), (&file2, "qrstuvwxyz\n")] {
|
||||||
let mut f = File::create(&path).unwrap();
|
let mut f = File::create(&path).unwrap();
|
||||||
if f.write_all(data.as_bytes()).is_err() {
|
assert!(
|
||||||
panic!("Test setup failed - could not write file");
|
!f.write_all(data.as_bytes()).is_err(),
|
||||||
}
|
"Test setup failed - could not write file"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
@ -126,9 +129,10 @@ fn test_from_mixed() {
|
||||||
let (data1, data2, data3) = ("abcdefg", "hijklmnop", "qrstuvwxyz\n");
|
let (data1, data2, data3) = ("abcdefg", "hijklmnop", "qrstuvwxyz\n");
|
||||||
for &(path, data) in &[(&file1, data1), (&file3, data3)] {
|
for &(path, data) in &[(&file1, data1), (&file3, data3)] {
|
||||||
let mut f = File::create(&path).unwrap();
|
let mut f = File::create(&path).unwrap();
|
||||||
if f.write_all(data.as_bytes()).is_err() {
|
assert!(
|
||||||
panic!("Test setup failed - could not write file");
|
!f.write_all(data.as_bytes()).is_err(),
|
||||||
}
|
"Test setup failed - could not write file"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
|
|
@ -1,6 +1,69 @@
|
||||||
use crate::common::util::*;
|
use crate::common::util::*;
|
||||||
use std::io::Read;
|
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]
|
#[test]
|
||||||
fn test_rejects_nan() {
|
fn test_rejects_nan() {
|
||||||
let ts = TestScenario::new(util_name!());
|
let ts = TestScenario::new(util_name!());
|
||||||
|
|
|
@ -163,25 +163,23 @@ impl CmdResult {
|
||||||
|
|
||||||
/// asserts that the command resulted in a success (zero) status code
|
/// asserts that the command resulted in a success (zero) status code
|
||||||
pub fn success(&self) -> &CmdResult {
|
pub fn success(&self) -> &CmdResult {
|
||||||
if !self.success {
|
assert!(
|
||||||
panic!(
|
self.success,
|
||||||
"Command was expected to succeed.\nstdout = {}\n stderr = {}",
|
"Command was expected to succeed.\nstdout = {}\n stderr = {}",
|
||||||
self.stdout_str(),
|
self.stdout_str(),
|
||||||
self.stderr_str()
|
self.stderr_str()
|
||||||
);
|
);
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// asserts that the command resulted in a failure (non-zero) status code
|
/// asserts that the command resulted in a failure (non-zero) status code
|
||||||
pub fn failure(&self) -> &CmdResult {
|
pub fn failure(&self) -> &CmdResult {
|
||||||
if self.success {
|
assert!(
|
||||||
panic!(
|
!self.success,
|
||||||
"Command was expected to fail.\nstdout = {}\n stderr = {}",
|
"Command was expected to fail.\nstdout = {}\n stderr = {}",
|
||||||
self.stdout_str(),
|
self.stdout_str(),
|
||||||
self.stderr_str()
|
self.stderr_str()
|
||||||
);
|
);
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,12 +195,11 @@ impl CmdResult {
|
||||||
/// 1. you can not know exactly what stdout will be or
|
/// 1. you can not know exactly what stdout will be or
|
||||||
/// 2. you know that stdout will also be empty
|
/// 2. you know that stdout will also be empty
|
||||||
pub fn no_stderr(&self) -> &CmdResult {
|
pub fn no_stderr(&self) -> &CmdResult {
|
||||||
if !self.stderr.is_empty() {
|
assert!(
|
||||||
panic!(
|
self.stderr.is_empty(),
|
||||||
"Expected stderr to be empty, but it's:\n{}",
|
"Expected stderr to be empty, but it's:\n{}",
|
||||||
self.stderr_str()
|
self.stderr_str()
|
||||||
);
|
);
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,12 +210,11 @@ impl CmdResult {
|
||||||
/// 1. you can not know exactly what stderr will be or
|
/// 1. you can not know exactly what stderr will be or
|
||||||
/// 2. you know that stderr will also be empty
|
/// 2. you know that stderr will also be empty
|
||||||
pub fn no_stdout(&self) -> &CmdResult {
|
pub fn no_stdout(&self) -> &CmdResult {
|
||||||
if !self.stdout.is_empty() {
|
assert!(
|
||||||
panic!(
|
self.stdout.is_empty(),
|
||||||
"Expected stdout to be empty, but it's:\n{}",
|
"Expected stdout to be empty, but it's:\n{}",
|
||||||
self.stderr_str()
|
self.stderr_str()
|
||||||
);
|
);
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,9 +864,7 @@ impl UCommand {
|
||||||
/// Add a parameter to the invocation. Path arguments are treated relative
|
/// Add a parameter to the invocation. Path arguments are treated relative
|
||||||
/// to the test environment directory.
|
/// to the test environment directory.
|
||||||
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut UCommand {
|
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut UCommand {
|
||||||
if self.has_run {
|
assert!(!self.has_run, ALREADY_RUN);
|
||||||
panic!("{}", ALREADY_RUN);
|
|
||||||
}
|
|
||||||
self.comm_string.push(' ');
|
self.comm_string.push(' ');
|
||||||
self.comm_string
|
self.comm_string
|
||||||
.push_str(arg.as_ref().to_str().unwrap_or_default());
|
.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
|
/// Add multiple parameters to the invocation. Path arguments are treated relative
|
||||||
/// to the test environment directory.
|
/// to the test environment directory.
|
||||||
pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut UCommand {
|
pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut UCommand {
|
||||||
if self.has_run {
|
assert!(!self.has_run, MULTIPLE_STDIN_MEANINGLESS);
|
||||||
panic!("{}", MULTIPLE_STDIN_MEANINGLESS);
|
|
||||||
}
|
|
||||||
let strings = args
|
let strings = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.as_ref().to_os_string())
|
.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
|
/// 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 {
|
pub fn pipe_in<T: Into<Vec<u8>>>(&mut self, input: T) -> &mut UCommand {
|
||||||
if self.bytes_into_stdin.is_some() {
|
assert!(!self.bytes_into_stdin.is_some(), MULTIPLE_STDIN_MEANINGLESS);
|
||||||
panic!("{}", MULTIPLE_STDIN_MEANINGLESS);
|
|
||||||
}
|
|
||||||
self.bytes_into_stdin = Some(input.into());
|
self.bytes_into_stdin = Some(input.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -918,9 +908,7 @@ impl UCommand {
|
||||||
/// This is typically useful to test non-standard workflows
|
/// This is typically useful to test non-standard workflows
|
||||||
/// like feeding something to a command that does not read it
|
/// like feeding something to a command that does not read it
|
||||||
pub fn ignore_stdin_write_error(&mut self) -> &mut UCommand {
|
pub fn ignore_stdin_write_error(&mut self) -> &mut UCommand {
|
||||||
if self.bytes_into_stdin.is_none() {
|
assert!(!self.bytes_into_stdin.is_none(), NO_STDIN_MEANINGLESS);
|
||||||
panic!("{}", NO_STDIN_MEANINGLESS);
|
|
||||||
}
|
|
||||||
self.ignore_stdin_write_error = true;
|
self.ignore_stdin_write_error = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -930,9 +918,7 @@ impl UCommand {
|
||||||
K: AsRef<OsStr>,
|
K: AsRef<OsStr>,
|
||||||
V: AsRef<OsStr>,
|
V: AsRef<OsStr>,
|
||||||
{
|
{
|
||||||
if self.has_run {
|
assert!(!self.has_run, ALREADY_RUN);
|
||||||
panic!("{}", ALREADY_RUN);
|
|
||||||
}
|
|
||||||
self.raw.env(key, val);
|
self.raw.env(key, val);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -951,9 +937,7 @@ impl UCommand {
|
||||||
/// Spawns the command, feeds the stdin if any, and returns the
|
/// Spawns the command, feeds the stdin if any, and returns the
|
||||||
/// child process immediately.
|
/// child process immediately.
|
||||||
pub fn run_no_wait(&mut self) -> Child {
|
pub fn run_no_wait(&mut self) -> Child {
|
||||||
if self.has_run {
|
assert!(!self.has_run, ALREADY_RUN);
|
||||||
panic!("{}", ALREADY_RUN);
|
|
||||||
}
|
|
||||||
self.has_run = true;
|
self.has_run = true;
|
||||||
log_info("run", &self.comm_string);
|
log_info("run", &self.comm_string);
|
||||||
let mut child = self
|
let mut child = self
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
set -e
|
set -e
|
||||||
if test ! -d ../gnu; then
|
if test ! -d ../gnu; then
|
||||||
echo "Could not find ../gnu"
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
if test ! -d ../gnulib; then
|
if test ! -d ../gnulib; then
|
||||||
echo "Could not find ../gnulib"
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue