Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
aa2120e9
Commit
aa2120e9
authored
Feb 10, 2011
by
nulltoken
Committed by
Vicent Marti
Mar 03, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added git_reference__normalize_name() along with tests.
parent
83403e99
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
165 additions
and
4 deletions
+165
-4
src/common.h
+1
-0
src/git2/types.h
+1
-0
src/refs.c
+100
-4
src/refs.h
+2
-0
tests/t10-refs.c
+61
-0
No files found.
src/common.h
View file @
aa2120e9
...
...
@@ -53,5 +53,6 @@ typedef SSIZE_T ssize_t;
#include "bswap.h"
#define GIT_PATH_MAX 4096
#define GIT_FILELOCK_EXTENSION ".lock\0"
#endif
/* INCLUDE_common_h__ */
src/git2/types.h
View file @
aa2120e9
...
...
@@ -140,6 +140,7 @@ typedef struct git_reference git_reference;
/** Basic type of any Git reference. */
typedef
enum
{
GIT_REF_ANY
=
-
2
,
/** Reference can be an object id reference or a symbolic reference */
GIT_REF_INVALID
=
-
1
,
/** Invalid reference */
GIT_REF_OID
=
1
,
/** A reference which points at an object id */
GIT_REF_SYMBOLIC
=
2
,
/** A reference which points at another reference */
...
...
src/refs.c
View file @
aa2120e9
...
...
@@ -571,12 +571,13 @@ error_cleanup:
int
git_repository_lookup_ref
(
git_reference
**
ref_out
,
git_repository
*
repo
,
const
char
*
name
)
{
int
error
;
char
normalized_name
[
GIT_PATH_MAX
];
assert
(
ref_out
&&
repo
&&
name
);
*
ref_out
=
NULL
;
error
=
check_refname
(
name
);
error
=
git_reference__normalize_name
(
normalized_name
,
name
,
GIT_REF_ANY
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
...
...
@@ -584,7 +585,7 @@ int git_repository_lookup_ref(git_reference **ref_out, git_repository *repo, con
* First, check if the reference is on the local cache;
* references on the cache are assured to be up-to-date
*/
*
ref_out
=
git_hashtable_lookup
(
repo
->
references
.
cache
,
name
);
*
ref_out
=
git_hashtable_lookup
(
repo
->
references
.
cache
,
n
ormalized_n
ame
);
if
(
*
ref_out
!=
NULL
)
return
GIT_SUCCESS
;
...
...
@@ -593,7 +594,7 @@ int git_repository_lookup_ref(git_reference **ref_out, git_repository *repo, con
* If the file exists, we parse it and store it on the
* cache.
*/
error
=
lookup_loose_ref
(
ref_out
,
repo
,
name
);
error
=
lookup_loose_ref
(
ref_out
,
repo
,
n
ormalized_n
ame
);
if
(
error
==
GIT_SUCCESS
)
return
GIT_SUCCESS
;
...
...
@@ -618,7 +619,7 @@ int git_repository_lookup_ref(git_reference **ref_out, git_repository *repo, con
return
error
;
/* check the cache again -- hopefully the reference will be there */
*
ref_out
=
git_hashtable_lookup
(
repo
->
references
.
cache
,
name
);
*
ref_out
=
git_hashtable_lookup
(
repo
->
references
.
cache
,
n
ormalized_n
ame
);
if
(
*
ref_out
!=
NULL
)
return
GIT_SUCCESS
;
}
...
...
@@ -653,4 +654,99 @@ void git_repository__refcache_free(git_refcache *refs)
git_hashtable_free
(
refs
->
cache
);
}
static
int
check_valid_ref_char
(
char
ch
)
{
if
(
ch
<=
' '
)
return
GIT_ERROR
;
switch
(
ch
)
{
case
'~'
:
case
'^'
:
case
':'
:
case
'\\'
:
case
'?'
:
case
'['
:
return
GIT_ERROR
;
break
;
default:
return
GIT_SUCCESS
;
}
}
int
git_reference__normalize_name
(
char
*
buffer_out
,
const
char
*
name
,
git_rtype
type
)
{
int
error
=
GIT_SUCCESS
;
const
char
*
name_end
,
*
buffer_out_start
;
char
*
current
;
int
contains_a_slash
=
0
;
assert
(
name
&&
buffer_out
);
buffer_out_start
=
buffer_out
;
current
=
(
char
*
)
name
;
name_end
=
name
+
strlen
(
name
);
if
(
type
==
GIT_REF_INVALID
)
return
GIT_EINVALIDTYPE
;
/* A refname can not be empty */
if
(
name_end
==
name
)
return
GIT_EINVALIDREFNAME
;
/* A refname can not end with a dot or a slash */
if
(
*
(
name_end
-
1
)
==
'.'
||
*
(
name_end
-
1
)
==
'/'
)
return
GIT_EINVALIDREFNAME
;
while
(
current
<
name_end
)
{
if
(
check_valid_ref_char
(
*
current
))
return
GIT_EINVALIDREFNAME
;
if
(
buffer_out
>
buffer_out_start
)
{
char
prev
=
*
(
buffer_out
-
1
);
/* A refname can not start with a dot nor contain a double dot */
if
(
*
current
==
'.'
&&
((
prev
==
'.'
)
||
(
prev
==
'/'
)))
return
GIT_EINVALIDREFNAME
;
/* '@{' is forbidden within a refname */
if
(
*
current
==
'{'
&&
prev
==
'@'
)
return
GIT_EINVALIDREFNAME
;
/* Prevent multiple slashes from being added to the output */
if
(
*
current
==
'/'
&&
prev
==
'/'
)
{
current
++
;
continue
;
}
}
if
(
*
current
==
'/'
)
{
/* Slashes are not authorized in symbolic reference name */
if
(
type
==
GIT_REF_SYMBOLIC
)
{
return
GIT_EINVALIDREFNAME
;
}
contains_a_slash
=
1
;
}
*
buffer_out
++
=
*
current
++
;
}
/* Object id refname have to contain at least one slash */
if
(
type
==
GIT_REF_OID
&&
!
contains_a_slash
)
return
GIT_EINVALIDREFNAME
;
/* A refname can not end with ".lock" */
if
(
!
git__suffixcmp
(
name
,
GIT_FILELOCK_EXTENSION
))
return
GIT_EINVALIDREFNAME
;
*
buffer_out
=
'\0'
;
/* For object id references, name has to start with refs/(heads|tags|remotes) */
if
(
type
==
GIT_REF_OID
&&
!
(
!
git__prefixcmp
(
buffer_out_start
,
GIT_REFS_HEADS_DIR
)
||
!
git__prefixcmp
(
buffer_out_start
,
GIT_REFS_TAGS_DIR
)
||
!
git__prefixcmp
(
buffer_out_start
,
GIT_REFS_REMOTES_DIR
)))
return
GIT_EINVALIDREFNAME
;
return
error
;
}
src/refs.h
View file @
aa2120e9
...
...
@@ -9,6 +9,7 @@
#define GIT_REFS_DIR "refs/"
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
#define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/"
#define GIT_REFS_REMOTES_DIR GIT_REFS_DIR "remotes/"
#define GIT_SYMREF "ref: "
#define GIT_PACKEDREFS_FILE "packed-refs"
...
...
@@ -37,5 +38,6 @@ typedef struct {
void
git_repository__refcache_free
(
git_refcache
*
refs
);
int
git_repository__refcache_init
(
git_refcache
*
refs
);
int
git_reference__normalize_name
(
char
*
buffer_out
,
const
char
*
name
,
git_rtype
type
);
#endif
tests/t10-refs.c
View file @
aa2120e9
...
...
@@ -279,6 +279,63 @@ BEGIN_TEST("createref", create_new_object_id_ref)
must_pass
(
gitfo_unlink
(
ref_path
));
/* TODO: replace with git_reference_delete() when available */
END_TEST
static
int
ensure_refname_normalized
(
git_rtype
ref_type
,
const
char
*
input_refname
,
const
char
*
expected_refname
)
{
int
error
=
GIT_SUCCESS
;
char
buffer_out
[
GIT_PATH_MAX
];
error
=
git_reference__normalize_name
(
buffer_out
,
input_refname
,
ref_type
);
if
(
error
<
GIT_SUCCESS
)
return
error
;
if
(
expected_refname
==
NULL
)
return
error
;
if
(
strcmp
(
buffer_out
,
expected_refname
))
error
=
GIT_ERROR
;
return
error
;
}
BEGIN_TEST
(
"normalizeref"
,
normalize_unknown_ref_type
)
must_fail
(
ensure_refname_normalized
(
GIT_REF_INVALID
,
"a"
,
NULL
));
END_TEST
BEGIN_TEST
(
"normalizeref"
,
normalize_object_id_ref
)
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"a"
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
""
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/a/"
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/a."
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/a.lock"
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/dummy/a"
,
NULL
));
must_pass
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/tags/a"
,
"refs/tags/a"
));
must_pass
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/a/b"
,
"refs/heads/a/b"
));
must_pass
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/a./b"
,
"refs/heads/a./b"
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/foo?bar"
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads
\f
oo"
,
NULL
));
must_pass
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/v@ation"
,
"refs/heads/v@ation"
));
must_pass
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs///heads///a"
,
"refs/heads/a"
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/.a/b"
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/foo/../bar"
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/foo..bar"
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/./foo"
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_OID
,
"refs/heads/v@{ation"
,
NULL
));
END_TEST
BEGIN_TEST
(
"normalizeref"
,
normalize_symbolic_ref
)
must_pass
(
ensure_refname_normalized
(
GIT_REF_SYMBOLIC
,
"a"
,
"a"
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_SYMBOLIC
,
""
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_SYMBOLIC
,
"a/b"
,
NULL
));
must_fail
(
ensure_refname_normalized
(
GIT_REF_SYMBOLIC
,
"heads
\f
oo"
,
NULL
));
END_TEST
BEGIN_TEST
(
"normalizeref"
,
normalize_any_ref
)
/* Slash related rules do not apply, neither do 'refs' prefix related rules */
must_pass
(
ensure_refname_normalized
(
GIT_REF_ANY
,
"a"
,
"a"
));
must_pass
(
ensure_refname_normalized
(
GIT_REF_ANY
,
"a/b"
,
"a/b"
));
must_pass
(
ensure_refname_normalized
(
GIT_REF_ANY
,
"refs///heads///a"
,
"refs/heads/a"
));
END_TEST
git_testsuite
*
libgit2_suite_refs
(
void
)
{
git_testsuite
*
suite
=
git_testsuite_new
(
"References"
);
...
...
@@ -293,6 +350,10 @@ git_testsuite *libgit2_suite_refs(void)
ADD_TEST
(
suite
,
"readpackedref"
,
packed_exists_but_more_recent_loose_reference_is_retrieved
);
ADD_TEST
(
suite
,
"createref"
,
create_new_symbolic_ref
);
ADD_TEST
(
suite
,
"createref"
,
create_new_object_id_ref
);
ADD_TEST
(
suite
,
"normalizeref"
,
normalize_unknown_ref_type
);
ADD_TEST
(
suite
,
"normalizeref"
,
normalize_object_id_ref
);
ADD_TEST
(
suite
,
"normalizeref"
,
normalize_symbolic_ref
);
ADD_TEST
(
suite
,
"normalizeref"
,
normalize_any_ref
);
return
suite
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment