mirror of
https://git.proxmox.com/git/libgit2
synced 2026-01-26 06:04:06 +00:00
remote: prune refs when fetching
This commit is contained in:
parent
4eb97ef3bf
commit
5f47394753
@ -374,6 +374,14 @@ GIT_EXTERN(int) git_remote_update_tips(
|
||||
const git_signature *signature,
|
||||
const char *reflog_message);
|
||||
|
||||
/**
|
||||
* Prune tracking refs that are no longer present on remote
|
||||
*
|
||||
* @param remote the remote to prune
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_remote_prune(git_remote *remote);
|
||||
|
||||
/**
|
||||
* Download new data and update tips
|
||||
*
|
||||
@ -584,6 +592,24 @@ GIT_EXTERN(void) git_remote_set_autotag(
|
||||
git_remote *remote,
|
||||
git_remote_autotag_option_t value);
|
||||
|
||||
/**
|
||||
* Retrieve the ref-prune setting
|
||||
*
|
||||
* @param remote the remote to query
|
||||
* @return the ref-prune setting
|
||||
*/
|
||||
GIT_EXTERN(int) git_remote_prune_refs(const git_remote *remote);
|
||||
|
||||
/**
|
||||
* Set the ref-prune setting
|
||||
*
|
||||
* @param remote the remote to configure
|
||||
* @param value a boolean value
|
||||
*/
|
||||
GIT_EXTERN(void) git_remote_set_prune_refs(
|
||||
git_remote *remote,
|
||||
int value);
|
||||
|
||||
/**
|
||||
* Give the remote a new name
|
||||
*
|
||||
|
||||
103
src/remote.c
103
src/remote.c
@ -287,6 +287,7 @@ int git_remote_dup(git_remote **dest, git_remote *source)
|
||||
remote->repo = source->repo;
|
||||
remote->download_tags = source->download_tags;
|
||||
remote->update_fetchhead = source->update_fetchhead;
|
||||
remote->prune_refs = source->prune_refs;
|
||||
|
||||
if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
|
||||
git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
|
||||
@ -442,6 +443,22 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
|
||||
if (download_tags_value(remote, config) < 0)
|
||||
goto cleanup;
|
||||
|
||||
git_buf_clear(&buf);
|
||||
git_buf_printf(&buf, "remote.%s.prune", name);
|
||||
|
||||
if ((error = git_config_get_bool(&remote->prune_refs, config, git_buf_cstr(&buf))) < 0) {
|
||||
if (error == GIT_ENOTFOUND) {
|
||||
giterr_clear();
|
||||
|
||||
if ((error = git_config_get_bool(&remote->prune_refs, config, "fetch.prune")) < 0) {
|
||||
if (error == GIT_ENOTFOUND) {
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Move the data over to where the matching functions can find them */
|
||||
if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0)
|
||||
goto cleanup;
|
||||
@ -887,6 +904,7 @@ int git_remote_fetch(
|
||||
{
|
||||
int error;
|
||||
git_buf reflog_msg_buf = GIT_BUF_INIT;
|
||||
size_t i;
|
||||
|
||||
/* Connect and download everything */
|
||||
if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) != 0)
|
||||
@ -909,6 +927,9 @@ int git_remote_fetch(
|
||||
remote->name ? remote->name : remote->url);
|
||||
}
|
||||
|
||||
if (remote->prune_refs && (error = git_remote_prune(remote)) < 0)
|
||||
return error;
|
||||
|
||||
/* Create "remote/foo" branches for all remote branches */
|
||||
error = git_remote_update_tips(remote, signature, git_buf_cstr(&reflog_msg_buf));
|
||||
git_buf_free(&reflog_msg_buf);
|
||||
@ -1066,6 +1087,78 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_remote_prune(git_remote *remote)
|
||||
{
|
||||
git_strarray arr = { 0 };
|
||||
size_t i, j, k;
|
||||
git_vector remote_refs = GIT_VECTOR_INIT;
|
||||
git_refspec *spec;
|
||||
int error;
|
||||
|
||||
if ((error = git_reference_list(&arr, remote->repo)) < 0)
|
||||
return error;
|
||||
|
||||
if ((error = ls_to_vector(&remote_refs, remote)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
git_vector_foreach(&remote->active_refspecs, k, spec) {
|
||||
if (spec->push)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < arr.count; ++i) {
|
||||
char *prune_ref = arr.strings[i];
|
||||
int found = 0;
|
||||
git_remote_head *remote_ref;
|
||||
git_oid oid;
|
||||
git_reference *ref;
|
||||
|
||||
if (git_refspec_dst_matches(spec, prune_ref) != 1)
|
||||
continue;
|
||||
|
||||
git_vector_foreach(&remote_refs, j, remote_ref) {
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
if (git_refspec_transform(&buf, spec, remote_ref->name) < 0)
|
||||
continue;
|
||||
|
||||
if (!git__strcmp(prune_ref, git_buf_cstr(&buf))) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
if ((error = git_reference_lookup(&ref, remote->repo, prune_ref)) >= 0) {
|
||||
if (git_reference_type(ref) == GIT_REF_OID) {
|
||||
git_oid_cpy(&oid, git_reference_target(ref));
|
||||
if ((error = git_reference_delete(ref)) < 0) {
|
||||
git_reference_free(ref);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (remote->callbacks.update_tips != NULL) {
|
||||
git_oid zero_oid;
|
||||
|
||||
memset(&zero_oid, 0, sizeof(zero_oid));
|
||||
if (remote->callbacks.update_tips(prune_ref, &oid, &zero_oid, remote->callbacks.payload) < 0) {
|
||||
git_reference_free(ref);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
git_reference_free(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
git_strarray_free(&arr);
|
||||
git_vector_free(&remote_refs);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int update_tips_for_spec(
|
||||
git_remote *remote,
|
||||
git_refspec *spec,
|
||||
@ -1465,6 +1558,16 @@ void git_remote_set_autotag(git_remote *remote, git_remote_autotag_option_t valu
|
||||
remote->download_tags = value;
|
||||
}
|
||||
|
||||
int git_remote_prune_refs(const git_remote *remote)
|
||||
{
|
||||
return remote->prune_refs;
|
||||
}
|
||||
|
||||
void git_remote_set_prune_refs(git_remote *remote, int value)
|
||||
{
|
||||
remote->prune_refs = value;
|
||||
}
|
||||
|
||||
static int rename_remote_config_section(
|
||||
git_repository *repo,
|
||||
const char *old_name,
|
||||
|
||||
@ -33,6 +33,7 @@ struct git_remote {
|
||||
unsigned int need_pack;
|
||||
git_remote_autotag_option_t download_tags;
|
||||
int update_fetchhead;
|
||||
int prune_refs;
|
||||
int passed_refspecs;
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user