@@ -21,11 +21,13 @@ enum deny_action {
21
21
static int deny_deletes = 0 ;
22
22
static int deny_non_fast_forwards = 0 ;
23
23
static enum deny_action deny_current_branch = DENY_UNCONFIGURED ;
24
+ static enum deny_action deny_delete_current = DENY_UNCONFIGURED ;
24
25
static int receive_fsck_objects ;
25
26
static int receive_unpack_limit = -1 ;
26
27
static int transfer_unpack_limit = -1 ;
27
28
static int unpack_limit = 100 ;
28
29
static int report_status ;
30
+ static const char * head_name ;
29
31
30
32
static char capabilities [] = " report-status delete-refs " ;
31
33
static int capabilities_sent ;
@@ -77,6 +79,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
77
79
return 0 ;
78
80
}
79
81
82
+ if (strcmp (var , "receive.denydeletecurrent" ) == 0 ) {
83
+ deny_delete_current = parse_deny_action (var , value );
84
+ return 0 ;
85
+ }
86
+
80
87
return git_default_config (var , value , cb );
81
88
}
82
89
@@ -203,16 +210,12 @@ static int run_update_hook(struct command *cmd)
203
210
204
211
static int is_ref_checked_out (const char * ref )
205
212
{
206
- unsigned char sha1 [20 ];
207
- const char * head ;
208
-
209
213
if (is_bare_repository ())
210
214
return 0 ;
211
215
212
- head = resolve_ref ("HEAD" , sha1 , 0 , NULL );
213
- if (!head )
216
+ if (!head_name )
214
217
return 0 ;
215
- return !strcmp (head , ref );
218
+ return !strcmp (head_name , ref );
216
219
}
217
220
218
221
static char * warn_unconfigured_deny_msg [] = {
@@ -244,6 +247,32 @@ static void warn_unconfigured_deny(void)
244
247
warning (warn_unconfigured_deny_msg [i ]);
245
248
}
246
249
250
+ static char * warn_unconfigured_deny_delete_current_msg [] = {
251
+ "Deleting the current branch can cause confusion by making the next" ,
252
+ "'git clone' not check out any file." ,
253
+ "" ,
254
+ "You can set 'receive.denyDeleteCurrent' configuration variable to" ,
255
+ "'refuse' in the remote repository to disallow deleting the current" ,
256
+ "branch." ,
257
+ "" ,
258
+ "You can set it to 'ignore' to allow such a delete without a warning." ,
259
+ "" ,
260
+ "To make this warning message less loud, you can set it to 'warn'." ,
261
+ "" ,
262
+ "Note that the default will change in a future version of git" ,
263
+ "to refuse deleting the current branch unless you have the" ,
264
+ "configuration variable set to either 'ignore' or 'warn'."
265
+ };
266
+
267
+ static void warn_unconfigured_deny_delete_current (void )
268
+ {
269
+ int i ;
270
+ for (i = 0 ;
271
+ i < ARRAY_SIZE (warn_unconfigured_deny_delete_current_msg );
272
+ i ++ )
273
+ warning (warn_unconfigured_deny_delete_current_msg [i ]);
274
+ }
275
+
247
276
static const char * update (struct command * cmd )
248
277
{
249
278
const char * name = cmd -> ref_name ;
@@ -278,12 +307,30 @@ static const char *update(struct command *cmd)
278
307
"but I can't find it!" , sha1_to_hex (new_sha1 ));
279
308
return "bad pack" ;
280
309
}
281
- if (deny_deletes && is_null_sha1 (new_sha1 ) &&
282
- !is_null_sha1 (old_sha1 ) &&
283
- !prefixcmp (name , "refs/heads/" )) {
284
- error ("denying ref deletion for %s" , name );
285
- return "deletion prohibited" ;
310
+
311
+ if (!is_null_sha1 (old_sha1 ) && is_null_sha1 (new_sha1 )) {
312
+ if (deny_deletes && !prefixcmp (name , "refs/heads/" )) {
313
+ error ("denying ref deletion for %s" , name );
314
+ return "deletion prohibited" ;
315
+ }
316
+
317
+ if (!strcmp (name , head_name )) {
318
+ switch (deny_delete_current ) {
319
+ case DENY_IGNORE :
320
+ break ;
321
+ case DENY_WARN :
322
+ case DENY_UNCONFIGURED :
323
+ if (deny_delete_current == DENY_UNCONFIGURED )
324
+ warn_unconfigured_deny_delete_current ();
325
+ warning ("deleting the current branch" );
326
+ break ;
327
+ case DENY_REFUSE :
328
+ error ("refusing to delete the current branch: %s" , name );
329
+ return "deletion of the current branch prohibited" ;
330
+ }
331
+ }
286
332
}
333
+
287
334
if (deny_non_fast_forwards && !is_null_sha1 (new_sha1 ) &&
288
335
!is_null_sha1 (old_sha1 ) &&
289
336
!prefixcmp (name , "refs/heads/" )) {
@@ -377,6 +424,7 @@ static void run_update_post_hook(struct command *cmd)
377
424
static void execute_commands (const char * unpacker_error )
378
425
{
379
426
struct command * cmd = commands ;
427
+ unsigned char sha1 [20 ];
380
428
381
429
if (unpacker_error ) {
382
430
while (cmd ) {
@@ -394,6 +442,8 @@ static void execute_commands(const char *unpacker_error)
394
442
return ;
395
443
}
396
444
445
+ head_name = resolve_ref ("HEAD" , sha1 , 0 , NULL );
446
+
397
447
while (cmd ) {
398
448
cmd -> error_string = update (cmd );
399
449
cmd = cmd -> next ;
0 commit comments