# HG changeset patch # User Christian Brabandt # Date 1457448305 -3600 # Node ID 6f26b680c243ce53f03e4f163901e21cf9256b96 # Parent cef7be734b6edf7a401a7a40f565e1b98ce1a62f commit https://github.com/vim/vim/commit/e98d12105213975f37b8d653bd909bd787a2cda9 Author: Bram Moolenaar Date: Tue Mar 8 15:37:41 2016 +0100 patch 7.4.1514 Problem: Channel output to file not implemented yet. Solution: Implement it for Unix. diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5046,13 +5046,18 @@ mch_start_job(char **argv, job_T *job, j int fd_err[2]; /* for stderr */ channel_T *channel = NULL; int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE; + int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE; + int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE; int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT; /* default is to fail */ job->jv_status = JOB_FAILED; fd_in[0] = -1; + fd_in[1] = -1; fd_out[0] = -1; + fd_out[1] = -1; fd_err[0] = -1; + fd_err[1] = -1; /* TODO: without the channel feature connect the child to /dev/null? */ /* Open pipes for stdin, stdout, stderr. */ @@ -5069,9 +5074,33 @@ mch_start_job(char **argv, job_T *job, j } else if (pipe(fd_in) < 0) goto failed; - if (pipe(fd_out) < 0) + + if (use_file_for_out) + { + char_u *fname = options->jo_io_name[PART_OUT]; + + fd_out[1] = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd_out[1] < 0) + { + EMSG2(_(e_notopen), fname); + goto failed; + } + } + else if (pipe(fd_out) < 0) goto failed; - if (!use_out_for_err && pipe(fd_err) < 0) + + if (use_file_for_err) + { + char_u *fname = options->jo_io_name[PART_ERR]; + + fd_err[1] = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd_err[1] < 0) + { + EMSG2(_(e_notopen), fname); + goto failed; + } + } + else if (!use_out_for_err && pipe(fd_err) < 0) goto failed; channel = add_channel(); @@ -5117,14 +5146,16 @@ mch_start_job(char **argv, job_T *job, j } else { - close(fd_err[0]); + if (!use_file_for_err) + close(fd_err[0]); close(2); ignored = dup(fd_err[1]); close(fd_err[1]); } /* set up stdout for the child */ - close(fd_out[0]); + if (!use_file_for_out) + close(fd_out[0]); close(1); ignored = dup(fd_out[1]); close(fd_out[1]); @@ -5148,13 +5179,15 @@ mch_start_job(char **argv, job_T *job, j /* child stdin, stdout and stderr */ if (!use_file_for_in) close(fd_in[0]); - close(fd_out[1]); - if (!use_out_for_err) + if (!use_file_for_out) + close(fd_out[1]); + if (!use_out_for_err && !use_file_for_err) close(fd_err[1]); channel_set_pipes(channel, use_file_for_in ? INVALID_FD : fd_in[1], - fd_out[0], - use_out_for_err ? INVALID_FD : fd_err[0]); + use_file_for_out ? INVALID_FD : fd_out[0], + use_out_for_err || use_file_for_err + ? INVALID_FD : fd_err[0]); channel_set_job(channel, job, options); # ifdef FEAT_GUI channel_gui_register(channel); @@ -5168,21 +5201,17 @@ failed: ; if (channel != NULL) channel_free(channel); if (fd_in[0] >= 0) - { close(fd_in[0]); - if (!use_file_for_in) - close(fd_in[1]); - } + if (fd_in[1] >= 0) + close(fd_in[1]); if (fd_out[0] >= 0) - { close(fd_out[0]); + if (fd_out[1] >= 0) close(fd_out[1]); - } if (fd_err[0] >= 0) - { close(fd_err[0]); + if (fd_err[1] >= 0) close(fd_err[1]); - } # endif } diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -555,6 +555,97 @@ func Test_nl_read_file() endtry endfunc +func Test_nl_write_out_file() + if !has('job') + return + endif + " TODO: make this work for MS-Windows + if !has('unix') + return + endif + call ch_log('Test_nl_write_out_file()') + let job = job_start(s:python . " test_channel_pipe.py", + \ {'out-io': 'file', 'out-name': 'Xoutput'}) + call assert_equal("run", job_status(job)) + try + let handle = job_getchannel(job) + call ch_sendraw(handle, "echo line one\n") + call ch_sendraw(handle, "echo line two\n") + call ch_sendraw(handle, "double this\n") + for i in range(50) + sleep 10m + if len(readfile('Xoutput')) > 2 + break + endif + endfor + call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput')) + finally + call job_stop(job) + call delete('Xoutput') + endtry +endfunc + +func Test_nl_write_err_file() + if !has('job') + return + endif + " TODO: make this work for MS-Windows + if !has('unix') + return + endif + call ch_log('Test_nl_write_err_file()') + let job = job_start(s:python . " test_channel_pipe.py", + \ {'err-io': 'file', 'err-name': 'Xoutput'}) + call assert_equal("run", job_status(job)) + try + let handle = job_getchannel(job) + call ch_sendraw(handle, "echoerr line one\n") + call ch_sendraw(handle, "echoerr line two\n") + call ch_sendraw(handle, "doubleerr this\n") + for i in range(50) + sleep 10m + if len(readfile('Xoutput')) > 2 + break + endif + endfor + call assert_equal(['line one', 'line two', 'this', 'AND this'], readfile('Xoutput')) + finally + call job_stop(job) + call delete('Xoutput') + endtry +endfunc + +func Test_nl_write_both_file() + if !has('job') + return + endif + " TODO: make this work for MS-Windows + if !has('unix') + return + endif + call ch_log('Test_nl_write_both_file()') + let job = job_start(s:python . " test_channel_pipe.py", + \ {'out-io': 'file', 'out-name': 'Xoutput', 'err-io': 'out'}) + call assert_equal("run", job_status(job)) + try + let handle = job_getchannel(job) + call ch_sendraw(handle, "echoerr line one\n") + call ch_sendraw(handle, "echo line two\n") + call ch_sendraw(handle, "double this\n") + call ch_sendraw(handle, "doubleerr that\n") + for i in range(50) + sleep 10m + if len(readfile('Xoutput')) > 5 + break + endif + endfor + call assert_equal(['line one', 'line two', 'this', 'AND this', 'that', 'AND that'], readfile('Xoutput')) + finally + call job_stop(job) + call delete('Xoutput') + endtry +endfunc + func Test_pipe_to_buffer() if !has('job') return diff --git a/src/testdir/test_channel_pipe.py b/src/testdir/test_channel_pipe.py --- a/src/testdir/test_channel_pipe.py +++ b/src/testdir/test_channel_pipe.py @@ -21,10 +21,13 @@ if __name__ == "__main__": if typed.startswith("echo "): print(typed[5:-1]) sys.stdout.flush() - if typed.startswith("echoerr"): + if typed.startswith("double "): + print(typed[7:-1] + "\nAND " + typed[7:-1]) + sys.stdout.flush() + if typed.startswith("echoerr "): print(typed[8:-1], file=sys.stderr) sys.stderr.flush() - if typed.startswith("double"): - print(typed[7:-1] + "\nAND " + typed[7:-1]) - sys.stdout.flush() + if typed.startswith("doubleerr "): + print(typed[10:-1] + "\nAND " + typed[10:-1], file=sys.stderr) + sys.stderr.flush() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -744,6 +744,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1514, +/**/ 1513, /**/ 1512,