Skip to content

Commit 8cd2f16

Browse files
committed
Merge branch 'jc/format-patch-error-check' into pu
* jc/format-patch-error-check: format-patch: --no-clobber refrains from overwriting output files format-patch: notice failure to open cover letter for writing builtin/log: downcase the beginning of error messages
2 parents 868a8f9 + 0799f93 commit 8cd2f16

File tree

3 files changed

+76
-28
lines changed

3 files changed

+76
-28
lines changed

Documentation/git-format-patch.txt

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

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

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

builtin/log.c

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c
517517
if (get_oid_with_context(the_repository, obj_name,
518518
GET_OID_RECORD_PATH,
519519
&oidc, &obj_context))
520-
die(_("Not a valid object name %s"), obj_name);
520+
die(_("not a valid object name %s"), obj_name);
521521
if (!obj_context.path ||
522522
!textconv_object(the_repository, obj_context.path,
523523
obj_context.mode, &oidc, 1, &buf, &size)) {
@@ -541,7 +541,7 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
541541
int offset = 0;
542542

543543
if (!buf)
544-
return error(_("Could not read object %s"), oid_to_hex(oid));
544+
return error(_("could not read object %s"), oid_to_hex(oid));
545545

546546
assert(type == OBJ_TAG);
547547
while (offset < size && buf[offset] != '\n') {
@@ -635,7 +635,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
635635
break;
636636
o = parse_object(the_repository, &t->tagged->oid);
637637
if (!o)
638-
ret = error(_("Could not read object %s"),
638+
ret = error(_("could not read object %s"),
639639
oid_to_hex(&t->tagged->oid));
640640
objects[i].item = o;
641641
i--;
@@ -660,7 +660,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
660660
ret = cmd_log_walk(&rev);
661661
break;
662662
default:
663-
ret = error(_("Unknown type: %d"), o->type);
663+
ret = error(_("unknown type: %d"), o->type);
664664
}
665665
}
666666
free(objects);
@@ -871,8 +871,16 @@ static int git_format_config(const char *var, const char *value, void *cb)
871871
static const char *output_directory = NULL;
872872
static int outdir_offset;
873873

874+
static FILE *fopen_excl(const char *filename)
875+
{
876+
int fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0666);
877+
if (fd < 0)
878+
return NULL;
879+
return fdopen(fd, "w");
880+
}
881+
874882
static int open_next_file(struct commit *commit, const char *subject,
875-
struct rev_info *rev, int quiet)
883+
struct rev_info *rev, int quiet, int clobber)
876884
{
877885
struct strbuf filename = STRBUF_INIT;
878886
int suffix_len = strlen(rev->patch_suffix) + 1;
@@ -897,8 +905,13 @@ static int open_next_file(struct commit *commit, const char *subject,
897905
if (!quiet)
898906
printf("%s\n", filename.buf + outdir_offset);
899907

900-
if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) {
901-
error_errno(_("Cannot open patch file %s"), filename.buf);
908+
if (clobber)
909+
rev->diffopt.file = fopen(filename.buf, "w");
910+
else
911+
rev->diffopt.file = fopen_excl(filename.buf);
912+
913+
if (!rev->diffopt.file) {
914+
error_errno(_("cannot open patch file %s"), filename.buf);
902915
strbuf_release(&filename);
903916
return -1;
904917
}
@@ -915,7 +928,7 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
915928
unsigned flags1, flags2;
916929

917930
if (rev->pending.nr != 2)
918-
die(_("Need exactly one range."));
931+
die(_("need exactly one range"));
919932

920933
o1 = rev->pending.objects[0].item;
921934
o2 = rev->pending.objects[1].item;
@@ -925,7 +938,7 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
925938
c2 = lookup_commit_reference(the_repository, &o2->oid);
926939

927940
if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
928-
die(_("Not a range."));
941+
die(_("not a range"));
929942

930943
init_patch_ids(the_repository, ids);
931944

@@ -1034,7 +1047,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
10341047
struct commit *origin,
10351048
int nr, struct commit **list,
10361049
const char *branch_name,
1037-
int quiet)
1050+
int quiet,
1051+
int clobber)
10381052
{
10391053
const char *committer;
10401054
const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
@@ -1048,13 +1062,14 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
10481062
struct commit *head = list[0];
10491063

10501064
if (!cmit_fmt_is_mail(rev->commit_format))
1051-
die(_("Cover letter needs email format"));
1065+
die(_("cover letter needs email format"));
10521066

10531067
committer = git_committer_info(0);
10541068

10551069
if (!use_stdout &&
1056-
open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
1057-
return;
1070+
open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter",
1071+
rev, quiet, clobber))
1072+
die(_("failed to create cover-letter file"));
10581073

