267
return 0;
268
}
269
270
+struct known_remote {
271
+ struct known_remote *next;
272
+ struct remote *remote;
273
+};
274
+
275
+struct known_remotes {
276
+ struct remote *to_delete;
277
+ struct known_remote *list;
278
+};
279
+
280
+static int add_known_remote(struct remote *remote, void *cb_data)
281
+{
282
+ struct known_remotes *all = cb_data;
283
+ struct known_remote *r;
284
+
285
+ if (!strcmp(all->to_delete->name, remote->name))
286
+ return 0;
287
+
288
+ r = xmalloc(sizeof(*r));
289
+ r->remote = remote;
290
+ r->next = all->list;
291
+ all->list = r;
292
+ return 0;
293
+}
294
+
295
struct branches_for_remote {
271
- const char *prefix;
296
+ struct remote *remote;
297
struct path_list *branches;
298
+ struct known_remotes *keep;
299
};
300
301
static int add_branch_for_removal(const char *refname,
302
const unsigned char *sha1, int flags, void *cb_data)
303
{
304
struct branches_for_remote *branches = cb_data;
305
+ struct refspec refspec;
306
+ struct path_list_item *item;
307
+ struct known_remote *kr;
308
280
- if (!prefixcmp(refname, branches->prefix)) {
281
- struct path_list_item *item;
309
+ memset(&refspec, 0, sizeof(refspec));
310
+ refspec.dst = (char *)refname;
311
+ if (remote_find_tracking(branches->remote, &refspec))
312
+ return 0;
313
+
314
+ /* don't delete a branch if another remote also uses it */
315
+ for (kr = branches->keep->list; kr; kr = kr->next) {
316
+ memset(&refspec, 0, sizeof(refspec));
317
+ refspec.dst = (char *)refname;
318
+ if (!remote_find_tracking(kr->remote, &refspec))
319
+ return 0;
320
+ }
321
283
- /* make sure that symrefs are deleted */
284
- if (flags & REF_ISSYMREF)
285
- return unlink(git_path(refname));
322
+ /* make sure that symrefs are deleted */
323
+ if (flags & REF_ISSYMREF)
324
+ return unlink(git_path(refname));
325
287
- item = path_list_append(refname, branches->branches);
288
- item->util = xmalloc(20);
289
- hashcpy(item->util, sha1);
290
- }
326
+ item = path_list_append(refname, branches->branches);
327
+ item->util = xmalloc(20);
328
+ hashcpy(item->util, sha1);
329
330
return 0;
331
}
351
};
352
struct remote *remote;
353
struct strbuf buf;
354
+ struct known_remotes known_remotes = { NULL, NULL };
355
struct path_list branches = { NULL, 0, 0, 1 };
317
- struct branches_for_remote cb_data = { NULL, &branches };
356
+ struct branches_for_remote cb_data = { NULL, &branches, &known_remotes };
357
int i;
358
359
if (argc != 2)
363
if (!remote)
364
die("No such remote: %s", argv[1]);
365
366
+ known_remotes.to_delete = remote;
367
+ for_each_remote(add_known_remote, &known_remotes);
368
+
369
strbuf_init(&buf, 0);
370
strbuf_addf(&buf, "remote.%s", remote->name);
371
if (git_config_rename_section(buf.buf, NULL) < 1)
394
* the branches one by one, since for_each_ref() relies on cached
395
* refs, which are invalidated when deleting a branch.
396
*/
355
- strbuf_reset(&buf);
356
- strbuf_addf(&buf, "refs/remotes/%s/", remote->name);
357
- cb_data.prefix = buf.buf;
397
+ cb_data.remote = remote;
398
i = for_each_ref(add_branch_for_removal, &cb_data);
399
strbuf_release(&buf);
400