refs.c: allow listing and deleting badly named refs
We currently do not handle badly named refs well: $ cp .git/refs/heads/master .git/refs/heads/master.....@\*@\\. $ git branch fatal: Reference has invalid format: 'refs/heads/master.....@*@\.' $ git branch -D master.....@\*@\\. error: branch 'master.....@*@\.' not found. Users cannot recover from a badly named ref without manually finding and deleting the loose ref file or appropriate line in packed-refs. Making that easier will make it easier to tweak the ref naming rules in the future, for example to forbid shell metacharacters like '`' and '"', without putting people in a state that is hard to get out of. So allow "branch --list" to show these refs and allow "branch -d/-D" and "update-ref -d" to delete them. Other commands (for example to rename refs) will continue to not handle these refs but can be changed in later patches. Details: In resolving functions, refuse to resolve refs that don't pass the git-check-ref-format(1) check unless the new RESOLVE_REF_ALLOW_BAD_NAME flag is passed. Even with RESOLVE_REF_ALLOW_BAD_NAME, refuse to resolve refs that escape the refs/ directory and do not match the pattern [A-Z_]* (think "HEAD" and "MERGE_HEAD"). In locking functions, refuse to act on badly named refs unless they are being deleted and either are in the refs/ directory or match [A-Z_]*. Just like other invalid refs, flag resolved, badly named refs with the REF_ISBROKEN flag, treat them as resolving to null_sha1, and skip them in all iteration functions except for for_each_rawref. Flag badly named refs (but not symrefs pointing to badly named refs) with a REF_BAD_NAME flag to make it easier for future callers to notice and handle them specially. For example, in a later patch for-each-ref will use this flag to detect refs whose names can confuse callers parsing for-each-ref output. In the transaction API, refuse to create or update badly named refs, but allow deleting them (unless they try to escape refs/ and don't match [A-Z_]*). Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
8159f4af7d
commit
d0f810f0bc
17
cache.h
17
cache.h
@ -981,16 +981,29 @@ extern int read_ref(const char *refname, unsigned char *sha1);
|
||||
* If flags is non-NULL, set the value that it points to the
|
||||
* combination of REF_ISPACKED (if the reference was found among the
|
||||
* packed references), REF_ISSYMREF (if the initial reference was a
|
||||
* symbolic reference) and REF_ISBROKEN (if the ref is malformed).
|
||||
* symbolic reference), REF_BAD_NAME (if the reference name is ill
|
||||
* formed --- see RESOLVE_REF_ALLOW_BAD_NAME below), and REF_ISBROKEN
|
||||
* (if the ref is malformed or has a bad name). See refs.h for more detail
|
||||
* on each flag.
|
||||
*
|
||||
* If ref is not a properly-formatted, normalized reference, return
|
||||
* NULL. If more than MAXDEPTH recursive symbolic lookups are needed,
|
||||
* give up and return NULL.
|
||||
*
|
||||
* errno is set to something meaningful on error.
|
||||
* RESOLVE_REF_ALLOW_BAD_NAME allows resolving refs even when their
|
||||
* name is invalid according to git-check-ref-format(1). If the name
|
||||
* is bad then the value stored in sha1 will be null_sha1 and the two
|
||||
* flags REF_ISBROKEN and REF_BAD_NAME will be set.
|
||||
*
|
||||
* Even with RESOLVE_REF_ALLOW_BAD_NAME, names that escape the refs/
|
||||
* directory and do not consist of all caps and underscores cannot be
|
||||
* resolved. The function returns NULL for such ref names.
|
||||
* Caps and underscores refers to the special refs, such as HEAD,
|
||||
* FETCH_HEAD and friends, that all live outside of the refs/ directory.
|
||||
*/
|
||||
#define RESOLVE_REF_READING 0x01
|
||||
#define RESOLVE_REF_NO_RECURSE 0x02
|
||||
#define RESOLVE_REF_ALLOW_BAD_NAME 0x04
|
||||
extern const char *resolve_ref_unsafe(const char *ref, int resolve_flags, unsigned char *sha1, int *flags);
|
||||
extern char *resolve_refdup(const char *ref, int resolve_flags, unsigned char *sha1, int *flags);
|
||||
|
||||
|
Reference in New Issue
Block a user