From: René Scharfe <hidden> Date: 2016-07-07 20:02:34
write_file() either returns 0 or dies, so there is no point in checking
its return value. The callers of the wrappers write_state_text(),
write_state_count() and write_state_bool() consequently already ignore
their return values. Stop pretenting we care and make them void.
Signed-off-by: Rene Scharfe <redacted>
---
builtin/am.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
From: Jeff King <hidden> Date: 2016-07-07 20:32:09
On Thu, Jul 07, 2016 at 10:02:14PM +0200, René Scharfe wrote:
write_file() either returns 0 or dies, so there is no point in checking
its return value. The callers of the wrappers write_state_text(),
write_state_count() and write_state_bool() consequently already ignore
their return values. Stop pretenting we care and make them void.
Makes sense. Originally it took "fatal" as a parameter, but it was split
into two functions in 12d6ce1 (write_file(): drop "fatal" parameter,
2015-08-24). The return value on the non-gentle version could have been
dropped at that point.
Arguably we could get rid of the gentle form entirely, as below. The
diffstat is certainly pleasing, but maybe we would eventually want it
for another caller. I dunno. I won't be offended if we drop this as
churn.
-- >8 --
Subject: [PATCH] write_file: drop "gently" form
We have two forms of write_file(): one that dies, and one
that returns an error. However, the latter has only a single
caller, which immediately dies anyway (after producing a
message that is not really any more informative than
write_file's generic die(), and arguably worse because it
does not give the actual filename).
Let's convert that site to use the non-gentle form. At that
point the gentle form has no callers, and we can simplify
the implementation of write_file.
Signed-off-by: Jeff King <redacted>
---
As a fun aside, this patch was generated using "--patience",
which gives a much closer to result to what I actually
changed than Myers diff (not meaningful to the patch, but
I'm just always on the lookout for cases where the
algorithms produce meaningfully different results).
builtin/branch.c | 5 +----
cache.h | 3 +--
wrapper.c | 56 ++++++++++++--------------------------------------------
3 files changed, 14 insertions(+), 50 deletions(-)
@@ -618,10 +618,7 @@ static int edit_branch_description(const char *branch_name)" %s\n""Lines starting with '%c' will be stripped.\n",branch_name,comment_line_char);-if(write_file_gently(git_path(edit_description),"%s",buf.buf)){-strbuf_release(&buf);-returnerror_errno(_("could not write branch description template"));-}+write_file(git_path(edit_description),"%s",buf.buf);strbuf_reset(&buf);if(launch_editor(git_path(edit_description),&buf,NULL)){strbuf_release(&buf);
@@ -640,56 +640,24 @@ int xsnprintf(char *dst, size_t max, const char *fmt, ...)returnlen;}-staticintwrite_file_v(constchar*path,intfatal,-constchar*fmt,va_listparams)+voidwrite_file(constchar*path,constchar*fmt,...){+va_listparams;structstrbufsb=STRBUF_INIT;intfd=open(path,O_RDWR|O_CREAT|O_TRUNC,0666);-if(fd<0){-if(fatal)-die_errno(_("could not open %s for writing"),path);-return-1;-}+if(fd<0)+die_errno(_("could not open %s for writing"),path);++va_start(params,fmt);strbuf_vaddf(&sb,fmt,params);+va_end(params);+strbuf_complete_line(&sb);-if(write_in_full(fd,sb.buf,sb.len)!=sb.len){-interr=errno;-close(fd);-strbuf_release(&sb);-errno=err;-if(fatal)-die_errno(_("could not write to %s"),path);-return-1;-}+if(write_in_full(fd,sb.buf,sb.len)!=sb.len)+die_errno(_("could not write to %s"),path);strbuf_release(&sb);-if(close(fd)){-if(fatal)-die_errno(_("could not close %s"),path);-return-1;-}-return0;-}--intwrite_file(constchar*path,constchar*fmt,...)-{-intstatus;-va_listparams;--va_start(params,fmt);-status=write_file_v(path,1,fmt,params);-va_end(params);-returnstatus;-}--intwrite_file_gently(constchar*path,constchar*fmt,...)-{-intstatus;-va_listparams;--va_start(params,fmt);-status=write_file_v(path,0,fmt,params);-va_end(params);-returnstatus;+if(close(fd))+die_errno(_("could not close %s"),path);}voidsleep_millisec(intmillisec)
From: Johannes Schindelin <hidden> Date: 2016-07-08 06:34:15
Hi René,
On Thu, 7 Jul 2016, René Scharfe wrote:
write_file() either returns 0 or dies, so there is no point in checking
its return value.
The question is whether it makes sense for write_file() to die(). It is a
library function and not every caller can be happy with that function to
exit the program when some file could not be written, without a chance to
tell the user what to do about the situation.
If write_file() was defined in builtin/am.c, as a static function, I would
grudgingly acquiesce, but it is not.
IMO it would be better to fix write_file() to *not* die() but return
error() instead.
Ciao,
Dscho
From: Johannes Schindelin <hidden> Date: 2016-07-08 06:37:49
Hi Peff,
On Thu, 7 Jul 2016, Jeff King wrote:
We have two forms of write_file(): one that dies, and one
that returns an error. However, the latter has only a single
caller, which immediately dies anyway (after producing a
message that is not really any more informative than
write_file's generic die(), and arguably worse because it
does not give the actual filename).
This is more an illustration of unnecessarily duplicated code, isn't it?
There are *tons* of instances in Git's code where writing to a file is
implemented separately (and differently).
It would make tons of sense to consolidate all of these instances,
methinks. The diffstat should look *very* pleasing.
Ciao,
Dscho
From: Jeff King <hidden> Date: 2016-07-08 06:57:00
On Fri, Jul 08, 2016 at 08:37:35AM +0200, Johannes Schindelin wrote:
quoted
We have two forms of write_file(): one that dies, and one
that returns an error. However, the latter has only a single
caller, which immediately dies anyway (after producing a
message that is not really any more informative than
write_file's generic die(), and arguably worse because it
does not give the actual filename).
This is more an illustration of unnecessarily duplicated code, isn't it?
There are *tons* of instances in Git's code where writing to a file is
implemented separately (and differently).
It would make tons of sense to consolidate all of these instances,
methinks. The diffstat should look *very* pleasing.
I grepped for O_WRONLY, and there are fewer instances than I would have
thought. Most of the obvious write_file() candidates are in the merge
code, which is probably why you saw so many of them. :)
I started at converting a few sites, but it's actually a little awkward
because they all have strbufs (with a ptr/len combo that _could_ contain
NULs, but probably doesn't), and write_file() wants to take a format
string.
I think we can clean that up, though. I'll hopefully have a series in a
few minutes.
-Peff
From: Jeff King <hidden> Date: 2016-07-08 09:04:13
On Fri, Jul 08, 2016 at 02:56:50AM -0400, Jeff King wrote:
quoted
This is more an illustration of unnecessarily duplicated code, isn't it?
There are *tons* of instances in Git's code where writing to a file is
implemented separately (and differently).
It would make tons of sense to consolidate all of these instances,
methinks. The diffstat should look *very* pleasing.
I grepped for O_WRONLY, and there are fewer instances than I would have
thought. Most of the obvious write_file() candidates are in the merge
code, which is probably why you saw so many of them. :)
I started at converting a few sites, but it's actually a little awkward
because they all have strbufs (with a ptr/len combo that _could_ contain
NULs, but probably doesn't), and write_file() wants to take a format
string.
I think we can clean that up, though. I'll hopefully have a series in a
few minutes.
Here it is. There actually weren't that many spots to clean up, as quite
a few of them have a "twist" where they want to do something clever,
like open the file and feed the descriptor to a sub-function, or open
with funny things like O_EXCL.
But still, the diffstat is pleasing:
builtin/am.c | 25 +++++++----------
builtin/branch.c | 5 +---
builtin/config.c | 2 +-
builtin/merge.c | 45 ++++--------------------------
cache.h | 17 ++++++++++--
wrapper.c | 52 ++++++++---------------------------
6 files changed, 44 insertions(+), 102 deletions(-)
and that even includes adding some function documentation.
The most interesting thing is that I also found a real bug, albeit a
fairly minor one. I floated that up to the front of the series.
[1/8]: config: fix bogus fd check when setting up default config
[2/8]: am: ignore return value of write_file()
[3/8]: branch: use non-gentle write_file for branch description
[4/8]: write_file: drop "gently" form
[5/8]: write_file: use xopen
[6/8]: write_file: add pointer+len variant
[7/8]: write_file: add format attribute
[8/8]: use write_file_buf where applicable
-Peff
From: Jeff King <hidden> Date: 2016-07-08 09:07:04
Since 9830534 (config --global --edit: create a template
file if needed, 2014-07-25), an edit of the global config
file will try to open() it with O_EXCL, and wants to handle
three cases:
1. We succeeded; the user has no config file, and we
should fill in the default template.
2. We got EEXIST; they have a file already, proceed as usual.
3. We got another error; we should complain.
However, the check for case 1 does "if (fd)", which will
generally _always_ be true (except for the oddball case that
somehow our stdin got closed and opening really did give us
a new descriptor 0).
So in the EEXIST case, we tried to write the default config
anyway! Fortunately, this turns out to be a noop, since we
just end up writing to and closing "-1", which does nothing.
But in case 3, we would fail to notice any other errors, and
just silently continue (given that we don't actually notice
write errors for the template either, it's probably not that
big a deal; we're about to spawn the editor, so it would
notice any problems. But the code is clearly _trying_ to hit
cover this case and failing).
We can fix it easily by using "fd >= 0" for case 1.
Signed-off-by: Jeff King <redacted>
---
I was looking at this to see whether it could be converted to
write_file(). However, the O_EXCL and the error-handling make things
too tricky.
builtin/config.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Jeff King <hidden> Date: 2016-07-08 09:08:13
From: René Scharfe <redacted>
write_file() either returns 0 or dies, so there is no point in checking
its return value. The callers of the wrappers write_state_text(),
write_state_count() and write_state_bool() consequently already ignore
their return values. Stop pretending we care and make them void.
Signed-off-by: Rene Scharfe <redacted>
Signed-off-by: Jeff King <redacted>
---
I included this just to make it clear that I am building on top. You
can also just apply on top of the existing branch (though note that I
fixed a typo s/pretenting/pretending/ in the commit message).
builtin/am.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
From: Jeff King <hidden> Date: 2016-07-08 09:09:01
We use write_file_gently() to do this job currently.
However, if we see an error, we simply complain via
error_errno() and then end up exiting with an error code.
By switching to the non-gentle form, the function will die
for us, with a better error. It is more specific about which
syscall caused the error, and that mentions the
actual filename we're trying to write.
Our exit code for the error case does switch from "1" to
"128", but that's OK; it wasn't a meaningful documented code
(and in fact it was odd that it was a different exit code
than most other error conditions).
Signed-off-by: Jeff King <redacted>
---
builtin/branch.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
@@ -618,10 +618,7 @@ static int edit_branch_description(const char *branch_name)" %s\n""Lines starting with '%c' will be stripped.\n",branch_name,comment_line_char);-if(write_file_gently(git_path(edit_description),"%s",buf.buf)){-strbuf_release(&buf);-returnerror_errno(_("could not write branch description template"));-}+write_file(git_path(edit_description),"%s",buf.buf);strbuf_reset(&buf);if(launch_editor(git_path(edit_description),&buf,NULL)){strbuf_release(&buf);
From: Jeff King <hidden> Date: 2016-07-08 09:09:42
There are no callers left of write_file_gently(). Let's drop
it, as it doesn't seem likely for new callers to be added
(since its inception, the only callers who wanted the gentle
form generally just died immediately themselves, and have
since been converted).
While we're there, let's also drop the "int" return from
write_file, as it is never meaningful (in the non-gentle
form, we always either die or return 0).
Signed-off-by: Jeff King <redacted>
---
cache.h | 3 +--
wrapper.c | 54 +++++++++++-------------------------------------------
2 files changed, 12 insertions(+), 45 deletions(-)
@@ -640,56 +640,24 @@ int xsnprintf(char *dst, size_t max, const char *fmt, ...)returnlen;}-staticintwrite_file_v(constchar*path,intfatal,-constchar*fmt,va_listparams)+voidwrite_file(constchar*path,constchar*fmt,...){+va_listparams;structstrbufsb=STRBUF_INIT;intfd=open(path,O_RDWR|O_CREAT|O_TRUNC,0666);-if(fd<0){-if(fatal)-die_errno(_("could not open %s for writing"),path);-return-1;-}-strbuf_vaddf(&sb,fmt,params);-strbuf_complete_line(&sb);-if(write_in_full(fd,sb.buf,sb.len)!=sb.len){-interr=errno;-close(fd);-strbuf_release(&sb);-errno=err;-if(fatal)-die_errno(_("could not write to %s"),path);-return-1;-}-strbuf_release(&sb);-if(close(fd)){-if(fatal)-die_errno(_("could not close %s"),path);-return-1;-}-return0;-}--intwrite_file(constchar*path,constchar*fmt,...)-{-intstatus;-va_listparams;+if(fd<0)+die_errno(_("could not open %s for writing"),path);va_start(params,fmt);-status=write_file_v(path,1,fmt,params);+strbuf_vaddf(&sb,fmt,params);va_end(params);-returnstatus;-}--intwrite_file_gently(constchar*path,constchar*fmt,...)-{-intstatus;-va_listparams;-va_start(params,fmt);-status=write_file_v(path,0,fmt,params);-va_end(params);-returnstatus;+strbuf_complete_line(&sb);+if(write_in_full(fd,sb.buf,sb.len)!=sb.len)+die_errno(_("could not write to %s"),path);+strbuf_release(&sb);+if(close(fd))+die_errno(_("could not close %s"),path);}voidsleep_millisec(intmillisec)
From: Jeff King <hidden> Date: 2016-07-08 09:10:17
This simplifies the code a tiny bit, and provides consistent
error messages with other users of xopen().
While we're here, let's also switch to using O_WRONLY. We
know we're only going to open/write/close the file, so
there's no point in asking for O_RDWR.
Signed-off-by: Jeff King <redacted>
---
wrapper.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
From: Jeff King <hidden> Date: 2016-07-08 09:12:35
There are many callsites which could use write_file, but for
which it is a little awkward because they have a strbuf or
other pointer/len combo. Specifically:
1. write_file() takes a format string, so we have to use
"%s" or "%.*s", which are ugly.
2. Using any form of "%s" does not handle embedded NULs in
the output. That probably doesn't matter for our
call-sites, but it's nicer not to have to worry.
3. It's less efficient; we format into another strbuf
just to do the write. That's probably not measurably
slow for our uses, but it's simply inelegant.
We can fix this by providing a helper to write out the
formatted buffer, and just calling it from write_file().
Note that we don't do the usual "complete with a newline"
that write_file does. If the caller has their own buffer,
there's a reasonable chance they're doing something more
complicated than a single line, and they can call
strbuf_complete_line() themselves.
We could go even further and add strbuf_write_file(), but it
doesn't save much:
- write_file_buf(path, sb.buf, sb.len);
+ strbuf_write_file(&sb, path);
It would also be somewhat asymmetric with strbuf_read_file,
which actually returns errors rather than dying (and the
error handling is most of the benefit of write_file() in the
first place).
Signed-off-by: Jeff King <redacted>
---
cache.h | 6 ++++++
wrapper.c | 16 +++++++++++-----
2 files changed, 17 insertions(+), 5 deletions(-)
@@ -640,22 +640,28 @@ int xsnprintf(char *dst, size_t max, const char *fmt, ...)returnlen;}+voidwrite_file_buf(constchar*path,constchar*buf,size_tlen)+{+intfd=xopen(path,O_WRONLY|O_CREAT|O_TRUNC,0666);+if(write_in_full(fd,buf,len)!=len)+die_errno(_("could not write to %s"),path);+if(close(fd))+die_errno(_("could not close %s"),path);+}+voidwrite_file(constchar*path,constchar*fmt,...){va_listparams;structstrbufsb=STRBUF_INIT;-intfd=xopen(path,O_WRONLY|O_CREAT|O_TRUNC,0666);va_start(params,fmt);strbuf_vaddf(&sb,fmt,params);va_end(params);strbuf_complete_line(&sb);-if(write_in_full(fd,sb.buf,sb.len)!=sb.len)-die_errno(_("could not write to %s"),path);++write_file_buf(path,sb.buf,sb.len);strbuf_release(&sb);-if(close(fd))-die_errno(_("could not close %s"),path);}voidsleep_millisec(intmillisec)
From: Jeff King <hidden> Date: 2016-07-08 09:13:01
This gives us compile-time checking of our format strings,
which is a good thing.
I had also hoped it would help with confusing write_file()
and write_file_buf(), since the former's "..." can make it
match the signature of the latter. But given that the buffer
for write_file_buf() is generally not a string literal, the
compiler won't complain unless -Wformat-nonliteral is on,
and that creates a ton of false positives elsewhere in the
code base.
While we're there, let's also give the function a docstring,
which it never had.
Signed-off-by: Jeff King <redacted>
---
cache.h | 8 ++++++++
1 file changed, 8 insertions(+)
From: Jeff King <hidden> Date: 2016-07-08 09:13:06
There are several places where we open a file, write some
content from a strbuf, and close it. These can be simplified
with write_file_buf(). As a bonus, many of these did not
catch write problems at close() time.
Signed-off-by: Jeff King <redacted>
---
builtin/am.c | 7 +------
builtin/merge.c | 45 +++++----------------------------------------
2 files changed, 6 insertions(+), 46 deletions(-)
@@ -403,13 +403,8 @@ static int read_commit_msg(struct am_state *state)*/staticvoidwrite_commit_msg(conststructam_state*state){-intfd;constchar*filename=am_path(state,"final-commit");--fd=xopen(filename,O_WRONLY|O_CREAT,0666);-if(write_in_full(fd,state->msg,state->msg_len)<0)-die_errno(_("could not write to %s"),filename);-close(fd);+write_file_buf(filename,state->msg,state->msg_len);}/**
@@ -756,18 +747,6 @@ static void add_strategies(const char *string, unsigned attr)}-staticvoidwrite_merge_msg(structstrbuf*msg)-{-constchar*filename=git_path_merge_msg();-intfd=open(filename,O_WRONLY|O_CREAT,0666);-if(fd<0)-die_errno(_("Could not open '%s' for writing"),-filename);-if(write_in_full(fd,msg->buf,msg->len)!=msg->len)-die_errno(_("Could not write to '%s'"),filename);-close(fd);-}-staticvoidread_merge_msg(structstrbuf*msg){constchar*filename=git_path_merge_msg();
@@ -964,8 +943,6 @@ static int setup_with_upstream(const char ***argv)staticvoidwrite_merge_state(structcommit_list*remoteheads){-constchar*filename;-intfd;structcommit_list*j;structstrbufbuf=STRBUF_INIT;
@@ -979,26 +956,14 @@ static void write_merge_state(struct commit_list *remoteheads)}strbuf_addf(&buf,"%s\n",oid_to_hex(oid));}-filename=git_path_merge_head();-fd=open(filename,O_WRONLY|O_CREAT,0666);-if(fd<0)-die_errno(_("Could not open '%s' for writing"),filename);-if(write_in_full(fd,buf.buf,buf.len)!=buf.len)-die_errno(_("Could not write to '%s'"),filename);-close(fd);+write_file_buf(git_path_merge_head(),buf.buf,buf.len);strbuf_addch(&merge_msg,'\n');-write_merge_msg(&merge_msg);+write_file_buf(git_path_merge_msg(),merge_msg.buf,merge_msg.len);-filename=git_path_merge_mode();-fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);-if(fd<0)-die_errno(_("Could not open '%s' for writing"),filename);strbuf_reset(&buf);if(fast_forward==FF_NO)strbuf_addf(&buf,"no-ff");-if(write_in_full(fd,buf.buf,buf.len)!=buf.len)-die_errno(_("Could not write to '%s'"),filename);-close(fd);+write_file_buf(git_path_merge_mode(),buf.buf,buf.len);}staticintdefault_edit_option(void)
From: Jeff King <hidden> Date: 2016-07-08 09:17:00
If we already have a strbuf, then using write_file_buf is a
little nicer to read (no wondering whether "%s" will eat
your NULs), and it's more efficient (no extra formatting
step).
We don't care about the newline magic of write_file(), as we
have our own multi-line content.
Signed-off-by: Jeff King <redacted>
---
Almost forgot this one. I had originally converted to write_file_buf
directly, but later reshuffled the patches to make the refactoring more
clear.
builtin/branch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
@@ -618,7 +618,7 @@ static int edit_branch_description(const char *branch_name)" %s\n""Lines starting with '%c' will be stripped.\n",branch_name,comment_line_char);-write_file(git_path(edit_description),"%s",buf.buf);+write_file_buf(git_path(edit_description),buf.buf,buf.len);strbuf_reset(&buf);if(launch_editor(git_path(edit_description),&buf,NULL)){strbuf_release(&buf);
From: Jeff King <hidden> Date: 2016-07-08 09:25:18
On Fri, Jul 08, 2016 at 05:12:41AM -0400, Jeff King wrote:
I had also hoped it would help with confusing write_file()
and write_file_buf(), since the former's "..." can make it
match the signature of the latter. But given that the buffer
for write_file_buf() is generally not a string literal, the
compiler won't complain unless -Wformat-nonliteral is on,
and that creates a ton of false positives elsewhere in the
code base.
I poked around at the results of compiling with -Wformat-nonliteral, but
gave up at trying to make it work. There are a number of clever uses of
formats that would be hard to do otherwise. There are also several cases
where a format string is used multiple times and we want to avoid
repeating it. But using #define doesn't work, because we want to be able
to translate it.
I did find a little bit of low-hanging fruit, though.
[1/2]: walker: let walker_say take arbitrary formats
[2/2]: avoid using sha1_to_hex output as printf format
These are totally independent of the main series, so they can be a
separate topic, go on top, or just get dropped entirely if it's not
worth the trouble.
-Peff
From: Jeff King <hidden> Date: 2016-07-08 09:25:29
We take a printf-style format and a single "char *"
parameter, and the format must therefore have at most one
"%s" in it. Besides being error-prone (and tickling
-Wformat-nonliteral), this is unnecessarily restrictive. We
can just provide the usual varargs interface.
Signed-off-by: Jeff King <redacted>
---
walker.c | 10 +++++++---
walker.h | 3 ++-
2 files changed, 9 insertions(+), 4 deletions(-)
@@ -19,7 +19,8 @@ struct walker {};/* Report what we got under get_verbosely */-voidwalker_say(structwalker*walker,constchar*,constchar*);+__attribute__((format(printf,2,3)))+voidwalker_say(structwalker*walker,constchar*fmt,...);/* Load pull targets from stdin */intwalker_targets_stdin(char***target,constchar***write_ref);
From: Jeff King <hidden> Date: 2016-07-08 09:25:33
We know that it should not contain any percent-signs, but
it's a good habit not to feed non-literals to printf
formatters.
Signed-off-by: Jeff King <redacted>
---
builtin/worktree.c | 2 +-
commit.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
Urgh, this second hunk is clearly bogus. This is a -Wformat-nonliteral
problem, but not because of oid_to_hex(), but rather because of
"format". :-/
Here's a corrected patch. But as this has demonstrated the dangers of
churn, and as it doesn't really get us meaningfully closer to being able
to use -Wformat-nonliteral, perhaps the best course of action is to just
drop it (I do think the "walker_say" patch has more inherent value as a
cleanup, though).
-- >8 --
Subject: [PATCH] avoid using sha1_to_hex output as printf format
We know that it should not contain any percent-signs, but
it's a good habit not to feed non-literals to printf
formatters.
Signed-off-by: Jeff King <redacted>
---
builtin/worktree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: René Scharfe <hidden> Date: 2016-07-08 18:44:46
Hi Dscho,
Am 08.07.2016 um 08:33 schrieb Johannes Schindelin:
On Thu, 7 Jul 2016, René Scharfe wrote:
quoted
write_file() either returns 0 or dies, so there is no point in checking
its return value.
The question is whether it makes sense for write_file() to die(). It is a
library function and not every caller can be happy with that function to
exit the program when some file could not be written, without a chance to
tell the user what to do about the situation.
If write_file() was defined in builtin/am.c, as a static function, I would
grudgingly acquiesce, but it is not.
IMO it would be better to fix write_file() to *not* die() but return
error() instead.
there is write_file_gently() for that purpose, but it's used only by a
single caller that exits on failure after all, and in fact Peff's series
drops it.
So I think write_file() is fine, and it's rather a question of whether
am should use write_file_gently() instead. I don't see why, but perhaps
that's because it's Friday..
René
From: René Scharfe <hidden> Date: 2016-07-08 18:44:55
Am 08.07.2016 um 11:04 schrieb Jeff King:
Here it is. There actually weren't that many spots to clean up, as quite
a few of them have a "twist" where they want to do something clever,
like open the file and feed the descriptor to a sub-function, or open
with funny things like O_EXCL.
But still, the diffstat is pleasing:
builtin/am.c | 25 +++++++----------
builtin/branch.c | 5 +---
builtin/config.c | 2 +-
builtin/merge.c | 45 ++++--------------------------
cache.h | 17 ++++++++++--
wrapper.c | 52 ++++++++---------------------------
6 files changed, 44 insertions(+), 102 deletions(-)
and that even includes adding some function documentation.
Haha, feels like Candy Crush. :)
(Sent a single small patch, lots of places get patched as if by magic.)
Thanks,
René
From: Jeff King <hidden> Date: 2016-07-08 21:51:21
On Fri, Jul 08, 2016 at 08:44:28PM +0200, René Scharfe wrote:
quoted
The question is whether it makes sense for write_file() to die(). It is a
library function and not every caller can be happy with that function to
exit the program when some file could not be written, without a chance to
tell the user what to do about the situation.
If write_file() was defined in builtin/am.c, as a static function, I would
grudgingly acquiesce, but it is not.
IMO it would be better to fix write_file() to *not* die() but return
error() instead.
there is write_file_gently() for that purpose, but it's used only by a
single caller that exits on failure after all, and in fact Peff's series
drops it.
Yeah, I always feel funny going in the opposite direction of
libification, as in this case. But having looked at the set of current
and potential-to-convert callers, I couldn't find a single one which
would want the gentle behavior. Any site which doesn't die also wanted
something else more complex (e.g., different open options).
So I think rather than loading down write_file() with options that will
make the simple callers harder to read, we are better off to keep its
implementation simple, and let people call its building blocks easily.
And I think we already have that; in my final version it really is just
xopen/write_in_full/close. So the non-simple sites can still make use of
those components.
-Peff
From: Johannes Schindelin <hidden> Date: 2016-07-10 10:54:00
Hi Peff,
On Sat, 9 Jul 2016, Johannes Schindelin wrote:
On Fri, 8 Jul 2016, Jeff King wrote:
quoted
I think we can clean that up, though. I'll hopefully have a series in a
few minutes.
You caught me at busy times... I'll review it tomorrow, promise!
And so I did. Looks good to me, I was surprised that there were no
possible callers is the non-builtin code. But I guess they all use the
lockfile mechanism now.
Ciao,
Dscho