8
8
#include "tag.h"
9
9
#include "string-list.h"
10
10
11
+ enum map_direction { FROM_SRC , FROM_DST };
12
+
11
13
static struct refspec s_tag_refspec = {
12
14
0 ,
13
15
1 ,
@@ -978,16 +980,20 @@ static void tail_link_ref(struct ref *ref, struct ref ***tail)
978
980
* tail = & ref -> next ;
979
981
}
980
982
983
+ static struct ref * alloc_delete_ref (void )
984
+ {
985
+ struct ref * ref = alloc_ref ("(delete)" );
986
+ hashclr (ref -> new_sha1 );
987
+ return ref ;
988
+ }
989
+
981
990
static struct ref * try_explicit_object_name (const char * name )
982
991
{
983
992
unsigned char sha1 [20 ];
984
993
struct ref * ref ;
985
994
986
- if (!* name ) {
987
- ref = alloc_ref ("(delete)" );
988
- hashclr (ref -> new_sha1 );
989
- return ref ;
990
- }
995
+ if (!* name )
996
+ return alloc_delete_ref ();
991
997
if (get_sha1 (name , sha1 ))
992
998
return NULL ;
993
999
ref = alloc_ref (name );
@@ -1110,10 +1116,11 @@ static int match_explicit_refs(struct ref *src, struct ref *dst,
1110
1116
return errs ;
1111
1117
}
1112
1118
1113
- static const struct refspec * check_pattern_match (const struct refspec * rs ,
1114
- int rs_nr ,
1115
- const struct ref * src )
1119
+ static char * get_ref_match (const struct refspec * rs , int rs_nr , const struct ref * ref ,
1120
+ int send_mirror , int direction , const struct refspec * * ret_pat )
1116
1121
{
1122
+ const struct refspec * pat ;
1123
+ char * name ;
1117
1124
int i ;
1118
1125
int matching_refs = -1 ;
1119
1126
for (i = 0 ; i < rs_nr ; i ++ ) {
@@ -1123,14 +1130,36 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
1123
1130
continue ;
1124
1131
}
1125
1132
1126
- if (rs [i ].pattern && match_name_with_pattern (rs [i ].src , src -> name ,
1127
- NULL , NULL ))
1128
- return rs + i ;
1133
+ if (rs [i ].pattern ) {
1134
+ const char * dst_side = rs [i ].dst ? rs [i ].dst : rs [i ].src ;
1135
+ int match ;
1136
+ if (direction == FROM_SRC )
1137
+ match = match_name_with_pattern (rs [i ].src , ref -> name , dst_side , & name );
1138
+ else
1139
+ match = match_name_with_pattern (dst_side , ref -> name , rs [i ].src , & name );
1140
+ if (match ) {
1141
+ matching_refs = i ;
1142
+ break ;
1143
+ }
1144
+ }
1129
1145
}
1130
- if (matching_refs != -1 )
1131
- return rs + matching_refs ;
1132
- else
1146
+ if (matching_refs == -1 )
1133
1147
return NULL ;
1148
+
1149
+ pat = rs + matching_refs ;
1150
+ if (pat -> matching ) {
1151
+ /*
1152
+ * "matching refs"; traditionally we pushed everything
1153
+ * including refs outside refs/heads/ hierarchy, but
1154
+ * that does not make much sense these days.
1155
+ */
1156
+ if (!send_mirror && prefixcmp (ref -> name , "refs/heads/" ))
1157
+ return NULL ;
1158
+ name = xstrdup (ref -> name );
1159
+ }
1160
+ if (ret_pat )
1161
+ * ret_pat = pat ;
1162
+ return name ;
1134
1163
}
1135
1164
1136
1165
static struct ref * * tail_ref (struct ref * * head )
@@ -1155,9 +1184,10 @@ int match_push_refs(struct ref *src, struct ref **dst,
1155
1184
struct refspec * rs ;
1156
1185
int send_all = flags & MATCH_REFS_ALL ;
1157
1186
int send_mirror = flags & MATCH_REFS_MIRROR ;
1187
+ int send_prune = flags & MATCH_REFS_PRUNE ;
1158
1188
int errs ;
1159
1189
static const char * default_refspec [] = { ":" , NULL };
1160
- struct ref * * dst_tail = tail_ref (dst );
1190
+ struct ref * ref , * * dst_tail = tail_ref (dst );
1161
1191
1162
1192
if (!nr_refspec ) {
1163
1193
nr_refspec = 1 ;
@@ -1167,39 +1197,23 @@ int match_push_refs(struct ref *src, struct ref **dst,
1167
1197
errs = match_explicit_refs (src , * dst , & dst_tail , rs , nr_refspec );
1168
1198
1169
1199
/* pick the remainder */
1170
- for ( ; src ; src = src -> next ) {
1200
+ for (ref = src ; ref ; ref = ref -> next ) {
1171
1201
struct ref * dst_peer ;
1172
1202
const struct refspec * pat = NULL ;
1173
1203
char * dst_name ;
1174
- if (src -> peer_ref )
1175
- continue ;
1176
1204
1177
- pat = check_pattern_match (rs , nr_refspec , src );
1178
- if (!pat )
1205
+ if (ref -> peer_ref )
1179
1206
continue ;
1180
1207
1181
- if (pat -> matching ) {
1182
- /*
1183
- * "matching refs"; traditionally we pushed everything
1184
- * including refs outside refs/heads/ hierarchy, but
1185
- * that does not make much sense these days.
1186
- */
1187
- if (!send_mirror && prefixcmp (src -> name , "refs/heads/" ))
1188
- continue ;
1189
- dst_name = xstrdup (src -> name );
1208
+ dst_name = get_ref_match (rs , nr_refspec , ref , send_mirror , FROM_SRC , & pat );
1209
+ if (!dst_name )
1210
+ continue ;
1190
1211
1191
- } else {
1192
- const char * dst_side = pat -> dst ? pat -> dst : pat -> src ;
1193
- if (!match_name_with_pattern (pat -> src , src -> name ,
1194
- dst_side , & dst_name ))
1195
- die ("Didn't think it matches any more" );
1196
- }
1197
1212
dst_peer = find_ref_by_name (* dst , dst_name );
1198
1213
if (dst_peer ) {
1199
1214
if (dst_peer -> peer_ref )
1200
1215
/* We're already sending something to this ref. */
1201
1216
goto free_name ;
1202
-
1203
1217
} else {
1204
1218
if (pat -> matching && !(send_all || send_mirror ))
1205
1219
/*
@@ -1211,13 +1225,30 @@ int match_push_refs(struct ref *src, struct ref **dst,
1211
1225
1212
1226
/* Create a new one and link it */
1213
1227
dst_peer = make_linked_ref (dst_name , & dst_tail );
1214
- hashcpy (dst_peer -> new_sha1 , src -> new_sha1 );
1228
+ hashcpy (dst_peer -> new_sha1 , ref -> new_sha1 );
1215
1229
}
1216
- dst_peer -> peer_ref = copy_ref (src );
1230
+ dst_peer -> peer_ref = copy_ref (ref );
1217
1231
dst_peer -> force = pat -> force ;
1218
1232
free_name :
1219
1233
free (dst_name );
1220
1234
}
1235
+ if (send_prune ) {
1236
+ /* check for missing refs on the remote */
1237
+ for (ref = * dst ; ref ; ref = ref -> next ) {
1238
+ char * src_name ;
1239
+
1240
+ if (ref -> peer_ref )
1241
+ /* We're already sending something to this ref. */
1242
+ continue ;
1243
+
1244
+ src_name = get_ref_match (rs , nr_refspec , ref , send_mirror , FROM_DST , NULL );
1245
+ if (src_name ) {
1246
+ if (!find_ref_by_name (src , src_name ))
1247
+ ref -> peer_ref = alloc_delete_ref ();
1248
+ free (src_name );
1249
+ }
1250
+ }
1251
+ }
1221
1252
if (errs )
1222
1253
return -1 ;
1223
1254
return 0 ;
0 commit comments