1
0
forked from aniani/vim

patch 7.4.1506

Problem:    Job cannot read from a file.
Solution:   Implement reading from a file for Unix.
This commit is contained in:
Bram Moolenaar
2016-03-06 23:06:25 +01:00
parent d0b6502a7a
commit b69fccf377
5 changed files with 85 additions and 15 deletions

View File

@@ -15118,6 +15118,7 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
garray_T ga; garray_T ga;
#endif #endif
jobopt_T opt; jobopt_T opt;
int part;
rettv->v_type = VAR_JOB; rettv->v_type = VAR_JOB;
job = job_alloc(); job = job_alloc();
@@ -15135,6 +15136,17 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
+ JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL) + JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL)
return; return;
/* Check that when io is "file" that there is a file name. */
for (part = PART_OUT; part <= PART_IN; ++part)
if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT)))
&& opt.jo_io[part] == JIO_FILE
&& (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT)))
|| *opt.jo_io_name[part] == NUL))
{
EMSG(_("E920: -io file requires -name to be set"));
return;
}
if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER) if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER)
{ {
buf_T *buf; buf_T *buf;

View File

@@ -5045,6 +5045,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
int fd_out[2]; /* for stdout */ int fd_out[2]; /* for stdout */
int fd_err[2]; /* for stderr */ int fd_err[2]; /* for stderr */
channel_T *channel = NULL; channel_T *channel = NULL;
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT; int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
/* default is to fail */ /* default is to fail */
@@ -5055,8 +5056,22 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
/* TODO: without the channel feature connect the child to /dev/null? */ /* TODO: without the channel feature connect the child to /dev/null? */
/* Open pipes for stdin, stdout, stderr. */ /* Open pipes for stdin, stdout, stderr. */
if (pipe(fd_in) < 0 || pipe(fd_out) < 0 if (use_file_for_in)
|| (!use_out_for_err && pipe(fd_err) < 0)) {
char_u *fname = options->jo_io_name[PART_IN];
fd_in[0] = mch_open((char *)fname, O_RDONLY, 0);
if (fd_in[0] < 0)
{
EMSG2(_(e_notopen), fname);
goto failed;
}
}
else if (pipe(fd_in) < 0)
goto failed;
if (pipe(fd_out) < 0)
goto failed;
if (!use_out_for_err && pipe(fd_err) < 0)
goto failed; goto failed;
channel = add_channel(); channel = add_channel();
@@ -5088,7 +5103,8 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
/* TODO: re-enable this when pipes connect without a channel */ /* TODO: re-enable this when pipes connect without a channel */
# ifdef FEAT_CHANNEL # ifdef FEAT_CHANNEL
/* set up stdin for the child */ /* set up stdin for the child */
close(fd_in[1]); if (!use_file_for_in)
close(fd_in[1]);
close(0); close(0);
ignored = dup(fd_in[0]); ignored = dup(fd_in[0]);
close(fd_in[0]); close(fd_in[0]);
@@ -5130,12 +5146,15 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
# ifdef FEAT_CHANNEL # ifdef FEAT_CHANNEL
/* child stdin, stdout and stderr */ /* child stdin, stdout and stderr */
close(fd_in[0]); if (!use_file_for_in)
close(fd_in[0]);
close(fd_out[1]); close(fd_out[1]);
if (!use_out_for_err) if (!use_out_for_err)
close(fd_err[1]); close(fd_err[1]);
channel_set_pipes(channel, fd_in[1], fd_out[0], channel_set_pipes(channel,
use_out_for_err ? INVALID_FD : fd_err[0]); use_file_for_in ? INVALID_FD : fd_in[1],
fd_out[0],
use_out_for_err ? INVALID_FD : fd_err[0]);
channel_set_job(channel, job, options); channel_set_job(channel, job, options);
# ifdef FEAT_GUI # ifdef FEAT_GUI
channel_gui_register(channel); channel_gui_register(channel);
@@ -5151,7 +5170,8 @@ failed: ;
if (fd_in[0] >= 0) if (fd_in[0] >= 0)
{ {
close(fd_in[0]); close(fd_in[0]);
close(fd_in[1]); if (!use_file_for_in)
close(fd_in[1]);
} }
if (fd_out[0] >= 0) if (fd_out[0] >= 0)
{ {

View File

@@ -5000,6 +5000,7 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
HANDLE jo; HANDLE jo;
# ifdef FEAT_CHANNEL # ifdef FEAT_CHANNEL
channel_T *channel; channel_T *channel;
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT; int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
HANDLE ifd[2]; HANDLE ifd[2];
HANDLE ofd[2]; HANDLE ofd[2];
@@ -5035,13 +5036,25 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE; saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL; saAttr.lpSecurityDescriptor = NULL;
if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0) if (use_file_for_in)
|| !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0) {
|| !CreatePipe(&ofd[0], &ofd[1], &saAttr, 0) char_u *fname = options->jo_io_name[PART_IN];
|| !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)
|| (!use_out_for_err // TODO
EMSG2(_(e_notopen), fname);
goto failed;
}
else if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
|| !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0))
goto failed;
if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
|| !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0))
goto failed;
if (!use_out_for_err
&& (!CreatePipe(&efd[0], &efd[1], &saAttr, 0) && (!CreatePipe(&efd[0], &efd[1], &saAttr, 0)
|| !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0)))) || !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0)))
goto failed; goto failed;
si.dwFlags |= STARTF_USESTDHANDLES; si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = ifd[0]; si.hStdInput = ifd[0];

View File

@@ -524,6 +524,31 @@ func Test_nl_err_to_out_pipe()
endtry endtry
endfunc endfunc
func Test_nl_read_file()
if !has('job')
return
endif
" TODO: make this work for MS-Windows.
if !has('unix')
return
endif
call ch_log('Test_nl_read_file()')
call writefile(['echo something', 'echoerr wrong', 'double this'], 'Xinput')
let job = job_start(s:python . " test_channel_pipe.py",
\ {'in-io': 'file', 'in-name': 'Xinput'})
call assert_equal("run", job_status(job))
try
let handle = job_getchannel(job)
call assert_equal("something", ch_readraw(handle))
call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
call assert_equal("this", ch_readraw(handle))
call assert_equal("AND this", ch_readraw(handle))
finally
call job_stop(job)
call delete('Xinput')
endtry
endfunc
func Test_pipe_to_buffer() func Test_pipe_to_buffer()
if !has('job') if !has('job')
return return
@@ -556,7 +581,6 @@ func Test_pipe_from_buffer()
if !has('job') if !has('job')
return return
endif endif
call ch_logfile('channellog', 'w')
call ch_log('Test_pipe_from_buffer()') call ch_log('Test_pipe_from_buffer()')
sp pipe-input sp pipe-input
@@ -574,7 +598,6 @@ call ch_logfile('channellog', 'w')
finally finally
call job_stop(job) call job_stop(job)
endtry endtry
call ch_logfile('')
endfunc endfunc
func Test_pipe_to_nameless_buffer() func Test_pipe_to_nameless_buffer()

View File

@@ -743,6 +743,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1506,
/**/ /**/
1505, 1505,
/**/ /**/