10591074
log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte, 0);
10601075

@@ -1218,7 +1233,7 @@ static int output_directory_callback(const struct option *opt, const char *arg,
12181233
const char **dir = (const char **)opt->value;
12191234
BUG_ON_OPT_NEG(unset);
12201235
if (*dir)
1221-
die(_("Two output directories?"));
1236+
die(_("two output directories?"));
12221237
*dir = arg;
12231238
return 0;
12241239
}
@@ -1329,7 +1344,7 @@ static struct commit *get_base_commit(const char *base_commit,
13291344
if (base_commit && strcmp(base_commit, "auto")) {
13301345
base = lookup_commit_reference_by_name(base_commit);
13311346
if (!base)
1332-
die(_("Unknown commit %s"), base_commit);
1347+
die(_("unknown commit %s"), base_commit);
13331348
} else if ((base_commit && !strcmp(base_commit, "auto")) || base_auto) {
13341349
struct branch *curr_branch = branch_get(NULL);
13351350
const char *upstream = branch_get_upstream(curr_branch, NULL);
@@ -1339,18 +1354,18 @@ static struct commit *get_base_commit(const char *base_commit,
13391354
struct object_id oid;
13401355

13411356
if (get_oid(upstream, &oid))
1342-
die(_("Failed to resolve '%s' as a valid ref."), upstream);
1357+
die(_("failed to resolve '%s' as a valid ref"), upstream);
13431358
commit = lookup_commit_or_die(&oid, "upstream base");
13441359
base_list = get_merge_bases_many(commit, total, list);
13451360
/* There should be one and only one merge base. */
13461361
if (!base_list || base_list->next)
1347-
die(_("Could not find exact merge base."));
1362+
die(_("could not find exact merge base"));
13481363
base = base_list->item;
13491364
free_commit_list(base_list);
13501365
} else {
1351-
die(_("Failed to get upstream, if you want to record base commit automatically,\n"
1366+
die(_("failed to get upstream, if you want to record base commit automatically,\n"
13521367
"please use git branch --set-upstream-to to track a remote branch.\n"
1353-
"Or you could specify base commit by --base=<base-commit-id> manually."));
1368+
"Or you could specify base commit by --base=<base-commit-id> manually"));
13541369
}
13551370
}
13561371

@@ -1368,7 +1383,7 @@ static struct commit *get_base_commit(const char *base_commit,
13681383
struct commit_list *merge_base;
13691384
merge_base = get_merge_bases(rev[2 * i], rev[2 * i + 1]);
13701385
if (!merge_base || merge_base->next)
1371-
die(_("Failed to find exact merge base"));
1386+
die(_("failed to find exact merge base"));
13721387

13731388
rev[i] = merge_base->item;
13741389
}
@@ -1517,6 +1532,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
15171532
struct strbuf buf = STRBUF_INIT;
15181533
int use_patch_format = 0;
15191534
int quiet = 0;
1535+
int clobber = 1;
15201536
int reroll_count = -1;
15211537
char *branch_name = NULL;
15221538
char *base_commit = NULL;
@@ -1603,6 +1619,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
16031619
OPT__QUIET(&quiet, N_("don't print the patch filenames")),
16041620
OPT_BOOL(0, "progress", &show_progress,
16051621
N_("show progress while generating patches")),
1622+
OPT_BOOL(0, "clobber", &clobber,
1623+
N_("allow overwriting output files")),
16061624
OPT_CALLBACK(0, "interdiff", &idiff_prev, N_("rev"),
16071625
N_("show changes against <rev> in cover letter or single patch"),
16081626
parse_opt_object_name),
@@ -1747,7 +1765,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
17471765
if (use_stdout)
17481766
die(_("standard output, or directory, which one?"));
17491767
if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
1750-
die_errno(_("Could not create directory '%s'"),
1768+
die_errno(_("could not create directory '%s'"),
17511769
output_directory);
17521770
}
17531771

@@ -1893,7 +1911,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
18931911
if (thread)
18941912
gen_message_id(&rev, "cover");
18951913
make_cover_letter(&rev, use_stdout,
1896-
origin, nr, list, branch_name, quiet);
1914+
origin, nr, list, branch_name,
1915+
quiet, clobber);
18971916
print_bases(&bases, rev.diffopt.file);
18981917
print_signature(rev.diffopt.file);
18991918
total++;
@@ -1948,8 +1967,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
19481967
}
19491968

