@@ -1036,11 +1036,13 @@ int count_refspec_match(const char *pattern,
1036
1036
}
1037
1037
}
1038
1038
if (!matched ) {
1039
- * matched_ref = matched_weak ;
1039
+ if (matched_ref )
1040
+ * matched_ref = matched_weak ;
1040
1041
return weak_match ;
1041
1042
}
1042
1043
else {
1043
- * matched_ref = matched ;
1044
+ if (matched_ref )
1045
+ * matched_ref = matched ;
1044
1046
return match ;
1045
1047
}
1046
1048
}
@@ -1060,18 +1062,25 @@ static struct ref *alloc_delete_ref(void)
1060
1062
return ref ;
1061
1063
}
1062
1064
1063
- static struct ref * try_explicit_object_name (const char * name )
1065
+ static int try_explicit_object_name (const char * name ,
1066
+ struct ref * * match )
1064
1067
{
1065
1068
unsigned char sha1 [20 ];
1066
- struct ref * ref ;
1067
1069
1068
- if (!* name )
1069
- return alloc_delete_ref ();
1070
+ if (!* name ) {
1071
+ if (match )
1072
+ * match = alloc_delete_ref ();
1073
+ return 0 ;
1074
+ }
1075
+
1070
1076
if (get_sha1 (name , sha1 ))
1071
- return NULL ;
1072
- ref = alloc_ref (name );
1073
- hashcpy (ref -> new_sha1 , sha1 );
1074
- return ref ;
1077
+ return -1 ;
1078
+
1079
+ if (match ) {
1080
+ * match = alloc_ref (name );
1081
+ hashcpy ((* match )-> new_sha1 , sha1 );
1082
+ }
1083
+ return 0 ;
1075
1084
}
1076
1085
1077
1086
static struct ref * make_linked_ref (const char * name , struct ref * * * tail )
@@ -1101,12 +1110,37 @@ static char *guess_ref(const char *name, struct ref *peer)
1101
1110
return strbuf_detach (& buf , NULL );
1102
1111
}
1103
1112
1113
+ static int match_explicit_lhs (struct ref * src ,
1114
+ struct refspec * rs ,
1115
+ struct ref * * match ,
1116
+ int * allocated_match )
1117
+ {
1118
+ switch (count_refspec_match (rs -> src , src , match )) {
1119
+ case 1 :
1120
+ if (allocated_match )
1121
+ * allocated_match = 0 ;
1122
+ return 0 ;
1123
+ case 0 :
1124
+ /* The source could be in the get_sha1() format
1125
+ * not a reference name. :refs/other is a
1126
+ * way to delete 'other' ref at the remote end.
1127
+ */
1128
+ if (try_explicit_object_name (rs -> src , match ) < 0 )
1129
+ return error ("src refspec %s does not match any." , rs -> src );
1130
+ if (allocated_match )
1131
+ * allocated_match = 1 ;
1132
+ return 0 ;
1133
+ default :
1134
+ return error ("src refspec %s matches more than one." , rs -> src );
1135
+ }
1136
+ }
1137
+
1104
1138
static int match_explicit (struct ref * src , struct ref * dst ,
1105
1139
struct ref * * * dst_tail ,
1106
1140
struct refspec * rs )
1107
1141
{
1108
1142
struct ref * matched_src , * matched_dst ;
1109
- int copy_src ;
1143
+ int allocated_src ;
1110
1144
1111
1145
const char * dst_value = rs -> dst ;
1112
1146
char * dst_guess ;
@@ -1115,23 +1149,8 @@ static int match_explicit(struct ref *src, struct ref *dst,
1115
1149
return 0 ;
1116
1150
1117
1151
matched_src = matched_dst = NULL ;
1118
- switch (count_refspec_match (rs -> src , src , & matched_src )) {
1119
- case 1 :
1120
- copy_src = 1 ;
1121
- break ;
1122
- case 0 :
1123
- /* The source could be in the get_sha1() format
1124
- * not a reference name. :refs/other is a
1125
- * way to delete 'other' ref at the remote end.
1126
- */
1127
- matched_src = try_explicit_object_name (rs -> src );
1128
- if (!matched_src )
1129
- return error ("src refspec %s does not match any." , rs -> src );
1130
- copy_src = 0 ;
1131
- break ;
1132
- default :
1133
- return error ("src refspec %s matches more than one." , rs -> src );
1134
- }
1152
+ if (match_explicit_lhs (src , rs , & matched_src , & allocated_src ) < 0 )
1153
+ return -1 ;
1135
1154
1136
1155
if (!dst_value ) {
1137
1156
unsigned char sha1 [20 ];
@@ -1176,7 +1195,9 @@ static int match_explicit(struct ref *src, struct ref *dst,
1176
1195
return error ("dst ref %s receives from more than one src." ,
1177
1196
matched_dst -> name );
1178
1197
else {
1179
- matched_dst -> peer_ref = copy_src ? copy_ref (matched_src ) : matched_src ;
1198
+ matched_dst -> peer_ref = allocated_src ?
1199
+ matched_src :
1200
+ copy_ref (matched_src );
1180
1201
matched_dst -> force = rs -> force ;
1181
1202
}
1182
1203
return 0 ;
@@ -1357,6 +1378,31 @@ static void prepare_ref_index(struct string_list *ref_index, struct ref *ref)
1357
1378
sort_string_list (ref_index );
1358
1379
}
1359
1380
1381
+ /*
1382
+ * Given only the set of local refs, sanity-check the set of push
1383
+ * refspecs. We can't catch all errors that match_push_refs would,
1384
+ * but we can catch some errors early before even talking to the
1385
+ * remote side.
1386
+ */
1387
+ int check_push_refs (struct ref * src , int nr_refspec , const char * * refspec_names )
1388
+ {
1389
+ struct refspec * refspec = parse_push_refspec (nr_refspec , refspec_names );
1390
+ int ret = 0 ;
1391
+ int i ;
1392
+
1393
+ for (i = 0 ; i < nr_refspec ; i ++ ) {
1394
+ struct refspec * rs = refspec + i ;
1395
+
1396
+ if (rs -> pattern || rs -> matching )
1397
+ continue ;
1398
+
1399
+ ret |= match_explicit_lhs (src , rs , NULL , NULL );
1400
+ }
1401
+
1402
+ free_refspec (nr_refspec , refspec );
1403
+ return ret ;
1404
+ }
1405
+
1360
1406
/*
1361
1407
* Given the set of refs the local repository has, the set of refs the
1362
1408
* remote repository has, and the refspec used for push, determine
0 commit comments