Skip to content

Commit 2a51679

Browse files
authored
Merge pull request libgit2#5659 from libgit2/ethomson/name_is_valid
Deprecate `is_valid_name` functions; replace with `name_is_valid` functions
2 parents 52294c4 + 8b0c7d7 commit 2a51679

File tree

20 files changed

+365
-105
lines changed

20 files changed

+365
-105
lines changed

docs/changelog.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
vNext
2+
-----
3+
4+
### Changes or improvements
5+
6+
* Branch and tag name validation functions have been introduced:
7+
`git_branch_name_is_valid` will check if a branch name is valid,
8+
and `git_tag_name_is_valid` will check if a tag name is valid.
9+
10+
* Some remote and reference validity checking functions have been
11+
introduced with error reporting semantics. `git_remote_name_is_valid`
12+
replaces `git_remote_is_valid_name`. `git_reference_name_is_valid`
13+
replaces `git_reference_is_valid_name`. Tthe former functions are
14+
deprecated.
15+
116
v1.1
217
----
318

include/git2/branch.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,18 @@ GIT_EXTERN(int) git_branch_remote_name(
304304
*/
305305
GIT_EXTERN(int) git_branch_upstream_remote(git_buf *buf, git_repository *repo, const char *refname);
306306

307+
/**
308+
* Determine whether a branch name is valid, meaning that (when prefixed
309+
* with `refs/heads/`) that it is a valid reference name, and that any
310+
* additional branch name restrictions are imposed (eg, it cannot start
311+
* with a `-`).
312+
*
313+
* @param valid output pointer to set with validity of given branch name
314+
* @param name a branch name to test
315+
* @return 0 on success or an error code
316+
*/
317+
GIT_EXTERN(int) git_branch_name_is_valid(int *valid, const char *name);
318+
307319
/** @} */
308320
GIT_END_DECL
309321
#endif

include/git2/deprecated.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,32 @@ GIT_EXTERN(size_t) git_object__size(git_object_t type);
340340

341341
/**@}*/
342342

343-
/** @name Deprecated Reference Constants
343+
/** @name Deprecated Remote Functions
344344
*
345-
* These enumeration values are retained for backward compatibility. The
346-
* newer versions of these values should be preferred in all new code.
345+
* These functions are retained for backward compatibility. The newer
346+
* versions of these functions should be preferred in all new code.
347+
*
348+
* There is no plan to remove these backward compatibility functions at
349+
* this time.
350+
*/
351+
/**@{*/
352+
353+
/**
354+
* Ensure the remote name is well-formed.
355+
*
356+
* @deprecated Use git_remote_name_is_valid
357+
* @param remote_name name to be checked.
358+
* @return 1 if the reference name is acceptable; 0 if it isn't
359+
*/
360+
GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name);
361+
362+
/**@}*/
363+
364+
/** @name Deprecated Reference Functions and Constants
365+
*
366+
* These functions and enumeration values are retained for backward
367+
* compatibility. The newer versions of these values should be
368+
* preferred in all new code.
347369
*
348370
* There is no plan to remove these backward compatibility values at
349371
* this time.
@@ -364,6 +386,23 @@ GIT_EXTERN(size_t) git_object__size(git_object_t type);
364386
#define GIT_REF_FORMAT_REFSPEC_PATTERN GIT_REFERENCE_FORMAT_REFSPEC_PATTERN
365387
#define GIT_REF_FORMAT_REFSPEC_SHORTHAND GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND
366388

389+
/**
390+
* Ensure the reference name is well-formed.
391+
*
392+
* Valid reference names must follow one of two patterns:
393+
*
394+
* 1. Top-level names must contain only capital letters and underscores,
395+
* and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD").
396+
* 2. Names prefixed with "refs/" can be almost anything. You must avoid
397+
* the characters '~', '^', ':', '\\', '?', '[', and '*', and the
398+
* sequences ".." and "@{" which have special meaning to revparse.
399+
*
400+
* @deprecated Use git_reference_name_is_valid
401+
* @param refname name to be checked.
402+
* @return 1 if the reference name is acceptable; 0 if it isn't
403+
*/
404+
GIT_EXTERN(int) git_reference_is_valid_name(const char *refname);
405+
367406
GIT_EXTERN(int) git_tag_create_frombuffer(
368407
git_oid *oid,
369408
git_repository *repo,

include/git2/refs.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -743,10 +743,11 @@ GIT_EXTERN(int) git_reference_peel(
743743
* the characters '~', '^', ':', '\\', '?', '[', and '*', and the
744744
* sequences ".." and "@{" which have special meaning to revparse.
745745
*
746+
* @param valid output pointer to set with validity of given reference name
746747
* @param refname name to be checked.
747-
* @return 1 if the reference name is acceptable; 0 if it isn't
748+
* @return 0 on success or an error code
748749
*/
749-
GIT_EXTERN(int) git_reference_is_valid_name(const char *refname);
750+
GIT_EXTERN(int) git_reference_name_is_valid(int *valid, const char *refname);
750751

751752
/**
752753
* Get the reference's short name

include/git2/remote.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -915,10 +915,11 @@ GIT_EXTERN(int) git_remote_rename(
915915
/**
916916
* Ensure the remote name is well-formed.
917917
*
918+
* @param valid output pointer to set with validity of given remote name
918919
* @param remote_name name to be checked.
919-
* @return 1 if the reference name is acceptable; 0 if it isn't
920+
* @return 0 on success or an error code
920921
*/
921-
GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name);
922+
int git_remote_name_is_valid(int *valid, const char *remote_name);
922923

923924
/**
924925
* Delete an existing persisted remote.

include/git2/tag.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,18 @@ GIT_EXTERN(int) git_tag_peel(
365365
*/
366366
GIT_EXTERN(int) git_tag_dup(git_tag **out, git_tag *source);
367367

368+
/**
369+
* Determine whether a tag name is valid, meaning that (when prefixed
370+
* with `refs/tags/`) that it is a valid reference name, and that any
371+
* additional tag name restrictions are imposed (eg, it cannot start
372+
* with a `-`).
373+
*
374+
* @param valid output pointer to set with validity of given tag name
375+
* @param name a tag name to test
376+
* @return 0 on success or an error code
377+
*/
378+
GIT_EXTERN(int) git_tag_name_is_valid(int *valid, const char *name);
379+
368380
/** @} */
369381
GIT_END_DECL
370382
#endif

src/branch.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,3 +723,32 @@ int git_branch_is_head(
723723

724724
return is_same;
725725
}
726+
727+
int git_branch_name_is_valid(int *valid, const char *name)
728+
{
729+
git_buf ref_name = GIT_BUF_INIT;
730+
int error = 0;
731+
732+
GIT_ASSERT(valid);
733+
734+
*valid = 0;
735+
736+
/*
737+
* Discourage branch name starting with dash,
738+
* https://github.com/git/git/commit/6348624010888b
739+
* and discourage HEAD as branch name,
740+
* https://github.com/git/git/commit/a625b092cc5994
741+
*/
742+
if (!name || name[0] == '-' || !git__strcmp(name, "HEAD"))
743+
goto done;
744+
745+
if ((error = git_buf_puts(&ref_name, GIT_REFS_HEADS_DIR)) < 0 ||
746+
(error = git_buf_puts(&ref_name, name)) < 0)
747+
goto done;
748+
749+
error = git_reference_name_is_valid(valid, ref_name.ptr);
750+
751+
done:
752+
git_buf_dispose(&ref_name);
753+
return error;
754+
}

src/fetch.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@
2121

2222
static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, git_refspec *tagspec, git_remote_autotag_option_t tagopt)
2323
{
24-
int match = 0;
24+
int match = 0, valid;
2525

26-
if (!git_reference_is_valid_name(head->name))
26+
if (git_reference_name_is_valid(&valid, head->name) < 0)
27+
return -1;
28+
29+
if (!valid)
2730
return 0;
2831

2932
if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {

src/refs.c

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ int git_reference_lookup_resolved(
239239

240240
int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname)
241241
{
242-
int error = 0, i;
242+
int error = 0, i, valid;
243243
bool fallbackmode = true, foundvalid = false;
244244
git_reference *ref;
245245
git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
@@ -265,10 +265,11 @@ int git_reference_dwim(git_reference **out, git_repository *repo, const char *re
265265

266266
git_buf_clear(&refnamebuf);
267267

268-
if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0)
268+
if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0 ||
269+
(error = git_reference_name_is_valid(&valid, git_buf_cstr(&refnamebuf))) < 0)
269270
goto cleanup;
270271

271-
if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) {
272+
if (!valid) {
272273
error = GIT_EINVALIDSPEC;
273274
continue;
274275
}
@@ -1287,19 +1288,30 @@ int git_reference_peel(
12871288
return error;
12881289
}
12891290

1290-
int git_reference__is_valid_name(const char *refname, unsigned int flags)
1291+
int git_reference__name_is_valid(
1292+
int *valid,
1293+
const char *refname,
1294+
unsigned int flags)
12911295
{
1292-
if (git_reference__normalize_name(NULL, refname, flags) < 0) {
1293-
git_error_clear();
1294-
return false;
1295-
}
1296+
int error;
12961297

1297-
return true;
1298+
GIT_ASSERT(valid && refname);
1299+
1300+
*valid = 0;
1301+
1302+
error = git_reference__normalize_name(NULL, refname, flags);
1303+
1304+
if (!error)
1305+
*valid = 1;
1306+
else if (error == GIT_EINVALIDSPEC)
1307+
error = 0;
1308+
1309+
return error;
12981310
}
12991311

1300-
int git_reference_is_valid_name(const char *refname)
1312+
int git_reference_name_is_valid(int *valid, const char *refname)
13011313
{
1302-
return git_reference__is_valid_name(refname, GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL);
1314+
return git_reference__name_is_valid(valid, refname, GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL);
13031315
}
13041316

13051317
const char *git_reference__shorthand(const char *name)
@@ -1345,3 +1357,18 @@ int git_reference__is_unborn_head(bool *unborn, const git_reference *ref, git_re
13451357

13461358
return 0;
13471359
}
1360+
1361+
/* Deprecated functions */
1362+
1363+
#ifndef GIT_DEPRECATE_HARD
1364+
1365+
int git_reference_is_valid_name(const char *refname)
1366+
{
1367+
int valid = 0;
1368+
1369+
git_reference__name_is_valid(&valid, refname, GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL);
1370+
1371+
return valid;
1372+
}
1373+
1374+
#endif

src/refs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ git_reference *git_reference__realloc(git_reference **ptr_to_ref, const char *na
8585

8686
int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int flags);
8787
int git_reference__update_terminal(git_repository *repo, const char *ref_name, const git_oid *oid, const git_signature *sig, const char *log_message);
88-
int git_reference__is_valid_name(const char *refname, unsigned int flags);
88+
int git_reference__name_is_valid(int *valid, const char *name, unsigned int flags);
8989
int git_reference__is_branch(const char *ref_name);
9090
int git_reference__is_remote(const char *ref_name);
9191
int git_reference__is_tag(const char *ref_name);

0 commit comments

Comments
 (0)