19501969
if (!use_stdout &&
1951-
open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
1952-
die(_("Failed to create output files"));
1970+
open_next_file(rev.numbered_files ? NULL : commit, NULL,
1971+
&rev, quiet, clobber))
1972+
die(_("failed to create output files"));
19531973
shown = log_tree_commit(&rev, commit);
19541974
free_commit_buffer(the_repository->parsed_objects,
19551975
commit);
@@ -2073,9 +2093,9 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
20732093
revs.max_parents = 1;
20742094

20752095
if (add_pending_commit(head, &revs, 0))
2076-
die(_("Unknown commit %s"), head);
2096+
die(_("unknown commit %s"), head);
20772097
if (add_pending_commit(upstream, &revs, UNINTERESTING))
2078-
die(_("Unknown commit %s"), upstream);
2098+
die(_("unknown commit %s"), upstream);
20792099

20802100
/* Don't say anything if head and upstream are the same. */
20812101
if (revs.pending.nr == 2) {
@@ -2087,7 +2107,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
20872107
get_patch_ids(&revs, &ids);
20882108

20892109
if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
2090-
die(_("Unknown commit %s"), limit);
2110+
die(_("unknown commit %s"), limit);
20912111

20922112
/* reverse the list of commits */
20932113
if (prepare_revision_walk(&revs))

t/t4014-format-patch.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,28 @@ test_expect_success 'excessive subject' '
589589
ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
590590
'
591591

592+
test_expect_success 'failure to write cover-letter aborts gracefully' '
593+
test_when_finished "rmdir 0000-cover-letter.patch" &&
594+
mkdir 0000-cover-letter.patch &&
595+
test_must_fail git format-patch --no-renames --cover-letter -1
596+
'
597+
598+
test_expect_success 'refrain from overwriting a patch with --no-clobber' '
599+
rm -f 000[01]-*.patch &&
600+
git format-patch --no-clobber --no-renames --cover-letter -1 >filelist &&
601+
# empty the files output by the command ...
602+
for f in $(cat filelist)
603+
do
604+
: >"$f" || return 1
605+
done &&
606+
test_must_fail git format-patch --no-clobber --cover-letter --no-renames -1 &&
607+
# ... and make sure they stay empty
608+
for f in $(cat filelist)
609+
do
610+
! test -s "$f" || return 1
611+
done
612+
'
613+
592614
test_expect_success 'cover-letter inherits diff options' '
593615
git mv file foo &&
594616
git commit -m foo &&

0 commit comments

Comments
 (0)