refs: expose function to parse reference URIs

In the next commit we're about to add more sites that want to parse a
reference backends URI into a format and payload. Expose a new function
`ref_storage_format_by_uri()` that enables this.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
next
Patrick Steinhardt 2026-09-09 13:12:54 +02:00 committed by Junio C Hamano
parent 022e59bc6b
commit 0af0e959c8
3 changed files with 39 additions and 36 deletions

23
refs.c
View File

@ -54,6 +54,29 @@ enum ref_storage_format ref_storage_format_by_name(const char *name)
return REF_STORAGE_FORMAT_UNKNOWN;
}

enum ref_storage_format ref_storage_format_by_uri(const char *uri,
char **payload)
{
enum ref_storage_format format;
const char *schema_end;
char *name;

schema_end = strstr(uri, "://");
if (!schema_end) {
name = xstrdup(uri);
if (payload)
*payload = NULL;
} else {
name = xstrndup(uri, schema_end - uri);
if (payload)
*payload = xstrdup(schema_end + 3);
}

format = ref_storage_format_by_name(name);
free(name);
return format;
}

const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_format)
{
const struct ref_storage_be *be = find_ref_storage_backend(ref_storage_format);

4
refs.h
View File

@ -17,6 +17,10 @@ struct worktree;
enum ref_storage_format ref_storage_format_by_name(const char *name);
const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_format);

/* Parse a reference storage URI in the format "<format>[://<payload>]". */
enum ref_storage_format ref_storage_format_by_uri(const char *uri,
char **payload);

enum ref_transaction_error {
/* Default error code */
REF_TRANSACTION_ERROR_GENERIC = -1,

48
setup.c
View File

@ -632,21 +632,6 @@ static enum extension_result handle_extension_v0(const char *var,
return EXTENSION_UNKNOWN;
}

static void parse_reference_uri(const char *value, char **format,
char **payload)
{
const char *schema_end;

schema_end = strstr(value, "://");
if (!schema_end) {
*format = xstrdup(value);
*payload = NULL;
} else {
*format = xstrndup(value, schema_end - value);
*payload = xstrdup_or_null(schema_end + 3);
}
}

/*
* Record any new extensions in this function.
*/
@ -689,16 +674,13 @@ static enum extension_result handle_extension(const char *var,
return EXTENSION_OK;
} else if (!strcmp(ext, "refstorage")) {
unsigned int format;
char *format_str;

if (!value)
return config_error_nonbool(var);

parse_reference_uri(value, &format_str,
&data->ref_storage_payload);

format = ref_storage_format_by_name(format_str);
free(format_str);
FREE_AND_NULL(data->ref_storage_payload);
format = ref_storage_format_by_uri(value,
&data->ref_storage_payload);

if (format == REF_STORAGE_FORMAT_UNKNOWN)
return error(_("invalid value for '%s': '%s'"),
@ -2069,16 +2051,12 @@ const char *setup_git_directory_gently(struct repository *repo, int *nongit_ok)
*/
ref_backend_uri = getenv(GIT_REFERENCE_BACKEND_ENVIRONMENT);
if (ref_backend_uri) {
char *format;

free(discovery.format.ref_storage_payload);

parse_reference_uri(ref_backend_uri, &format, &discovery.format.ref_storage_payload);
discovery.format.ref_storage_format = ref_storage_format_by_name(format);
FREE_AND_NULL(discovery.format.ref_storage_payload);
discovery.format.ref_storage_format =
ref_storage_format_by_uri(ref_backend_uri,
&discovery.format.ref_storage_payload);
if (discovery.format.ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
die(_("unknown ref storage format: '%s'"), format);

free(format);
die(_("unknown ref storage format: '%s'"), ref_backend_uri);
}

if (apply_repository_format(repo, &discovery.format,
@ -2806,18 +2784,16 @@ static void repository_format_configure(struct repository_format *repo_fmt,

ref_backend_uri = getenv(GIT_REFERENCE_BACKEND_ENVIRONMENT);
if (ref_backend_uri) {
char *backend, *payload;
enum ref_storage_format format;
char *payload;

parse_reference_uri(ref_backend_uri, &backend, &payload);
format = ref_storage_format_by_name(backend);
format = ref_storage_format_by_uri(ref_backend_uri, &payload);
if (format == REF_STORAGE_FORMAT_UNKNOWN)
die(_("unknown ref storage format: '%s'"), backend);
die(_("unknown ref storage format: '%s'"), ref_backend_uri);

repo_fmt->ref_storage_format = format;
free(repo_fmt->ref_storage_payload);
repo_fmt->ref_storage_payload = payload;

free(backend);
}
}