Skip to content

Commit eaf15ff

Browse files
committed
refs: use the lower-level functions when renaming
Also, don't loose the old reflog when renaming
1 parent 228a8be commit eaf15ff

1 file changed

Lines changed: 49 additions & 33 deletions

File tree

‎src/refdb_fs.c‎

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,56 +1428,72 @@ static int refdb_fs_backend__rename(
14281428
const char *message)
14291429
{
14301430
refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
1431-
git_reference *old, *new;
1432-
git_filebuf file = GIT_FILEBUF_INIT;
1431+
git_reference *old, *new = NULL;
1432+
git_filebuf old_lock = GIT_FILEBUF_INIT;
1433+
git_filebuf new_lock = GIT_FILEBUF_INIT;
14331434
int error;
1435+
git__refdb_flags flags;
14341436

14351437
assert(backend);
14361438

1437-
if ((error = reference_path_available(
1438-
backend, new_name, old_name, force)) < 0 ||
1439+
if ((error = reference_path_available(backend, new_name, old_name, force)) < 0 ||
14391440
(error = refdb_fs_backend__lookup(&old, _backend, old_name)) < 0)
14401441
return error;
14411442

1442-
if ((error = refdb_fs_backend__delete(_backend, old_name, who, message, NULL, NULL)) < 0) {
1443-
git_reference_free(old);
1444-
return error;
1445-
}
1443+
/* We delete the old ref first so we don't cause a failure later if the new
1444+
* name is the suffix or prefix of the old. Also, we skip the reflog, because
1445+
* we want to rename it */
1446+
if ((error = refdb_fs_backend__delete_tail(&old_lock, _backend, old, NULL, NULL, GIT_REFDB__SKIP_REFLOG, who, message)) < 0)
1447+
goto cleanup;
1448+
git_filebuf_cleanup(&old_lock);
14461449

1447-
new = git_reference__set_name(old, new_name);
1448-
if (!new) {
1449-
git_reference_free(old);
1450-
return -1;
1450+
/* We need to create a reference object to write */
1451+
if (old->type == GIT_REF_OID) {
1452+
new = git_reference__alloc(new_name, &old->target.oid, NULL);
1453+
} else if (old->type == GIT_REF_SYMBOLIC) {
1454+
new = git_reference__alloc_symbolic(new_name, old->target.symbolic);
1455+
} else {
1456+
assert(false);
14511457
}
14521458

1453-
if ((error = loose_lock(&file, backend, new->name)) < 0) {
1454-
git_reference_free(new);
1455-
return error;
1456-
}
1459+
if (new == NULL) goto cleanup;
14571460

1458-
/* Try to rename the refog; it's ok if the old doesn't exist */
1461+
/* Save the new ref on disk; we skip the reflog because the old ref might be
1462+
* sharing a suffix/prefix with us.
1463+
*/
1464+
flags = GIT_REFDB__SKIP_REFLOG;
1465+
if (force) flags |= GIT_REFDB__FORCE_WRITE;
1466+
if ((error = refdb_fs_backend__write_tail(&new_lock, _backend, new, NULL, NULL, flags, who, message)) < 0)
1467+
goto cleanup;
1468+
1469+
/* Try to rename the reflog; it's ok if the old doesn't exist */
14591470
error = refdb_reflog_fs__rename(_backend, old_name, new_name);
1460-
if (((error == 0) || (error == GIT_ENOTFOUND)) &&
1461-
((error = reflog_append(backend, new, git_reference_target(new), NULL, who, message)) < 0)) {
1462-
git_reference_free(new);
1463-
git_filebuf_cleanup(&file);
1464-
return error;
1465-
}
1471+
if (error < 0 && error != GIT_ENOTFOUND)
1472+
goto cleanup;
14661473

1467-
if (error < 0) {
1468-
git_reference_free(new);
1469-
git_filebuf_cleanup(&file);
1470-
return error;
1471-
}
1474+
if ((error = reflog_append(backend, new, git_reference_target(new), NULL, who, message)) < 0)
1475+
goto cleanup;
14721476

1477+
if ((error = loose_commit(&new_lock, new)) < 0)
1478+
goto cleanup;
14731479

1474-
if ((error = loose_commit(&file, new)) < 0 || out == NULL) {
1480+
1481+
goto success;
1482+
1483+
cleanup:
1484+
git_filebuf_cleanup(&new_lock);
1485+
git_reference_free(new);
1486+
git_reference_free(old);
1487+
new = NULL;
1488+
1489+
success:
1490+
1491+
if (out != NULL)
1492+
*out = new;
1493+
else
14751494
git_reference_free(new);
1476-
return error;
1477-
}
14781495

1479-
*out = new;
1480-
return 0;
1496+
return error;
14811497
}
14821498

14831499
static int refdb_fs_backend__compress(git_refdb_backend *_backend)

0 commit comments

Comments
 (0)