Skip to content

Commit 8aaf7d6

Browse files
spearceJunio C Hamano
authored andcommitted
Refactor handling of error_string in receive-pack
I discovered we did not send an ng line in the report-status feedback if the ref was not updated because the repository has the config option receive.denyNonFastForwards enabled. I think the reason this happened is that it is simply too easy to forget to set error_string when returning back a failure from update() We now return an ng line for a non-fastforward update, which in turn will cause send-pack to exit with a non-zero exit status. Hence the modified test. This refactoring changes update to return a const char* describing the error, which execute_commands always loads into error_string. The result is what I think is cleaner code, and allows us to initialize the error_string member to NULL when we read_head_info. I want error_string to be NULL in all commands before we call execute_commands, so that we can reuse the run_hook function to execute a new pre-receive hook. Signed-off-by: Shawn O. Pearce <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent c8dd277 commit 8aaf7d6

File tree

2 files changed

+36
-32
lines changed

2 files changed

+36
-32
lines changed

receive-pack.c

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -127,24 +127,22 @@ static int run_hook(const char *hook_name,
127127
}
128128
}
129129

130-
static int update(struct command *cmd)
130+
static const char *update(struct command *cmd)
131131
{
132132
const char *name = cmd->ref_name;
133133
unsigned char *old_sha1 = cmd->old_sha1;
134134
unsigned char *new_sha1 = cmd->new_sha1;
135135
struct ref_lock *lock;
136136

137-
cmd->error_string = NULL;
138137
if (!prefixcmp(name, "refs/") && check_ref_format(name + 5)) {
139-
cmd->error_string = "funny refname";
140-
return error("refusing to create funny ref '%s' locally",
141-
name);
138+
error("refusing to create funny ref '%s' locally", name);
139+
return "funny refname";
142140
}
143141

144142
if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
145-
cmd->error_string = "bad pack";
146-
return error("unpack should have generated %s, "
147-
"but I can't find it!", sha1_to_hex(new_sha1));
143+
error("unpack should have generated %s, "
144+
"but I can't find it!", sha1_to_hex(new_sha1));
145+
return "bad pack";
148146
}
149147
if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
150148
!is_null_sha1(old_sha1) &&
@@ -159,37 +157,39 @@ static int update(struct command *cmd)
159157
if (!hashcmp(old_sha1, ent->item->object.sha1))
160158
break;
161159
free_commit_list(bases);
162-
if (!ent)
163-
return error("denying non-fast forward;"
164-
" you should pull first");
160+
if (!ent) {
161+
error("denying non-fast forward %s"
162+
" (you should pull first)", name);
163+
return "non-fast forward";
164+
}
165165
}
166166
if (run_hook(update_hook, cmd, 1)) {
167-
cmd->error_string = "hook declined";
168-
return error("hook declined to update %s", name);
167+
error("hook declined to update %s", name);
168+
return "hook declined";
169169
}
170170

171171
if (is_null_sha1(new_sha1)) {
172172
if (delete_ref(name, old_sha1)) {
173-
cmd->error_string = "failed to delete";
174-
return error("failed to delete %s", name);
173+
error("failed to delete %s", name);
174+
return "failed to delete";
175175
}
176176
fprintf(stderr, "%s: %s -> deleted\n", name,
177177
sha1_to_hex(old_sha1));
178+
return NULL; /* good */
178179
}
179180
else {
180181
lock = lock_any_ref_for_update(name, old_sha1);
181182
if (!lock) {
182-
cmd->error_string = "failed to lock";
183-
return error("failed to lock %s", name);
183+
error("failed to lock %s", name);
184+
return "failed to lock";
184185
}
185186
if (write_ref_sha1(lock, new_sha1, "push")) {
186-
cmd->error_string = "failed to write";
187-
return -1; /* error() already called */
187+
return "failed to write"; /* error() already called */
188188
}
189189
fprintf(stderr, "%s: %s -> %s\n", name,
190190
sha1_to_hex(old_sha1), sha1_to_hex(new_sha1));
191+
return NULL; /* good */
191192
}
192-
return 0;
193193
}
194194

195195
static char update_post_hook[] = "hooks/post-update";
@@ -224,15 +224,20 @@ static void run_update_post_hook(struct command *cmd)
224224
| RUN_COMMAND_STDOUT_TO_STDERR);
225225
}
226226

227-
/*
228-
* This gets called after(if) we've successfully
229-
* unpacked the data payload.
230-
*/
231-
static void execute_commands(void)
227+
static void execute_commands(const char *unpacker_error)
232228
{
233229
struct command *cmd = commands;
230+
231+
if (unpacker_error) {
232+
while (cmd) {
233+
cmd->error_string = "n/a (unpacker error)";
234+
cmd = cmd->next;
235+
}
236+
return;
237+
}
238+
234239
while (cmd) {
235-
update(cmd);
240+
cmd->error_string = update(cmd);
236241
cmd = cmd->next;
237242
}
238243
}
@@ -270,7 +275,7 @@ static void read_head_info(void)
270275
hashcpy(cmd->old_sha1, old_sha1);
271276
hashcpy(cmd->new_sha1, new_sha1);
272277
memcpy(cmd->ref_name, line + 82, len - 81);
273-
cmd->error_string = "n/a (unpacker error)";
278+
cmd->error_string = NULL;
274279
cmd->next = NULL;
275280
*p = cmd;
276281
p = &cmd->next;
@@ -473,8 +478,7 @@ int main(int argc, char **argv)
473478

474479
if (!delete_only(commands))
475480
unpack_status = unpack();
476-
if (!unpack_status)
477-
execute_commands();
481+
execute_commands(unpack_status);
478482
if (pack_lockfile)
479483
unlink(pack_lockfile);
480484
if (report_status)

t/t5400-send-pack.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ test_expect_success \
108108
cd victim &&
109109
git-config receive.denyNonFastforwards true &&
110110
cd .. &&
111-
git-update-ref refs/heads/master master^ &&
112-
git-send-pack --force ./victim/.git/ master &&
113-
! diff -u .git/refs/heads/master victim/.git/refs/heads/master
111+
git-update-ref refs/heads/master master^ || return 1
112+
git-send-pack --force ./victim/.git/ master && return 1
113+
! diff .git/refs/heads/master victim/.git/refs/heads/master
114114
'
115115

116116
test_done

0 commit comments

Comments
 (0)