Skip to content

Commit c694cdd

Browse files
committed
Merge branch 'jc/format-patch-noclobber' into pu
"git format-patch" used to overwrite an existing patch/cover-letter file. A new "--no-clobber" option stops it. Undecided but inclined to discard. * jc/format-patch-noclobber: format-patch: --no-clobber refrains from overwriting output files
2 parents 9d1b638 + 0799f93 commit c694cdd

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

Documentation/git-format-patch.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ SYNOPSIS
2626
[--no-notes | --notes[=<ref>]]
2727
[--interdiff=<previous>]
2828
[--range-diff=<previous> [--creation-factor=<percent>]]
29-
[--progress]
29+
[--progress] [--[no-]clobber]
3030
[<common diff options>]
3131
[ <since> | <revision range> ]
3232

@@ -94,6 +94,12 @@ include::diff-options.txt[]
9494
Use <dir> to store the resulting files, instead of the
9595
current working directory.
9696

97+
--clobber::
98+
--no-clobber::
99+
(experimental)
100+
Allow overwriting existing files, which is the default. To
101+
make the command refrain from overwriting, use `--no-clobber`.
102+
97103
-n::
98104
--numbered::
99105
Name output in '[PATCH n/m]' format, even with a single patch.

builtin/log.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -887,8 +887,16 @@ static int git_format_config(const char *var, const char *value, void *cb)
887887
static const char *output_directory = NULL;
888888
static int outdir_offset;
889889

890+
static FILE *fopen_excl(const char *filename)
891+
{
892+
int fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0666);
893+
if (fd < 0)
894+
return NULL;
895+
return fdopen(fd, "w");
896+
}
897+
890898
static int open_next_file(struct commit *commit, const char *subject,
891-
struct rev_info *rev, int quiet)
899+
struct rev_info *rev, int quiet, int clobber)
892900
{
893901
struct strbuf filename = STRBUF_INIT;
894902
int suffix_len = strlen(rev->patch_suffix) + 1;
@@ -913,7 +921,12 @@ static int open_next_file(struct commit *commit, const char *subject,
913921
if (!quiet)
914922
printf("%s\n", filename.buf + outdir_offset);
915923

916-
if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) {
924+
if (clobber)
925+
rev->diffopt.file = fopen(filename.buf, "w");
926+
else
927+
rev->diffopt.file = fopen_excl(filename.buf);
928+
929+
if (!rev->diffopt.file) {
917930
error_errno(_("cannot open patch file %s"), filename.buf);
918931
strbuf_release(&filename);
919932
return -1;
@@ -1050,7 +1063,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
10501063
struct commit *origin,
10511064
int nr, struct commit **list,
10521065
const char *branch_name,
1053-
int quiet)
1066+
int quiet,
1067+
int clobber)
10541068
{
10551069
const char *committer;
10561070
const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
@@ -1069,7 +1083,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
10691083
committer = git_committer_info(0);
10701084

10711085
if (!use_stdout &&
1072-
open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
1086+
open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter",
1087+
rev, quiet, clobber))
10731088
die(_("failed to create cover-letter file"));
10741089

10751090
log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte, 0);
@@ -1533,6 +1548,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
15331548
struct strbuf buf = STRBUF_INIT;
15341549
int use_patch_format = 0;
15351550
int quiet = 0;
1551+
int clobber = 1;
15361552
int reroll_count = -1;
15371553
char *branch_name = NULL;
15381554
char *base_commit = NULL;
@@ -1619,6 +1635,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
16191635
OPT__QUIET(&quiet, N_("don't print the patch filenames")),
16201636
OPT_BOOL(0, "progress", &show_progress,
16211637
N_("show progress while generating patches")),
1638+
OPT_BOOL(0, "clobber", &clobber,
1639+
N_("allow overwriting output files")),
16221640
OPT_CALLBACK(0, "interdiff", &idiff_prev, N_("rev"),
16231641
N_("show changes against <rev> in cover letter or single patch"),
16241642
parse_opt_object_name),
@@ -1909,7 +1927,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
19091927
if (thread)
19101928
gen_message_id(&rev, "cover");
19111929
make_cover_letter(&rev, use_stdout,
1912-
origin, nr, list, branch_name, quiet);
1930+
origin, nr, list, branch_name,
1931+
quiet, clobber);
19131932
print_bases(&bases, rev.diffopt.file);
19141933
print_signature(rev.diffopt.file);
19151934
total++;
@@ -1964,7 +1983,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
19641983
}
19651984

19661985
if (!use_stdout &&
1967-
open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
1986+
open_next_file(rev.numbered_files ? NULL : commit, NULL,
1987+
&rev, quiet, clobber))
19681988
die(_("failed to create output files"));
19691989
shown = log_tree_commit(&rev, commit);
19701990
free_commit_buffer(the_repository->parsed_objects,

t/t4014-format-patch.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,22 @@ test_expect_success 'failure to write cover-letter aborts gracefully' '
614614
test_must_fail git format-patch --no-renames --cover-letter -1
615615
'
616616

617+
test_expect_success 'refrain from overwriting a patch with --no-clobber' '
618+
rm -f 000[01]-*.patch &&
619+
git format-patch --no-clobber --no-renames --cover-letter -1 >filelist &&
620+
# empty the files output by the command ...
621+
for f in $(cat filelist)
622+
do
623+
: >"$f" || return 1
624+
done &&
625+
test_must_fail git format-patch --no-clobber --cover-letter --no-renames -1 &&
626+
# ... and make sure they stay empty
627+
for f in $(cat filelist)
628+
do
629+
! test -s "$f" || return 1
630+
done
631+
'
632+
617633
test_expect_success 'cover-letter inherits diff options' '
618634
git mv file foo &&
619635
git commit -m foo &&

0 commit comments

Comments
 (0)