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
c030ada7
Commit
c030ada7
authored
Sep 11, 2012
by
nulltoken
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refs: make git_reference_normalize_name() accept refspec pattern
parent
d75074f4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
176 additions
and
79 deletions
+176
-79
include/git2/refs.h
+0
-2
src/refs.c
+114
-72
src/refs.h
+3
-1
tests-clar/refs/normalize.c
+59
-4
No files found.
include/git2/refs.h
View file @
c030ada7
...
...
@@ -414,8 +414,6 @@ enum {
* Once normalized, if the reference name is valid, it will be
* returned in the user allocated buffer.
*
* TODO: Implement handling of GIT_REF_FORMAT_REFSPEC_PATTERN
*
* @param buffer_out The user allocated buffer where the
* normalized name will be stored.
*
...
...
src/refs.c
View file @
c030ada7
...
...
@@ -1098,7 +1098,7 @@ int git_reference_lookup_resolved(
scan
->
name
=
git__calloc
(
GIT_REFNAME_MAX
+
1
,
sizeof
(
char
));
GITERR_CHECK_ALLOC
(
scan
->
name
);
if
((
result
=
git_reference__normalize_name
(
if
((
result
=
git_reference__normalize_name
_lax
(
scan
->
name
,
GIT_REFNAME_MAX
,
name
))
<
0
)
{
...
...
@@ -1200,7 +1200,7 @@ int git_reference_create_symbolic(
char
normalized
[
GIT_REFNAME_MAX
];
git_reference
*
ref
=
NULL
;
if
(
git_reference__normalize_name
(
if
(
git_reference__normalize_name
_lax
(
normalized
,
sizeof
(
normalized
),
name
)
<
0
)
...
...
@@ -1322,7 +1322,7 @@ int git_reference_set_target(git_reference *ref, const char *target)
return
-
1
;
}
if
(
git_reference__normalize_name
(
if
(
git_reference__normalize_name
_lax
(
normalized
,
sizeof
(
normalized
),
target
))
...
...
@@ -1584,106 +1584,148 @@ static int is_valid_ref_char(char ch)
}
}
int
git_reference_normalize_name
(
char
*
buffer_out
,
size_t
buffer_size
,
const
char
*
name
,
unsigned
int
flags
)
static
int
ensure_segment_validity
(
const
char
*
name
)
{
const
char
*
name_end
,
*
buffer_out_start
;
const
char
*
current
;
int
contains_a_slash
=
0
;
const
char
*
current
=
name
;
char
prev
=
'\0'
;
assert
(
name
&&
buffer_out
);
if
(
*
current
==
'.'
)
return
-
1
;
/* Refname starts with "." */
if
(
flags
&
GIT_REF_FORMAT_REFSPEC_PATTERN
)
{
giterr_set
(
GITERR_INVALID
,
"Unimplemented"
);
return
-
1
;
}
for
(
current
=
name
;
;
current
++
)
{
if
(
*
current
==
'\0'
||
*
current
==
'/'
)
break
;
buffer_out_start
=
buffer_out
;
current
=
name
;
name_end
=
name
+
strlen
(
name
);
if
(
!
is_valid_ref_char
(
*
current
))
return
-
1
;
/* Illegal character in refname */
/* Terminating null byte */
buffer_size
--
;
if
(
prev
==
'.'
&&
*
current
==
'.'
)
return
-
1
;
/* Refname contains ".." */
/* A refname can not be empty */
if
(
name_end
==
name
)
goto
invalid_name
;
if
(
prev
==
'@'
&&
*
current
==
'{'
)
return
-
1
;
/* Refname contains "@{" */
/* A refname can not end with a dot or a slash */
if
(
*
(
name_end
-
1
)
==
'.'
||
*
(
name_end
-
1
)
==
'/'
)
goto
invalid_name
;
prev
=
*
current
;
}
while
(
current
<
name_end
&&
buffer_size
>
0
)
{
if
(
!
is_valid_ref_char
(
*
current
))
goto
invalid_name
;
return
current
-
name
;
}
int
git_reference__normalize_name
(
git_buf
*
buf
,
const
char
*
name
,
unsigned
int
flags
)
{
// Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100
if
(
buffer_out
>
buffer_out_start
)
{
char
prev
=
*
(
buffer_out
-
1
);
char
*
current
;
int
segment_len
,
segments_count
=
0
,
error
=
-
1
;
assert
(
name
&&
buf
);
current
=
(
char
*
)
name
;
git_buf_clear
(
buf
);
while
(
true
)
{
segment_len
=
ensure_segment_validity
(
current
);
if
(
segment_len
<
0
)
{
if
((
flags
&
GIT_REF_FORMAT_REFSPEC_PATTERN
)
&&
current
[
0
]
==
'*'
&&
(
current
[
1
]
==
'\0'
||
current
[
1
]
==
'/'
))
{
/* Accept one wildcard as a full refname component. */
flags
&=
~
GIT_REF_FORMAT_REFSPEC_PATTERN
;
segment_len
=
1
;
}
else
goto
cleanup
;
}
/* A refname can not start with a dot nor contain a double dot */
if
(
*
current
==
'.'
&&
((
prev
==
'.'
)
||
(
prev
==
'/'
)))
goto
invalid_name
;
if
(
segment_len
>
0
)
{
int
cur_len
=
git_buf_len
(
buf
);
/* '@{' is forbidden within a refname */
if
(
*
current
==
'{'
&&
prev
==
'@'
)
goto
invalid_name
;
git_buf_joinpath
(
buf
,
git_buf_cstr
(
buf
),
current
);
git_buf_truncate
(
buf
,
cur_len
+
segment_len
+
(
segments_count
?
1
:
0
))
;
/* Prevent multiple slashes from being added to the output */
if
(
*
current
==
'/'
&&
prev
==
'/'
)
{
current
++
;
continue
;
}
}
segments_count
++
;
if
(
*
current
==
'/'
)
{
if
(
buffer_out
>
buffer_out_start
)
contains_a_slash
=
1
;
else
{
current
++
;
continue
;
}
if
(
git_buf_oom
(
buf
))
goto
cleanup
;
}
*
buffer_out
++
=
*
current
++
;
buffer_size
--
;
}
if
(
current
[
segment_len
]
==
'\0'
)
break
;
if
(
current
<
name_end
)
{
giterr_set
(
GITERR_REFERENCE
,
"The provided buffer is too short to hold the normalization of '%s'"
,
name
);
return
GIT_EBUFS
;
current
+=
segment_len
+
1
;
}
/* A refname can not be empty */
if
(
git_buf_len
(
buf
)
==
0
)
goto
cleanup
;
/* A refname can not end with "." */
if
(
current
[
segment_len
-
1
]
==
'.'
)
goto
cleanup
;
/* A refname can not end with "/" */
if
(
current
[
segment_len
-
1
]
==
'/'
)
goto
cleanup
;
/* A refname can not end with ".lock" */
if
(
!
git__suffixcmp
(
name
,
GIT_FILELOCK_EXTENSION
))
goto
cleanup
;
/* Object id refname have to contain at least one slash, except
* for HEAD in a detached state or MERGE_HEAD if we're in the
* middle of a merge */
if
(
!
(
flags
&
GIT_REF_FORMAT_ALLOW_ONELEVEL
)
&&
!
contains_a_slash
&&
if
(
!
(
flags
&
GIT_REF_FORMAT_ALLOW_ONELEVEL
)
&&
segments_count
<
2
&&
strcmp
(
name
,
GIT_HEAD_FILE
)
!=
0
&&
strcmp
(
name
,
GIT_MERGE_HEAD_FILE
)
!=
0
&&
strcmp
(
name
,
GIT_FETCH_HEAD_FILE
)
!=
0
)
goto
invalid_name
;
return
-
1
;
/* A refname can not end with ".lock" */
if
(
!
git__suffixcmp
(
name
,
GIT_FILELOCK_EXTENSION
))
goto
invalid_name
;
error
=
0
;
*
buffer_out
=
'\0'
;
cleanup:
if
(
error
)
giterr_set
(
GITERR_REFERENCE
,
"The given reference name '%s' is not valid"
,
name
);
return
0
;
return
error
;
}
invalid_name:
giterr_set
(
int
git_reference_normalize_name
(
char
*
buffer_out
,
size_t
buffer_size
,
const
char
*
name
,
unsigned
int
flags
)
{
git_buf
buf
=
GIT_BUF_INIT
;
int
error
;
if
((
error
=
git_reference__normalize_name
(
&
buf
,
name
,
flags
))
<
0
)
goto
cleanup
;
if
(
git_buf_len
(
&
buf
)
>
buffer_size
-
1
)
{
giterr_set
(
GITERR_REFERENCE
,
"The given reference name '%s' is not valid"
,
name
);
return
-
1
;
"The provided buffer is too short to hold the normalization of '%s'"
,
name
);
error
=
GIT_EBUFS
;
goto
cleanup
;
}
git_buf_copy_cstr
(
buffer_out
,
buffer_size
,
&
buf
);
error
=
0
;
cleanup:
git_buf_free
(
&
buf
);
return
error
;
}
int
git_reference__normalize_name
(
int
git_reference__normalize_name
_lax
(
char
*
buffer_out
,
size_t
out_size
,
const
char
*
name
)
...
...
src/refs.h
View file @
c030ada7
...
...
@@ -11,6 +11,7 @@
#include "git2/oid.h"
#include "git2/refs.h"
#include "strmap.h"
#include "buffer.h"
#define GIT_REFS_DIR "refs/"
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
...
...
@@ -52,8 +53,9 @@ typedef struct {
void
git_repository__refcache_free
(
git_refcache
*
refs
);
int
git_reference__normalize_name
(
char
*
buffer_out
,
size_t
out_size
,
const
char
*
name
);
int
git_reference__normalize_name
_lax
(
char
*
buffer_out
,
size_t
out_size
,
const
char
*
name
);
int
git_reference__normalize_name_oid
(
char
*
buffer_out
,
size_t
out_size
,
const
char
*
name
);
int
git_reference__normalize_name
(
git_buf
*
buf
,
const
char
*
name
,
unsigned
int
flags
);
int
git_reference__update
(
git_repository
*
repo
,
const
git_oid
*
oid
,
const
char
*
ref_name
);
/**
...
...
tests-clar/refs/normalize.c
View file @
c030ada7
...
...
@@ -5,9 +5,10 @@
#include "reflog.h"
// Helpers
static
void
ensure_refname_normalized
(
unsigned
int
flags
,
const
char
*
input_refname
,
const
char
*
expected_refname
)
static
void
ensure_refname_normalized
(
unsigned
int
flags
,
const
char
*
input_refname
,
const
char
*
expected_refname
)
{
char
buffer_out
[
GIT_REFNAME_MAX
];
...
...
@@ -115,7 +116,7 @@ void test_refs_normalize__symbolic(void)
* See https://github.com/spearce/JGit/commit/e4bf8f6957bbb29362575d641d1e77a02d906739 */
void
test_refs_normalize__jgit_suite
(
void
)
{
// tests borrowed from JGit
// tests borrowed from JGit
/* EmptyString */
ensure_refname_invalid
(
...
...
@@ -314,3 +315,57 @@ void test_refs_normalize__buffer_has_to_be_big_enough_to_hold_the_normalized_ver
cl_git_fail
(
git_reference_normalize_name
(
buffer_out
,
20
,
"//refs//heads/long///name"
,
GIT_REF_FORMAT_NORMAL
));
}
#define ONE_LEVEL_AND_REFSPEC \
GIT_REF_FORMAT_ALLOW_ONELEVEL \
| GIT_REF_FORMAT_REFSPEC_PATTERN
void
test_refs_normalize__refspec_pattern
(
void
)
{
ensure_refname_invalid
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"heads/*foo/bar"
);
ensure_refname_invalid
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"heads/foo*/bar"
);
ensure_refname_invalid
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"heads/f*o/bar"
);
ensure_refname_invalid
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"foo"
);
ensure_refname_normalized
(
ONE_LEVEL_AND_REFSPEC
,
"foo"
,
"foo"
);
ensure_refname_normalized
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"foo/bar"
,
"foo/bar"
);
ensure_refname_normalized
(
ONE_LEVEL_AND_REFSPEC
,
"foo/bar"
,
"foo/bar"
);
ensure_refname_normalized
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"*/foo"
,
"*/foo"
);
ensure_refname_normalized
(
ONE_LEVEL_AND_REFSPEC
,
"*/foo"
,
"*/foo"
);
ensure_refname_normalized
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"foo/*/bar"
,
"foo/*/bar"
);
ensure_refname_normalized
(
ONE_LEVEL_AND_REFSPEC
,
"foo/*/bar"
,
"foo/*/bar"
);
ensure_refname_invalid
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"*"
);
ensure_refname_normalized
(
ONE_LEVEL_AND_REFSPEC
,
"*"
,
"*"
);
ensure_refname_invalid
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"foo/*/*"
);
ensure_refname_invalid
(
ONE_LEVEL_AND_REFSPEC
,
"foo/*/*"
);
ensure_refname_invalid
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"*/foo/*"
);
ensure_refname_invalid
(
ONE_LEVEL_AND_REFSPEC
,
"*/foo/*"
);
ensure_refname_invalid
(
GIT_REF_FORMAT_REFSPEC_PATTERN
,
"*/*/foo"
);
ensure_refname_invalid
(
ONE_LEVEL_AND_REFSPEC
,
"*/*/foo"
);
}
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