зеркало из https://github.com/microsoft/git.git
walker.c: use ref transaction for ref updates
Switch to using ref transactions in walker_fetch(). As part of the refactoring to use ref transactions we also fix a potential memory leak where in the original code if write_ref_sha1() would fail we would end up returning from the function without free()ing the msg string. Note that this function is only called when fetching from a remote HTTP repository onto the local (most of the time single-user) repository which likely means that the type of collisions that the previous locking would protect against and cause the fetch to fail for are even more rare. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
3f09ba7543
Коммит
b6b10bb44c
72
walker.c
72
walker.c
|
@ -251,40 +251,40 @@ void walker_targets_free(int targets, char **target, const char **write_ref)
|
|||
int walker_fetch(struct walker *walker, int targets, char **target,
|
||||
const char **write_ref, const char *write_ref_log_details)
|
||||
{
|
||||
struct ref_lock **lock = xcalloc(targets, sizeof(struct ref_lock *));
|
||||
struct strbuf refname = STRBUF_INIT;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
struct ref_transaction *transaction = NULL;
|
||||
unsigned char *sha1 = xmalloc(targets * 20);
|
||||
char *msg;
|
||||
int ret;
|
||||
int i;
|
||||
char *msg = NULL;
|
||||
int i, ret = -1;
|
||||
|
||||
save_commit_buffer = 0;
|
||||
|
||||
for (i = 0; i < targets; i++) {
|
||||
if (!write_ref || !write_ref[i])
|
||||
continue;
|
||||
|
||||
lock[i] = lock_ref_sha1(write_ref[i], NULL);
|
||||
if (!lock[i]) {
|
||||
error("Can't lock ref %s", write_ref[i]);
|
||||
goto unlock_and_fail;
|
||||
if (write_ref) {
|
||||
transaction = ref_transaction_begin(&err);
|
||||
if (!transaction) {
|
||||
error("%s", err.buf);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!walker->get_recover)
|
||||
for_each_ref(mark_complete, NULL);
|
||||
|
||||
for (i = 0; i < targets; i++) {
|
||||
if (interpret_target(walker, target[i], &sha1[20 * i])) {
|
||||
error("Could not interpret response from server '%s' as something to pull", target[i]);
|
||||
goto unlock_and_fail;
|
||||
goto done;
|
||||
}
|
||||
if (process(walker, lookup_unknown_object(&sha1[20 * i])))
|
||||
goto unlock_and_fail;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (loop(walker))
|
||||
goto unlock_and_fail;
|
||||
|
||||
goto done;
|
||||
if (!write_ref) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
if (write_ref_log_details) {
|
||||
msg = xmalloc(strlen(write_ref_log_details) + 12);
|
||||
sprintf(msg, "fetch from %s", write_ref_log_details);
|
||||
|
@ -292,23 +292,33 @@ int walker_fetch(struct walker *walker, int targets, char **target,
|
|||
msg = NULL;
|
||||
}
|
||||
for (i = 0; i < targets; i++) {
|
||||
if (!write_ref || !write_ref[i])
|
||||
if (!write_ref[i])
|
||||
continue;
|
||||
ret = write_ref_sha1(lock[i], &sha1[20 * i], msg ? msg : "fetch (unknown)");
|
||||
lock[i] = NULL;
|
||||
if (ret)
|
||||
goto unlock_and_fail;
|
||||
strbuf_reset(&refname);
|
||||
strbuf_addf(&refname, "refs/%s", write_ref[i]);
|
||||
if (ref_transaction_update(transaction, refname.buf,
|
||||
&sha1[20 * i], NULL, 0, 0,
|
||||
&err)) {
|
||||
error("%s", err.buf);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (ref_transaction_commit(transaction,
|
||||
msg ? msg : "fetch (unknown)",
|
||||
&err)) {
|
||||
error("%s", err.buf);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
ref_transaction_free(transaction);
|
||||
free(msg);
|
||||
|
||||
return 0;
|
||||
|
||||
unlock_and_fail:
|
||||
for (i = 0; i < targets; i++)
|
||||
if (lock[i])
|
||||
unlock_ref(lock[i]);
|
||||
|
||||
return -1;
|
||||
free(sha1);
|
||||
strbuf_release(&err);
|
||||
strbuf_release(&refname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void walker_free(struct walker *walker)
|
||||
|
|
Загрузка…
Ссылка в новой задаче