Commit 7ee8c7e6 by Carlos Martín Nieto

refs: placeholder conditional delete

We don't actually pass the old value yet.
parent f8621dde
...@@ -106,7 +106,7 @@ struct git_refdb_backend { ...@@ -106,7 +106,7 @@ struct git_refdb_backend {
* Deletes the given reference from the refdb. A refdb implementation * Deletes the given reference from the refdb. A refdb implementation
* must provide this function. * must provide this function.
*/ */
int (*del)(git_refdb_backend *backend, const char *ref_name); int (*del)(git_refdb_backend *backend, const char *ref_name, const git_oid *old_id, const char *old_target);
/** /**
* Suggests that the given refdb compress or optimize its references. * Suggests that the given refdb compress or optimize its references.
......
...@@ -201,10 +201,10 @@ int git_refdb_rename( ...@@ -201,10 +201,10 @@ int git_refdb_rename(
return 0; return 0;
} }
int git_refdb_delete(struct git_refdb *db, const char *ref_name) int git_refdb_delete(struct git_refdb *db, const char *ref_name, const git_oid *old_id, const char *old_target)
{ {
assert(db && db->backend); assert(db && db->backend);
return db->backend->del(db->backend, ref_name); return db->backend->del(db->backend, ref_name, old_id, old_target);
} }
int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name) int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name)
......
...@@ -43,7 +43,7 @@ int git_refdb_iterator_next_name(const char **out, git_reference_iterator *iter) ...@@ -43,7 +43,7 @@ int git_refdb_iterator_next_name(const char **out, git_reference_iterator *iter)
void git_refdb_iterator_free(git_reference_iterator *iter); void git_refdb_iterator_free(git_reference_iterator *iter);
int git_refdb_write(git_refdb *refdb, git_reference *ref, int force, const git_signature *who, const char *message, const git_oid *old_id, const char *old_target); int git_refdb_write(git_refdb *refdb, git_reference *ref, int force, const git_signature *who, const char *message, const git_oid *old_id, const char *old_target);
int git_refdb_delete(git_refdb *refdb, const char *ref_name); int git_refdb_delete(git_refdb *refdb, const char *ref_name, const git_oid *old_id, const char *old_target);
int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name); int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name);
int git_refdb_reflog_write(git_reflog *reflog); int git_refdb_reflog_write(git_reflog *reflog);
......
...@@ -688,20 +688,20 @@ static int reference_path_available( ...@@ -688,20 +688,20 @@ static int reference_path_available(
return 0; return 0;
} }
static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const git_reference *ref) static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *name)
{ {
int error; int error;
git_buf ref_path = GIT_BUF_INIT; git_buf ref_path = GIT_BUF_INIT;
assert(file && backend && ref); assert(file && backend && name);
/* Remove a possibly existing empty directory hierarchy /* Remove a possibly existing empty directory hierarchy
* which name would collide with the reference name * which name would collide with the reference name
*/ */
if (git_futils_rmdir_r(ref->name, backend->path, GIT_RMDIR_SKIP_NONEMPTY) < 0) if (git_futils_rmdir_r(name, backend->path, GIT_RMDIR_SKIP_NONEMPTY) < 0)
return -1; return -1;
if (git_buf_joinpath(&ref_path, backend->path, ref->name) < 0) if (git_buf_joinpath(&ref_path, backend->path, name) < 0)
return -1; return -1;
error = git_filebuf_open(file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE); error = git_filebuf_open(file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE);
...@@ -930,7 +930,7 @@ static bool should_write_reflog(git_repository *repo, const char *name) ...@@ -930,7 +930,7 @@ static bool should_write_reflog(git_repository *repo, const char *name)
return 0; return 0;
} }
static int cmp_old_ref(int *cmp, git_refdb_backend *backend, const git_reference *ref, static int cmp_old_ref(int *cmp, git_refdb_backend *backend, const char *name,
const git_oid *old_id, const char *old_target) const git_oid *old_id, const char *old_target)
{ {
int error = 0; int error = 0;
...@@ -938,7 +938,7 @@ static int cmp_old_ref(int *cmp, git_refdb_backend *backend, const git_reference ...@@ -938,7 +938,7 @@ static int cmp_old_ref(int *cmp, git_refdb_backend *backend, const git_reference
*cmp = 0; *cmp = 0;
if (old_id || old_target) { if (old_id || old_target) {
if ((error = refdb_fs_backend__lookup(&old_ref, backend, ref->name)) < 0) if ((error = refdb_fs_backend__lookup(&old_ref, backend, name)) < 0)
goto out; goto out;
} }
...@@ -965,7 +965,6 @@ static int refdb_fs_backend__write( ...@@ -965,7 +965,6 @@ static int refdb_fs_backend__write(
{ {
refdb_fs_backend *backend = (refdb_fs_backend *)_backend; refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
git_filebuf file = GIT_FILEBUF_INIT; git_filebuf file = GIT_FILEBUF_INIT;
git_reference *old_ref = NULL;
int error = 0, cmp = 0; int error = 0, cmp = 0;
assert(backend); assert(backend);
...@@ -975,10 +974,10 @@ static int refdb_fs_backend__write( ...@@ -975,10 +974,10 @@ static int refdb_fs_backend__write(
return error; return error;
/* We need to perform the reflog append and old value check under the ref's lock */ /* We need to perform the reflog append and old value check under the ref's lock */
if ((error = loose_lock(&file, backend, ref)) < 0) if ((error = loose_lock(&file, backend, ref->name)) < 0)
return error; return error;
if ((error = cmp_old_ref(&cmp, _backend, ref, old_id, old_target)) < 0) if ((error = cmp_old_ref(&cmp, _backend, ref->name, old_id, old_target)) < 0)
goto on_error; goto on_error;
if (cmp) { if (cmp) {
...@@ -1002,16 +1001,32 @@ on_error: ...@@ -1002,16 +1001,32 @@ on_error:
static int refdb_fs_backend__delete( static int refdb_fs_backend__delete(
git_refdb_backend *_backend, git_refdb_backend *_backend,
const char *ref_name) const char *ref_name,
const git_oid *old_id, const char *old_target)
{ {
refdb_fs_backend *backend = (refdb_fs_backend *)_backend; refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
git_buf loose_path = GIT_BUF_INIT; git_buf loose_path = GIT_BUF_INIT;
size_t pack_pos; size_t pack_pos
int error = 0; ; git_filebuf file = GIT_FILEBUF_INIT;
int error = 0, cmp = 0;
bool loose_deleted = 0; bool loose_deleted = 0;
assert(backend && ref_name); assert(backend && ref_name);
if ((error = loose_lock(&file, backend, ref_name)) < 0)
return error;
error = cmp_old_ref(&cmp, _backend, ref_name, old_id, old_target);
//git_filebuf_cleanup(&file);
if (error < 0)
goto cleanup;
if (cmp) {
giterr_set(GITERR_REFERENCE, "old reference value does not match");
error = GIT_EMODIFIED;
goto cleanup;
}
/* If a loose reference exists, remove it from the filesystem */ /* If a loose reference exists, remove it from the filesystem */
if (git_buf_joinpath(&loose_path, backend->path, ref_name) < 0) if (git_buf_joinpath(&loose_path, backend->path, ref_name) < 0)
return -1; return -1;
...@@ -1024,14 +1039,14 @@ static int refdb_fs_backend__delete( ...@@ -1024,14 +1039,14 @@ static int refdb_fs_backend__delete(
git_buf_free(&loose_path); git_buf_free(&loose_path);
if (error != 0) if (error != 0)
return error; goto cleanup;
if (packed_reload(backend) < 0) if ((error = packed_reload(backend)) < 0)
return -1; goto cleanup;
/* If a packed reference exists, remove it from the packfile and repack */ /* If a packed reference exists, remove it from the packfile and repack */
if (git_sortedcache_wlock(backend->refcache) < 0) if ((error = git_sortedcache_wlock(backend->refcache)) < 0)
return -1; goto cleanup;
if (!(error = git_sortedcache_lookup_index( if (!(error = git_sortedcache_lookup_index(
&pack_pos, backend->refcache, ref_name))) &pack_pos, backend->refcache, ref_name)))
...@@ -1039,10 +1054,17 @@ static int refdb_fs_backend__delete( ...@@ -1039,10 +1054,17 @@ static int refdb_fs_backend__delete(
git_sortedcache_wunlock(backend->refcache); git_sortedcache_wunlock(backend->refcache);
if (error == GIT_ENOTFOUND) if (error == GIT_ENOTFOUND) {
return loose_deleted ? 0 : ref_error_notfound(ref_name); error = loose_deleted ? 0 : ref_error_notfound(ref_name);
goto cleanup;
}
error = packed_write(backend);
return packed_write(backend); cleanup:
git_filebuf_cleanup(&file);
return error;
} }
static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_name, const char *new_name); static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_name, const char *new_name);
...@@ -1068,7 +1090,7 @@ static int refdb_fs_backend__rename( ...@@ -1068,7 +1090,7 @@ static int refdb_fs_backend__rename(
(error = refdb_fs_backend__lookup(&old, _backend, old_name)) < 0) (error = refdb_fs_backend__lookup(&old, _backend, old_name)) < 0)
return error; return error;
if ((error = refdb_fs_backend__delete(_backend, old_name)) < 0) { if ((error = refdb_fs_backend__delete(_backend, old_name, NULL, NULL)) < 0) {
git_reference_free(old); git_reference_free(old);
return error; return error;
} }
...@@ -1079,7 +1101,7 @@ static int refdb_fs_backend__rename( ...@@ -1079,7 +1101,7 @@ static int refdb_fs_backend__rename(
return -1; return -1;
} }
if ((error = loose_lock(&file, backend, new)) < 0) { if ((error = loose_lock(&file, backend, new->name)) < 0) {
git_reference_free(new); git_reference_free(new);
return error; return error;
} }
......
...@@ -116,7 +116,7 @@ void git_reference_free(git_reference *reference) ...@@ -116,7 +116,7 @@ void git_reference_free(git_reference *reference)
int git_reference_delete(git_reference *ref) int git_reference_delete(git_reference *ref)
{ {
return git_refdb_delete(ref->db, ref->name); return git_refdb_delete(ref->db, ref->name, NULL, NULL);
} }
int git_reference_lookup(git_reference **ref_out, int git_reference_lookup(git_reference **ref_out,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment