From 0958395969504cdb87742853c88dc8328f661d28 Mon Sep 17 00:00:00 2001 From: Georg Date: Thu, 28 Nov 2024 22:55:03 +0100 Subject: [PATCH 1/6] Begin link --- src/link/link.v | 42 ++++++++++++++++++++++++++++++++++++++++++ src/link/link_test.v | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/link/link.v create mode 100644 src/link/link_test.v diff --git a/src/link/link.v b/src/link/link.v new file mode 100644 index 00000000..29d3612f --- /dev/null +++ b/src/link/link.v @@ -0,0 +1,42 @@ +module main + +import common +import os + +const app = common.CoreutilInfo{ + name: 'link' + description: 'Call the link function to create a link named FILE2 to an existing FILE1.' +} + +struct Settings { +mut: + files []string +} + +fn args() Settings { + mut fp := app.make_flag_parser(os.args) + mut st := Settings{} + st.files = fp.remaining_parameters() + match st.files.len { + 0 { app.quit(message: 'missing operand') } + 1 { app.quit(message: 'missing operand after ‘${st.files[0]}’', show_help_advice: true) } + 2 {} + else { app.quit(message: 'extra operand ‘${st.files[2]}’', show_help_advice: true) } + } + + return st +} + +fn link(settings Settings) !int { + mut exit_code := 0 + os.link(settings.files[0], settings.files[1]) or { + app.quit( + message: "cannot create link '${settings.files[1]}' to '${settings.files[0]}': ${err.msg()}" + ) + } + return exit_code +} + +fn main() { + exit(link(args()) or { common.err_programming_error }) +} diff --git a/src/link/link_test.v b/src/link/link_test.v new file mode 100644 index 00000000..082d6fd2 --- /dev/null +++ b/src/link/link_test.v @@ -0,0 +1,36 @@ +module main + +import common.testing +import os + +const rig = testing.prepare_rig(util: 'link') + +fn testsuite_begin() { +} + +fn testsuite_end() { +} + +fn test_help_and_version() { + rig.assert_help_and_version_options_work() +} + +fn test_compare() { + rig.assert_same_results('a') + // rig.assert_same_results('a b') + rig.assert_same_results('a b c') + rig.assert_same_results('a b c d e f') + os.mkdir('d')! + rig.assert_same_results('d e') + os.write_file('a', '12345')! + rig.assert_same_results('a b') + assert os.is_file('a') + assert os.is_file('b') + assert os.read_file('b') or { '' } == '12345' + mut f := os.open_append('b')! + f.write_string('67890')! + f.close() + assert os.read_file('a') or { '' } == '1234567890' + os.rm('b')! + os.rm('a')! +} From ff3108ca059340fac87b7295e9c03bd5b62e714c Mon Sep 17 00:00:00 2001 From: Georg Date: Thu, 28 Nov 2024 23:00:26 +0100 Subject: [PATCH 2/6] Make normalise public --- common/testing/testing.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/testing/testing.v b/common/testing/testing.v index e3516f5f..343b0790 100644 --- a/common/testing/testing.v +++ b/common/testing/testing.v @@ -186,7 +186,7 @@ pub fn same_results(cmd1 string, cmd2 string) bool { return cmd1_res.exit_code == cmd2_res.exit_code && noutput1 == noutput2 } -fn normalise(s string) string { +pub fn normalise(s string) string { return s.replace_each(['‘', "'", '’', "'"]).replace(' ', ' ').replace(' ', ' ').replace(' ', ' ').replace(', ', ' ').split_into_lines().join('\n').trim_space() } From 4ea9b9cd7fe89dbed23852488817ac7777e5430c Mon Sep 17 00:00:00 2001 From: Georg Date: Thu, 28 Nov 2024 23:00:55 +0100 Subject: [PATCH 3/6] Improve link tests --- src/link/delete.me | 0 src/link/link_test.v | 21 ++++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) delete mode 100644 src/link/delete.me diff --git a/src/link/delete.me b/src/link/delete.me deleted file mode 100644 index e69de29b..00000000 diff --git a/src/link/link_test.v b/src/link/link_test.v index 082d6fd2..54fb925d 100644 --- a/src/link/link_test.v +++ b/src/link/link_test.v @@ -22,8 +22,12 @@ fn test_compare() { rig.assert_same_results('a b c d e f') os.mkdir('d')! rig.assert_same_results('d e') + os.rmdir('d')! + + // We can't use assert_same_results here because the hard link will already + // exist when the second util is called os.write_file('a', '12345')! - rig.assert_same_results('a b') + cmd1_res := rig.call_orig('a b') assert os.is_file('a') assert os.is_file('b') assert os.read_file('b') or { '' } == '12345' @@ -33,4 +37,19 @@ fn test_compare() { assert os.read_file('a') or { '' } == '1234567890' os.rm('b')! os.rm('a')! + + os.write_file('a', '12345')! + cmd2_res := rig.call_new('a b') + assert os.is_file('a') + assert os.is_file('b') + assert os.read_file('b') or { '' } == '12345' + f = os.open_append('b')! + f.write_string('67890')! + f.close() + assert os.read_file('a') or { '' } == '1234567890' + os.rm('b')! + os.rm('a')! + + assert cmd1_res.exit_code == cmd2_res.exit_code + assert testing.normalise(cmd1_res.output) == testing.normalise(cmd2_res.output) } From 2cf1f85268ba649794dde17f1514bcc4b6c01a23 Mon Sep 17 00:00:00 2001 From: Georg Date: Thu, 28 Nov 2024 23:01:05 +0100 Subject: [PATCH 4/6] Remove outdated delete.me --- src/id/delete.me | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/id/delete.me diff --git a/src/id/delete.me b/src/id/delete.me deleted file mode 100644 index e69de29b..00000000 From d371b90dfed11a6d194082f9ebc6362c8ce32bea Mon Sep 17 00:00:00 2001 From: Georg Date: Thu, 28 Nov 2024 23:01:50 +0100 Subject: [PATCH 5/6] Update README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 295d3288..819b86df 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ count below and mark it as done in this README.md. Thanks! GNU coreutils. They are not 100% compatiable. If you encounter different behaviors, compare against the true GNU coreutils version on the Linux-based tests first. -## Completed (73/109) - 67% done! +## Completed (74/109) - 68% done! | Done | Cmd | Descripton | Windows | | :-----: | --------- | ------------------------------------------------ | ------- | @@ -94,7 +94,7 @@ compare against the true GNU coreutils version on the Linux-based tests first. | | install | Copy files and set attributes | | | | join | Join lines on a common field | ✓ | | | kill | Send a signal to processes | ✓ | -| | link | Make a hard link via the link syscall | ✓ | +| ✓ | link | Make a hard link via the link syscall | ✓ | | ✓ | ln | Make links between files | ✓ | | ✓ | logname | Print current login name | ✓ | | ✓ | ls | List directory contents | | @@ -129,7 +129,7 @@ compare against the true GNU coreutils version on the Linux-based tests first. | ✓ | sha256sum | Print or check SHA-2 256 bit digests | ✓ | | ✓ | sha384sum | Print or check SHA-2 384 bit digests | ✓ | | ✓ | sha512sum | Print or check SHA-2 512 bit digests | ✓ | -| | shred | Remove files more securely | ✓ | +| ✓ | shred | Remove files more securely | ✓ | | ✓ | shuf | Shuffling text | ✓ | | ✓ | sleep | Delay for a specified time | ✓ | | ✓ | sort | Sort text files | ✓ | From 4f6c2fe202f88e799237329d7f42fa8cfc2990a1 Mon Sep 17 00:00:00 2001 From: Georg Date: Thu, 28 Nov 2024 23:24:45 +0100 Subject: [PATCH 6/6] Update error messages and tests based on CI results --- src/link/link.v | 4 ++-- src/link/link_test.v | 26 +++++++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/link/link.v b/src/link/link.v index 29d3612f..b90efd45 100644 --- a/src/link/link.v +++ b/src/link/link.v @@ -19,9 +19,9 @@ fn args() Settings { st.files = fp.remaining_parameters() match st.files.len { 0 { app.quit(message: 'missing operand') } - 1 { app.quit(message: 'missing operand after ‘${st.files[0]}’', show_help_advice: true) } + 1 { app.quit(message: "missing operand after '${st.files[0]}'", show_help_advice: true) } 2 {} - else { app.quit(message: 'extra operand ‘${st.files[2]}’', show_help_advice: true) } + else { app.quit(message: "extra operand '${st.files[2]}'", show_help_advice: true) } } return st diff --git a/src/link/link_test.v b/src/link/link_test.v index 54fb925d..0c5bfbf6 100644 --- a/src/link/link_test.v +++ b/src/link/link_test.v @@ -16,13 +16,25 @@ fn test_help_and_version() { } fn test_compare() { - rig.assert_same_results('a') - // rig.assert_same_results('a b') - rig.assert_same_results('a b c') - rig.assert_same_results('a b c d e f') - os.mkdir('d')! - rig.assert_same_results('d e') - os.rmdir('d')! + $if windows { + // The coreutils used on Windows does not produce the exact + // same error messages + rig.assert_same_exit_code('a') + rig.assert_same_exit_code('a b') + rig.assert_same_exit_code('a b c') + rig.assert_same_exit_code('a b c d e f') + os.mkdir('d')! + rig.assert_same_exit_code('d e') + os.rmdir('d')! + } $else { + rig.assert_same_results('a') + rig.assert_same_results('a b') + rig.assert_same_results('a b c') + rig.assert_same_results('a b c d e f') + os.mkdir('d')! + rig.assert_same_results('d e') + os.rmdir('d')! + } // We can't use assert_same_results here because the hard link will already // exist when the second util is called