1231
int result;
1232
1233
struct string_list changed_submodule_names;
1234
+
1235
+ /* Pending fetches by OIDs */
1236
+ struct fetch_task **oid_fetch_tasks;
1237
+ int oid_fetch_tasks_nr, oid_fetch_tasks_alloc;
1238
};
1235
-#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0, 0, STRING_LIST_INIT_DUP }
1239
+#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0, 0, \
1240
+ STRING_LIST_INIT_DUP, \
1241
+ NULL, 0, 0}
1242
1243
static int get_fetch_recurse_config(const struct submodule *submodule,
1244
struct submodule_parallel_fetch *spf)
1265
return spf->default_option;
1266
}
1267
1268
+/*
1269
+ * Fetch in progress (if callback data) or
1270
+ * pending (if in oid_fetch_tasks in struct submodule_parallel_fetch)
1271
+ */
1272
+struct fetch_task {
1273
+ struct repository *repo;
1274
+ const struct submodule *sub;
1275
+ unsigned free_sub : 1; /* Do we need to free the submodule? */
1276
+
1277
+ struct oid_array *commits; /* Ensure these commits are fetched */
1278
+};
1279
+
1280
+/**
1281
+ * When a submodule is not defined in .gitmodules, we cannot access it
1282
+ * via the regular submodule-config. Create a fake submodule, which we can
1283
+ * work on.
1284
+ */
1285
+static const struct submodule *get_non_gitmodules_submodule(const char *path)
1286
+{
1287
+ struct submodule *ret = NULL;
1288
+ const char *name = default_name_or_path(path);
1289
+
1290
+ if (!name)
1291
+ return NULL;
1292
+
1293
+ ret = xmalloc(sizeof(*ret));
1294
+ memset(ret, 0, sizeof(*ret));
1295
+ ret->path = name;
1296
+ ret->name = name;
1297
+
1298
+ return (const struct submodule *) ret;
1299
+}
1300
+
1301
+static struct fetch_task *fetch_task_create(struct repository *r,
1302
+ const char *path)
1303
+{
1304
+ struct fetch_task *task = xmalloc(sizeof(*task));
1305
+ memset(task, 0, sizeof(*task));
1306
+
1307
+ task->sub = submodule_from_path(r, &null_oid, path);
1308
+ if (!task->sub) {
1309
+ /*
1310
+ * No entry in .gitmodules? Technically not a submodule,
1311
+ * but historically we supported repositories that happen to be
1312
+ * in-place where a gitlink is. Keep supporting them.
1313
+ */
1314
+ task->sub = get_non_gitmodules_submodule(path);
1315
+ if (!task->sub) {
1316
+ free(task);
1317
+ return NULL;
1318
+ }
1319
+
1320
+ task->free_sub = 1;
1321
+ }
1322
+
1323
+ return task;
1324
+}
1325
+
1326
+static void fetch_task_release(struct fetch_task *p)
1327
+{
1328
+ if (p->free_sub)
1329
+ free((void*)p->sub);
1330
+ p->free_sub = 0;
1331
+ p->sub = NULL;
1332
+
1333
+ if (p->repo)
1334
+ repo_clear(p->repo);
1335
+ FREE_AND_NULL(p->repo);
1336
+}
1337
+
1338
static struct repository *get_submodule_repo_for(struct repository *r,
1339
const struct submodule *sub)
1340
{
1362
static int get_next_submodule(struct child_process *cp,
1363
struct strbuf *err, void *data, void **task_cb)
1364
{
1289
- int ret = 0;
1365
struct submodule_parallel_fetch *spf = data;
1366
1367
for (; spf->count < spf->r->index->cache_nr; spf->count++) {
1293
- struct strbuf submodule_prefix = STRBUF_INIT;
1368
const struct cache_entry *ce = spf->r->index->cache[spf->count];
1369
const char *default_argv;
1296
- const struct submodule *submodule;
1297
- struct repository *repo;
1298
- struct submodule default_submodule = SUBMODULE_INIT;
1370
+ struct fetch_task *task;
1371
1372
if (!S_ISGITLINK(ce->ce_mode))
1373
continue;
1374
1303
- submodule = submodule_from_path(spf->r, &null_oid, ce->name);
1304
- if (!submodule) {
1305
- const char *name = default_name_or_path(ce->name);
1306
- if (name) {
1307
- default_submodule.path = name;
1308
- default_submodule.name = name;
1309
- submodule = &default_submodule;
1310
- }
1311
- }
1375
+ task = fetch_task_create(spf->r, ce->name);
1376
+ if (!task)
1377
+ continue;
1378
1313
- switch (get_fetch_recurse_config(submodule, spf))
1379
+ switch (get_fetch_recurse_config(task->sub, spf))
1380
{
1381
default:
1382
case RECURSE_SUBMODULES_DEFAULT:
1383
case RECURSE_SUBMODULES_ON_DEMAND:
1318
- if (!submodule ||
1384
+ if (!task->sub ||
1385
!string_list_lookup(
1386
&spf->changed_submodule_names,
1321
- submodule->name))
1387
+ task->sub->name))
1388
continue;
1389
default_argv = "on-demand";
1390
break;
1395
continue;
1396
}
1397
1332
- strbuf_addf(&submodule_prefix, "%s%s/", spf->prefix, ce->name);
1333
- repo = get_submodule_repo_for(spf->r, submodule);
1334
- if (repo) {
1398
+ task->repo = get_submodule_repo_for(spf->r, task->sub);
1399
+ if (task->repo) {
1400
+ struct strbuf submodule_prefix = STRBUF_INIT;
1401
child_process_init(cp);
1336
- cp->dir = xstrdup(repo->gitdir);
1402
+ cp->dir = task->repo->gitdir;
1403
prepare_submodule_repo_env_in_gitdir(&cp->env_array);
1404
cp->git_cmd = 1;
1405
if (!spf->quiet)
1409
argv_array_pushv(&cp->args, spf->args.argv);
1410
argv_array_push(&cp->args, default_argv);
1411
argv_array_push(&cp->args, "--submodule-prefix");
1412
+
1413
+ strbuf_addf(&submodule_prefix, "%s%s/",
1414
+ spf->prefix,
1415
+ task->sub->path);
1416
argv_array_push(&cp->args, submodule_prefix.buf);
1417
1348
- repo_clear(repo);
1349
- free(repo);
1350
- ret = 1;
1418
+ spf->count++;
1419
+ *task_cb = task;
1420
+
1421
+ strbuf_release(&submodule_prefix);
1422
+ return 1;
1423
} else {
1424
+
1425
+ fetch_task_release(task);
1426
+ free(task);
1427
+
1428
/*
1429
* An empty directory is normal,
1430
* the submodule is not initialized
1437
ce->name);
1438
}
1439
}
1440
+ }
1441
+
1442
+ if (spf->oid_fetch_tasks_nr) {
1443
+ struct fetch_task *task =
1444
+ spf->oid_fetch_tasks[spf->oid_fetch_tasks_nr - 1];
1445
+ struct strbuf submodule_prefix = STRBUF_INIT;
1446
+ spf->oid_fetch_tasks_nr--;
1447
+
1448
+ strbuf_addf(&submodule_prefix, "%s%s/",
1449
+ spf->prefix, task->sub->path);
1450
+
1451
+ child_process_init(cp);
1452
+ prepare_submodule_repo_env_in_gitdir(&cp->env_array);
1453
+ cp->git_cmd = 1;
1454
+ cp->dir = task->repo->gitdir;
1455
+
1456
+ argv_array_init(&cp->args);
1457
+ argv_array_pushv(&cp->args, spf->args.argv);
1458
+ argv_array_push(&cp->args, "on-demand");
1459
+ argv_array_push(&cp->args, "--submodule-prefix");
1460
+ argv_array_push(&cp->args, submodule_prefix.buf);
1461
+
1462
+ /* NEEDSWORK: have get_default_remote from submodule--helper */
1463
+ argv_array_push(&cp->args, "origin");
1464
+ oid_array_for_each_unique(task->commits,
1465
+ append_oid_to_argv, &cp->args);
1466
+
1467
+ *task_cb = task;
1468
strbuf_release(&submodule_prefix);
1365
- if (ret) {
1366
- spf->count++;
1367
- return 1;
1368
- }
1469
+ return 1;
1470
}
1471
+
1472
return 0;
1473
}
1474
1476
void *cb, void *task_cb)
1477
{
1478
struct submodule_parallel_fetch *spf = cb;
1479
+ struct fetch_task *task = task_cb;
1480
1481
spf->result = 1;
1482
1483
+ fetch_task_release(task);
1484
return 0;
1485
}
1486
1487
+static int commit_missing_in_sub(const struct object_id *oid, void *data)
1488
+{
1489
+ struct repository *subrepo = data;
1490
+
1491
+ enum object_type type = oid_object_info(subrepo, oid, NULL);
1492
+
1493
+ return type != OBJ_COMMIT;
1494
+}
1495
+
1496
static int fetch_finish(int retvalue, struct strbuf *err,
1497
void *cb, void *task_cb)
1498
{
1499
struct submodule_parallel_fetch *spf = cb;
1500
+ struct fetch_task *task = task_cb;
1501
+
1502
+ struct string_list_item *it;
1503
+ struct oid_array *commits;
1504
1505
if (retvalue)
1506
spf->result = 1;
1507
1508
+ if (!task || !task->sub)
1509
+ BUG("callback cookie bogus");
1510
+
1511
+ /* Is this the second time we process this submodule? */
1512
+ if (task->commits)
1513
+ goto out;
1514
+
1515
+ it = string_list_lookup(&spf->changed_submodule_names, task->sub->name);
1516
+ if (!it)
1517
+ /* Could be an unchanged submodule, not contained in the list */
1518
+ goto out;
1519
+
1520
+ commits = it->util;
1521
+ oid_array_filter(commits,
1522
+ commit_missing_in_sub,
1523
+ task->repo);
1524
+
1525
+ /* Are there commits we want, but do not exist? */
1526
+ if (commits->nr) {
1527
+ task->commits = commits;
1528
+ ALLOC_GROW(spf->oid_fetch_tasks,
1529
+ spf->oid_fetch_tasks_nr + 1,
1530
+ spf->oid_fetch_tasks_alloc);
1531
+ spf->oid_fetch_tasks[spf->oid_fetch_tasks_nr] = task;
1532
+ spf->oid_fetch_tasks_nr++;
1533
+ return 0;
1534
+ }
1535
+
1536
+out:
1537
+ fetch_task_release(task);
1538
+
1539
return 0;
1540
}
1541