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
34a4ad46
Commit
34a4ad46
authored
Jan 16, 2013
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1211 from arrbee/fix-icase-status-file
Fix case insensitivity issues in git_status_file
parents
4b45675d
fffe429a
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
705 additions
and
203 deletions
+705
-203
include/git2/tree.h
+9
-0
src/checkout.c
+10
-6
src/diff.c
+13
-11
src/diff_output.c
+16
-20
src/iterator.c
+196
-77
src/iterator.h
+58
-47
src/path.c
+24
-0
src/path.h
+6
-1
src/status.c
+17
-5
src/submodule.c
+3
-1
src/tree.c
+15
-6
src/tree.h
+2
-0
src/tsort.c
+38
-22
src/util.c
+31
-0
src/util.h
+18
-2
tests-clar/diff/iterator.c
+162
-5
tests-clar/status/worktree.c
+87
-0
No files found.
include/git2/tree.h
View file @
34a4ad46
...
...
@@ -209,6 +209,15 @@ GIT_EXTERN(git_otype) git_tree_entry_type(const git_tree_entry *entry);
GIT_EXTERN
(
git_filemode_t
)
git_tree_entry_filemode
(
const
git_tree_entry
*
entry
);
/**
* Compare two tree entries
*
* @param e1 first tree entry
* @param e2 second tree entry
* @return <0 if e1 is before e2, 0 if e1 == e2, >0 if e1 is after e2
*/
GIT_EXTERN
(
int
)
git_tree_entry_cmp
(
const
git_tree_entry
*
e1
,
const
git_tree_entry
*
e2
);
/**
* Convert a tree entry to the git_object it points too.
*
* You must call `git_object_free()` on the object when you are done with it.
...
...
src/checkout.c
View file @
34a4ad46
...
...
@@ -224,7 +224,7 @@ static int checkout_action_wd_only(
if
(
!
git_pathspec_match_path
(
pathspec
,
wd
->
path
,
(
data
->
strategy
&
GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH
)
!=
0
,
workdir
->
ignore_case
))
git_iterator_ignore_case
(
workdir
)
))
return
0
;
/* check if item is tracked in the index but not in the checkout diff */
...
...
@@ -1130,7 +1130,7 @@ static int checkout_data_init(
if
((
error
=
git_config_refresh
(
cfg
))
<
0
)
goto
cleanup
;
if
(
git_iterator_inner_type
(
target
)
==
GIT_ITERATOR_INDEX
)
{
if
(
git_iterator_inner_type
(
target
)
==
GIT_ITERATOR_
TYPE_
INDEX
)
{
/* if we are iterating over the index, don't reload */
data
->
index
=
git_iterator_index_get_index
(
target
);
GIT_REFCOUNT_INC
(
data
->
index
);
...
...
@@ -1208,6 +1208,7 @@ int git_checkout_iterator(
git_diff_options
diff_opts
=
GIT_DIFF_OPTIONS_INIT
;
uint32_t
*
actions
=
NULL
;
size_t
*
counts
=
NULL
;
git_iterator_flag_t
iterflags
=
0
;
/* initialize structures and options */
error
=
checkout_data_init
(
&
data
,
target
,
opts
);
...
...
@@ -1228,18 +1229,21 @@ int git_checkout_iterator(
diff_opts
.
pathspec
=
data
.
opts
.
paths
;
/* set up iterators */
iterflags
=
git_iterator_ignore_case
(
target
)
?
GIT_ITERATOR_IGNORE_CASE
:
GIT_ITERATOR_DONT_IGNORE_CASE
;
if
((
error
=
git_iterator_reset
(
target
,
data
.
pfx
,
data
.
pfx
))
<
0
||
(
error
=
git_iterator_for_workdir_range
(
&
workdir
,
data
.
repo
,
data
.
pfx
,
data
.
pfx
))
<
0
||
&
workdir
,
data
.
repo
,
iterflags
,
data
.
pfx
,
data
.
pfx
))
<
0
||
(
error
=
git_iterator_for_tree_range
(
&
baseline
,
data
.
opts
.
baseline
,
data
.
pfx
,
data
.
pfx
))
<
0
)
&
baseline
,
data
.
opts
.
baseline
,
iterflags
,
data
.
pfx
,
data
.
pfx
))
<
0
)
goto
cleanup
;
/* Handle case insensitivity for baseline if necessary */
if
(
workdir
->
ignore_case
&&
!
baseline
->
ignore_case
)
{
if
(
git_iterator_ignore_case
(
workdir
)
!=
git_iterator_ignore_case
(
baseline
))
if
((
error
=
git_iterator_spoolandsort_push
(
baseline
,
true
))
<
0
)
goto
cleanup
;
}
/* Generate baseline-to-target diff which will include an entry for
* every possible update that might need to be made.
...
...
src/diff.c
View file @
34a4ad46
...
...
@@ -418,7 +418,7 @@ static int maybe_modified(
git_delta_t
status
=
GIT_DELTA_MODIFIED
;
unsigned
int
omode
=
oitem
->
mode
;
unsigned
int
nmode
=
nitem
->
mode
;
bool
new_is_workdir
=
(
new_iter
->
type
==
GIT_ITERATOR_WORKDIR
);
bool
new_is_workdir
=
(
new_iter
->
type
==
GIT_ITERATOR_
TYPE_
WORKDIR
);
GIT_UNUSED
(
old_iter
);
...
...
@@ -556,7 +556,9 @@ static int diff_list_init_from_iterators(
/* Use case-insensitive compare if either iterator has
* the ignore_case bit set */
if
(
!
old_iter
->
ignore_case
&&
!
new_iter
->
ignore_case
)
{
if
(
!
git_iterator_ignore_case
(
old_iter
)
&&
!
git_iterator_ignore_case
(
new_iter
))
{
diff
->
opts
.
flags
&=
~
GIT_DIFF_DELTAS_ARE_ICASE
;
diff
->
strcomp
=
git__strcmp
;
...
...
@@ -714,7 +716,7 @@ int git_diff__from_iterators(
else
if
(
git_iterator_current_is_ignored
(
new_iter
))
delta_type
=
GIT_DELTA_IGNORED
;
else
if
(
new_iter
->
type
!=
GIT_ITERATOR_WORKDIR
)
else
if
(
new_iter
->
type
!=
GIT_ITERATOR_
TYPE_
WORKDIR
)
delta_type
=
GIT_DELTA_ADDED
;
if
(
diff_delta__from_one
(
diff
,
delta_type
,
nitem
)
<
0
)
...
...
@@ -786,8 +788,8 @@ int git_diff_tree_to_tree(
assert
(
diff
&&
repo
);
DIFF_FROM_ITERATORS
(
git_iterator_for_tree_range
(
&
a
,
old_tree
,
pfx
,
pfx
),
git_iterator_for_tree_range
(
&
b
,
new_tree
,
pfx
,
pfx
)
git_iterator_for_tree_range
(
&
a
,
old_tree
,
0
,
pfx
,
pfx
),
git_iterator_for_tree_range
(
&
b
,
new_tree
,
0
,
pfx
,
pfx
)
);
return
error
;
...
...
@@ -808,8 +810,8 @@ int git_diff_tree_to_index(
return
error
;
DIFF_FROM_ITERATORS
(
git_iterator_for_tree_range
(
&
a
,
old_tree
,
pfx
,
pfx
),
git_iterator_for_index_range
(
&
b
,
index
,
pfx
,
pfx
)
git_iterator_for_tree_range
(
&
a
,
old_tree
,
0
,
pfx
,
pfx
),
git_iterator_for_index_range
(
&
b
,
index
,
0
,
pfx
,
pfx
)
);
return
error
;
...
...
@@ -829,8 +831,8 @@ int git_diff_index_to_workdir(
return
error
;
DIFF_FROM_ITERATORS
(
git_iterator_for_index_range
(
&
a
,
index
,
pfx
,
pfx
),
git_iterator_for_workdir_range
(
&
b
,
repo
,
pfx
,
pfx
)
git_iterator_for_index_range
(
&
a
,
index
,
0
,
pfx
,
pfx
),
git_iterator_for_workdir_range
(
&
b
,
repo
,
0
,
pfx
,
pfx
)
);
return
error
;
...
...
@@ -848,8 +850,8 @@ int git_diff_tree_to_workdir(
assert
(
diff
&&
repo
);
DIFF_FROM_ITERATORS
(
git_iterator_for_tree_range
(
&
a
,
old_tree
,
pfx
,
pfx
),
git_iterator_for_workdir_range
(
&
b
,
repo
,
pfx
,
pfx
)
git_iterator_for_tree_range
(
&
a
,
old_tree
,
0
,
pfx
,
pfx
),
git_iterator_for_workdir_range
(
&
b
,
repo
,
0
,
pfx
,
pfx
)
);
return
error
;
...
...
src/diff_output.c
View file @
34a4ad46
...
...
@@ -495,7 +495,7 @@ static void diff_patch_init(
patch
->
old_src
=
patch
->
diff
->
old_src
;
patch
->
new_src
=
patch
->
diff
->
new_src
;
}
else
{
patch
->
old_src
=
patch
->
new_src
=
GIT_ITERATOR_TREE
;
patch
->
old_src
=
patch
->
new_src
=
GIT_ITERATOR_T
YPE_T
REE
;
}
}
...
...
@@ -578,7 +578,7 @@ static int diff_patch_load(
*/
if
((
delta
->
old_file
.
flags
&
GIT_DIFF_FILE_NO_DATA
)
==
0
&&
patch
->
old_src
==
GIT_ITERATOR_WORKDIR
)
{
patch
->
old_src
==
GIT_ITERATOR_
TYPE_
WORKDIR
)
{
if
((
error
=
get_workdir_content
(
ctxt
,
delta
,
&
delta
->
old_file
,
&
patch
->
old_data
))
<
0
)
goto
cleanup
;
...
...
@@ -587,7 +587,7 @@ static int diff_patch_load(
}
if
((
delta
->
new_file
.
flags
&
GIT_DIFF_FILE_NO_DATA
)
==
0
&&
patch
->
new_src
==
GIT_ITERATOR_WORKDIR
)
{
patch
->
new_src
==
GIT_ITERATOR_
TYPE_
WORKDIR
)
{
if
((
error
=
get_workdir_content
(
ctxt
,
delta
,
&
delta
->
new_file
,
&
patch
->
new_data
))
<
0
)
goto
cleanup
;
...
...
@@ -596,7 +596,7 @@ static int diff_patch_load(
}
if
((
delta
->
old_file
.
flags
&
GIT_DIFF_FILE_NO_DATA
)
==
0
&&
patch
->
old_src
!=
GIT_ITERATOR_WORKDIR
)
{
patch
->
old_src
!=
GIT_ITERATOR_
TYPE_
WORKDIR
)
{
if
((
error
=
get_blob_content
(
ctxt
,
delta
,
&
delta
->
old_file
,
&
patch
->
old_data
,
&
patch
->
old_blob
))
<
0
)
...
...
@@ -606,7 +606,7 @@ static int diff_patch_load(
}
if
((
delta
->
new_file
.
flags
&
GIT_DIFF_FILE_NO_DATA
)
==
0
&&
patch
->
new_src
!=
GIT_ITERATOR_WORKDIR
)
{
patch
->
new_src
!=
GIT_ITERATOR_
TYPE_
WORKDIR
)
{
if
((
error
=
get_blob_content
(
ctxt
,
delta
,
&
delta
->
new_file
,
&
patch
->
new_data
,
&
patch
->
new_blob
))
<
0
)
...
...
@@ -1666,24 +1666,20 @@ int git_diff__paired_foreach(
int
cmp
;
git_diff_delta
*
i2h
,
*
w2i
;
size_t
i
,
j
,
i_max
,
j_max
;
bool
icase
=
false
;
int
(
*
strcomp
)(
const
char
*
,
const
char
*
)
;
i_max
=
idx2head
?
idx2head
->
deltas
.
length
:
0
;
j_max
=
wd2idx
?
wd2idx
->
deltas
.
length
:
0
;
if
(
idx2head
&&
wd2idx
&&
(
0
!=
(
idx2head
->
opts
.
flags
&
GIT_DIFF_DELTAS_ARE_ICASE
)
||
0
!=
(
wd2idx
->
opts
.
flags
&
GIT_DIFF_DELTAS_ARE_ICASE
)))
{
/* Then use the ignore-case sorter... */
icase
=
true
;
/* and assert that both are ignore-case sorted. If this function
* ever needs to support merge joining result sets that are not sorted
* by the same function, then it will need to be extended to do a spool
* and sort on one of the results before merge joining */
assert
(
0
!=
(
idx2head
->
opts
.
flags
&
GIT_DIFF_DELTAS_ARE_ICASE
)
&&
0
!=
(
wd2idx
->
opts
.
flags
&
GIT_DIFF_DELTAS_ARE_ICASE
));
/* Get appropriate strcmp function */
strcomp
=
idx2head
?
idx2head
->
strcomp
:
wd2idx
?
wd2idx
->
strcomp
:
NULL
;
/* Assert both iterators use matching ignore-case. If this function ever
* supports merging diffs that are not sorted by the same function, then
* it will need to spool and sort on one of the results before merging
*/
if
(
idx2head
&&
wd2idx
)
{
assert
(
idx2head
->
strcomp
==
wd2idx
->
strcomp
);
}
for
(
i
=
0
,
j
=
0
;
i
<
i_max
||
j
<
j_max
;
)
{
...
...
@@ -1691,7 +1687,7 @@ int git_diff__paired_foreach(
w2i
=
wd2idx
?
GIT_VECTOR_GET
(
&
wd2idx
->
deltas
,
j
)
:
NULL
;
cmp
=
!
w2i
?
-
1
:
!
i2h
?
1
:
STRCMP_CASESELECT
(
icase
,
i2h
->
old_file
.
path
,
w2i
->
old_file
.
path
);
strcomp
(
i2h
->
old_file
.
path
,
w2i
->
old_file
.
path
);
if
(
cmp
<
0
)
{
if
(
cb
(
i2h
,
NULL
,
payload
))
...
...
src/iterator.c
View file @
34a4ad46
...
...
@@ -24,14 +24,14 @@
#define ITERATOR_BASE_INIT(P,NAME_LC,NAME_UC) do { \
(P) = git__calloc(1, sizeof(NAME_LC ## _iterator)); \
GITERR_CHECK_ALLOC(P); \
(P)->base.type = GIT_ITERATOR_ ## NAME_UC; \
(P)->base.type = GIT_ITERATOR_
TYPE_
## NAME_UC; \
(P)->base.cb = &(P)->cb; \
ITERATOR_SET_CB(P,NAME_LC); \
(P)->base.start = start ? git__strdup(start) : NULL; \
(P)->base.end = end ? git__strdup(end) : NULL; \
(P)->base.ignore_case = false; \
if ((start && !(P)->base.start) || (end && !(P)->base.end)) { \
git__free(P); return -1; } \
(P)->base.prefixcomp = git__prefixcmp; \
} while (0)
static
int
iterator__reset_range
(
...
...
@@ -54,6 +54,34 @@ static int iterator__reset_range(
return
0
;
}
static
int
iterator_update_ignore_case
(
git_iterator
*
iter
,
git_iterator_flag_t
flags
)
{
int
error
=
0
,
ignore_case
=
-
1
;
if
((
flags
&
GIT_ITERATOR_IGNORE_CASE
)
!=
0
)
ignore_case
=
true
;
else
if
((
flags
&
GIT_ITERATOR_DONT_IGNORE_CASE
)
!=
0
)
ignore_case
=
false
;
else
{
git_index
*
index
;
if
(
!
(
error
=
git_repository_index__weakptr
(
&
index
,
iter
->
repo
)))
ignore_case
=
(
index
->
ignore_case
!=
false
);
}
if
(
ignore_case
>
0
)
iter
->
flags
=
(
iter
->
flags
|
GIT_ITERATOR_IGNORE_CASE
);
else
if
(
ignore_case
==
0
)
iter
->
flags
=
(
iter
->
flags
&
~
GIT_ITERATOR_IGNORE_CASE
);
iter
->
prefixcomp
=
((
iter
->
flags
&
GIT_ITERATOR_IGNORE_CASE
)
!=
0
)
?
git__prefixcmp_icase
:
git__prefixcmp
;
return
error
;
}
static
int
empty_iterator__no_item
(
git_iterator
*
iter
,
const
git_index_entry
**
entry
)
{
...
...
@@ -91,13 +119,14 @@ typedef struct {
git_iterator_callbacks
cb
;
}
empty_iterator
;
int
git_iterator_for_nothing
(
git_iterator
**
iter
)
int
git_iterator_for_nothing
(
git_iterator
**
iter
,
git_iterator_flag_t
flags
)
{
empty_iterator
*
i
=
git__calloc
(
1
,
sizeof
(
empty_iterator
));
GITERR_CHECK_ALLOC
(
i
);
i
->
base
.
type
=
GIT_ITERATOR_EMPTY
;
i
->
base
.
type
=
GIT_ITERATOR_
TYPE_
EMPTY
;
i
->
base
.
cb
=
&
i
->
cb
;
i
->
base
.
flags
=
flags
;
i
->
cb
.
current
=
empty_iterator__no_item
;
i
->
cb
.
at_end
=
empty_iterator__at_end
;
i
->
cb
.
advance
=
empty_iterator__no_item
;
...
...
@@ -116,7 +145,10 @@ struct tree_iterator_frame {
tree_iterator_frame
*
next
,
*
prev
;
git_tree
*
tree
;
char
*
start
;
size_t
startlen
;
size_t
index
;
void
**
icase_map
;
void
*
icase_data
[
GIT_FLEX_ARRAY
];
};
typedef
struct
{
...
...
@@ -130,7 +162,13 @@ typedef struct {
GIT_INLINE
(
const
git_tree_entry
*
)
tree_iterator__tree_entry
(
tree_iterator
*
ti
)
{
return
git_tree_entry_byindex
(
ti
->
stack
->
tree
,
ti
->
stack
->
index
);
tree_iterator_frame
*
tf
=
ti
->
stack
;
if
(
tf
->
index
>=
git_tree_entrycount
(
tf
->
tree
))
return
NULL
;
return
git_tree_entry_byindex
(
tf
->
tree
,
tf
->
icase_map
?
(
size_t
)
tf
->
icase_map
[
tf
->
index
]
:
tf
->
index
);
}
static
char
*
tree_iterator__current_filename
(
...
...
@@ -149,7 +187,10 @@ static void tree_iterator__free_frame(tree_iterator_frame *tf)
{
if
(
!
tf
)
return
;
git_tree_free
(
tf
->
tree
);
tf
->
tree
=
NULL
;
git__free
(
tf
);
}
...
...
@@ -195,7 +236,7 @@ static int tree_iterator__current(
if
(
ti
->
entry
.
path
==
NULL
)
return
-
1
;
if
(
ti
->
base
.
end
&&
git__prefixc
mp
(
ti
->
entry
.
path
,
ti
->
base
.
end
)
>
0
)
if
(
ti
->
base
.
end
&&
ti
->
base
.
prefixco
mp
(
ti
->
entry
.
path
,
ti
->
base
.
end
)
>
0
)
return
tree_iterator__to_end
(
ti
);
if
(
entry
)
...
...
@@ -209,10 +250,50 @@ static int tree_iterator__at_end(git_iterator *self)
return
(
tree_iterator__tree_entry
((
tree_iterator
*
)
self
)
==
NULL
);
}
static
int
tree_iterator__icase_map_cmp
(
const
void
*
a
,
const
void
*
b
,
void
*
data
)
{
git_tree
*
tree
=
data
;
const
git_tree_entry
*
te1
=
git_tree_entry_byindex
(
tree
,
(
size_t
)
a
);
const
git_tree_entry
*
te2
=
git_tree_entry_byindex
(
tree
,
(
size_t
)
b
);
return
te1
?
(
te2
?
git_tree_entry_icmp
(
te1
,
te2
)
:
1
)
:
-
1
;
}
static
int
tree_iterator__frame_start_icmp
(
const
void
*
key
,
const
void
*
element
)
{
const
tree_iterator_frame
*
tf
=
(
const
tree_iterator_frame
*
)
key
;
const
git_tree_entry
*
te
=
git_tree_entry_byindex
(
tf
->
tree
,
(
size_t
)
element
);
return
memcmp
(
tf
->
start
,
te
->
filename
,
min
(
tf
->
startlen
,
te
->
filename_len
));
}
static
void
tree_iterator__frame_seek_start
(
tree_iterator_frame
*
tf
)
{
if
(
!
tf
->
start
)
tf
->
index
=
0
;
else
if
(
!
tf
->
icase_map
)
tf
->
index
=
git_tree__prefix_position
(
tf
->
tree
,
tf
->
start
);
else
{
if
(
!
git__bsearch
(
tf
->
icase_map
,
git_tree_entrycount
(
tf
->
tree
),
tf
,
tree_iterator__frame_start_icmp
,
&
tf
->
index
))
{
while
(
tf
->
index
>
0
)
{
/* move back while previous entry is still prefixed */
if
(
tree_iterator__frame_start_icmp
(
tf
,
(
const
void
*
)(
tf
->
index
-
1
)))
break
;
tf
->
index
--
;
}
}
}
}
static
tree_iterator_frame
*
tree_iterator__alloc_frame
(
git_tree
*
tree
,
char
*
start
)
tree_iterator
*
ti
,
git_tree
*
tree
,
char
*
start
)
{
tree_iterator_frame
*
tf
=
git__calloc
(
1
,
sizeof
(
tree_iterator_frame
));
size_t
i
,
max_i
=
git_tree_entrycount
(
tree
);
tree_iterator_frame
*
tf
=
git__calloc
(
1
,
sizeof
(
tree_iterator_frame
)
+
max_i
*
sizeof
(
void
*
));
if
(
!
tf
)
return
NULL
;
...
...
@@ -220,9 +301,24 @@ static tree_iterator_frame *tree_iterator__alloc_frame(
if
(
start
&&
*
start
)
{
tf
->
start
=
start
;
tf
->
index
=
git_tree__prefix_position
(
tree
,
start
);
tf
->
startlen
=
strlen
(
start
);
}
if
(
!
max_i
)
return
tf
;
if
((
ti
->
base
.
flags
&
GIT_ITERATOR_IGNORE_CASE
)
!=
0
)
{
tf
->
icase_map
=
tf
->
icase_data
;
for
(
i
=
0
;
i
<
max_i
;
++
i
)
tf
->
icase_map
[
i
]
=
(
void
*
)
i
;
git__tsort_r
(
tf
->
icase_map
,
max_i
,
tree_iterator__icase_map_cmp
,
tf
->
tree
);
}
tree_iterator__frame_seek_start
(
tf
);
return
tf
;
}
...
...
@@ -240,7 +336,7 @@ static int tree_iterator__expand_tree(tree_iterator *ti)
/* check that we have not passed the range end */
if
(
ti
->
base
.
end
!=
NULL
&&
git__prefixc
mp
(
ti
->
path
.
ptr
,
ti
->
base
.
end
)
>
0
)
ti
->
base
.
prefixco
mp
(
ti
->
path
.
ptr
,
ti
->
base
.
end
)
>
0
)
return
tree_iterator__to_end
(
ti
);
if
((
error
=
git_tree_lookup
(
&
subtree
,
ti
->
base
.
repo
,
&
te
->
oid
))
<
0
)
...
...
@@ -250,14 +346,13 @@ static int tree_iterator__expand_tree(tree_iterator *ti)
/* apply range start to new frame if relevant */
if
(
ti
->
stack
->
start
&&
git__prefixc
mp
(
ti
->
stack
->
start
,
te
->
filename
)
==
0
)
ti
->
base
.
prefixco
mp
(
ti
->
stack
->
start
,
te
->
filename
)
==
0
)
{
size_t
namelen
=
strlen
(
te
->
filename
);
if
(
ti
->
stack
->
start
[
namelen
]
==
'/'
)
relpath
=
ti
->
stack
->
start
+
namelen
+
1
;
if
(
ti
->
stack
->
start
[
te
->
filename_len
]
==
'/'
)
relpath
=
ti
->
stack
->
start
+
te
->
filename_len
+
1
;
}
if
((
tf
=
tree_iterator__alloc_frame
(
subtree
,
relpath
))
==
NULL
)
if
((
tf
=
tree_iterator__alloc_frame
(
ti
,
subtree
,
relpath
))
==
NULL
)
return
-
1
;
tf
->
next
=
ti
->
stack
;
...
...
@@ -286,8 +381,9 @@ static int tree_iterator__advance(
}
while
(
1
)
{
te
=
git_tree_entry_byindex
(
ti
->
stack
->
tree
,
++
ti
->
stack
->
index
);
if
(
te
!=
NULL
)
++
ti
->
stack
->
index
;
if
((
te
=
tree_iterator__tree_entry
(
ti
))
!=
NULL
)
break
;
if
(
!
tree_iterator__pop_frame
(
ti
))
...
...
@@ -337,8 +433,8 @@ static int tree_iterator__reset(
if
(
iterator__reset_range
(
self
,
start
,
end
)
<
0
)
return
-
1
;
ti
->
stack
->
index
=
git_tree__prefix_position
(
ti
->
stack
->
tree
,
ti
->
base
.
start
);
/* reset start position */
tree_iterator__frame_seek_start
(
ti
->
stack
);
git_buf_clear
(
&
ti
->
path
);
ti
->
path_has_filename
=
false
;
...
...
@@ -349,6 +445,7 @@ static int tree_iterator__reset(
int
git_iterator_for_tree_range
(
git_iterator
**
iter
,
git_tree
*
tree
,
git_iterator_flag_t
flags
,
const
char
*
start
,
const
char
*
end
)
{
...
...
@@ -356,7 +453,7 @@ int git_iterator_for_tree_range(
tree_iterator
*
ti
;
if
(
tree
==
NULL
)
return
git_iterator_for_nothing
(
iter
);
return
git_iterator_for_nothing
(
iter
,
flags
);
if
((
error
=
git_tree__dup
(
&
tree
,
tree
))
<
0
)
return
error
;
...
...
@@ -364,13 +461,20 @@ int git_iterator_for_tree_range(
ITERATOR_BASE_INIT
(
ti
,
tree
,
TREE
);
ti
->
base
.
repo
=
git_tree_owner
(
tree
);
ti
->
stack
=
ti
->
tail
=
tree_iterator__alloc_frame
(
tree
,
ti
->
base
.
start
);
if
((
error
=
iterator_update_ignore_case
((
git_iterator
*
)
ti
,
flags
))
<
0
)
goto
fail
;
ti
->
stack
=
ti
->
tail
=
tree_iterator__alloc_frame
(
ti
,
tree
,
ti
->
base
.
start
);
if
((
error
=
tree_iterator__expand_tree
(
ti
))
<
0
)
g
it_iterator_free
((
git_iterator
*
)
ti
)
;
else
g
oto
fail
;
*
iter
=
(
git_iterator
*
)
ti
;
return
0
;
fail
:
git_iterator_free
((
git_iterator
*
)
ti
);
return
error
;
}
...
...
@@ -411,7 +515,7 @@ static void index_iterator__skip_conflicts(
if
(
ie
==
NULL
||
(
ii
->
base
.
end
!=
NULL
&&
ITERATOR_PREFIXCMP
(
ii
->
base
,
ie
->
path
,
ii
->
base
.
end
)
>
0
))
{
ii
->
base
.
prefixcomp
(
ie
->
path
,
ii
->
base
.
end
)
>
0
))
{
ii
->
current
=
entrycount
;
break
;
}
...
...
@@ -466,15 +570,21 @@ static void index_iterator__free(git_iterator *self)
int
git_iterator_for_index_range
(
git_iterator
**
iter
,
git_index
*
index
,
git_iterator_flag_t
flags
,
const
char
*
start
,
const
char
*
end
)
{
index_iterator
*
ii
;
GIT_UNUSED
(
flags
);
ITERATOR_BASE_INIT
(
ii
,
index
,
INDEX
);
ii
->
base
.
repo
=
git_index_owner
(
index
);
ii
->
base
.
ignore_case
=
index
->
ignore_case
;
if
(
index
->
ignore_case
)
{
ii
->
base
.
flags
|=
GIT_ITERATOR_IGNORE_CASE
;
ii
->
base
.
prefixcomp
=
git__prefixcmp_icase
;
}
ii
->
index
=
index
;
GIT_REFCOUNT_INC
(
index
);
...
...
@@ -485,20 +595,6 @@ int git_iterator_for_index_range(
return
0
;
}
int
git_iterator_for_repo_index_range
(
git_iterator
**
iter
,
git_repository
*
repo
,
const
char
*
start
,
const
char
*
end
)
{
int
error
;
git_index
*
index
;
if
((
error
=
git_repository_index__weakptr
(
&
index
,
repo
))
<
0
)
return
error
;
return
git_iterator_for_index_range
(
iter
,
index
,
start
,
end
);
}
typedef
struct
workdir_iterator_frame
workdir_iterator_frame
;
struct
workdir_iterator_frame
{
...
...
@@ -544,7 +640,8 @@ static workdir_iterator_frame *workdir_iterator__alloc_frame(
workdir_iterator
*
wi
)
{
workdir_iterator_frame
*
wf
=
git__calloc
(
1
,
sizeof
(
workdir_iterator_frame
));
git_vector_cmp
entry_compare
=
CASESELECT
(
wi
->
base
.
ignore_case
,
git_vector_cmp
entry_compare
=
CASESELECT
(
(
wi
->
base
.
flags
&
GIT_ITERATOR_IGNORE_CASE
)
!=
0
,
git_path_with_stat_cmp_icase
,
git_path_with_stat_cmp
);
if
(
wf
==
NULL
)
...
...
@@ -606,7 +703,8 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi)
GITERR_CHECK_ALLOC
(
wf
);
error
=
git_path_dirload_with_stat
(
wi
->
path
.
ptr
,
wi
->
root_len
,
wi
->
base
.
ignore_case
,
wi
->
path
.
ptr
,
wi
->
root_len
,
(
wi
->
base
.
flags
&
GIT_ITERATOR_IGNORE_CASE
)
!=
0
,
wi
->
base
.
start
,
wi
->
base
.
end
,
&
wf
->
entries
);
if
(
error
<
0
||
wf
->
entries
.
length
==
0
)
{
...
...
@@ -744,8 +842,8 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
if
(
git_buf_put
(
&
wi
->
path
,
ps
->
path
,
ps
->
path_len
)
<
0
)
return
-
1
;
if
(
wi
->
base
.
end
&&
ITERATOR_PREFIXCMP
(
wi
->
base
,
wi
->
path
.
ptr
+
wi
->
root_len
,
wi
->
base
.
end
)
>
0
)
if
(
wi
->
base
.
end
&&
wi
->
base
.
prefixcomp
(
wi
->
path
.
ptr
+
wi
->
root_len
,
wi
->
base
.
end
)
>
0
)
return
0
;
wi
->
entry
.
path
=
ps
->
path
;
...
...
@@ -789,12 +887,12 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
int
git_iterator_for_workdir_range
(
git_iterator
**
iter
,
git_repository
*
repo
,
git_iterator_flag_t
flags
,
const
char
*
start
,
const
char
*
end
)
{
int
error
;
workdir_iterator
*
wi
;
git_index
*
index
;
assert
(
iter
&&
repo
);
...
...
@@ -805,13 +903,8 @@ int git_iterator_for_workdir_range(
ITERATOR_BASE_INIT
(
wi
,
workdir
,
WORKDIR
);
wi
->
base
.
repo
=
repo
;
if
((
error
=
git_repository_index__weakptr
(
&
index
,
repo
))
<
0
)
{
git_iterator_free
((
git_iterator
*
)
wi
);
return
error
;
}
/* Match ignore_case flag for iterator to that of the index */
wi
->
base
.
ignore_case
=
index
->
ignore_case
;
if
((
error
=
iterator_update_ignore_case
((
git_iterator
*
)
wi
,
flags
))
<
0
)
goto
fail
;
if
(
git_buf_sets
(
&
wi
->
path
,
git_repository_workdir
(
repo
))
<
0
||
git_path_to_dir
(
&
wi
->
path
)
<
0
||
...
...
@@ -822,23 +915,24 @@ int git_iterator_for_workdir_range(
}
wi
->
root_len
=
wi
->
path
.
size
;
wi
->
entrycmp
=
wi
->
base
.
ignore_case
?
wi
->
entrycmp
=
(
wi
->
base
.
flags
&
GIT_ITERATOR_IGNORE_CASE
)
!=
0
?
workdir_iterator__entry_cmp_icase
:
workdir_iterator__entry_cmp_case
;
if
((
error
=
workdir_iterator__expand_dir
(
wi
))
<
0
)
{
if
(
error
==
GIT_ENOTFOUND
)
error
=
0
;
else
{
git_iterator_free
((
git_iterator
*
)
wi
);
wi
=
NULL
;
}
if
(
error
!=
GIT_ENOTFOUND
)
goto
fail
;
giterr_clear
();
}
*
iter
=
(
git_iterator
*
)
wi
;
return
0
;
fail:
git_iterator_free
((
git_iterator
*
)
wi
);
return
error
;
}
typedef
struct
{
/* replacement callbacks */
git_iterator_callbacks
cb
;
...
...
@@ -913,12 +1007,12 @@ void git_iterator_spoolandsort_pop(git_iterator *self)
{
spoolandsort_callbacks
*
scb
=
(
spoolandsort_callbacks
*
)
self
->
cb
;
if
(
self
->
type
!=
GIT_ITERATOR_SPOOLANDSORT
)
if
(
self
->
type
!=
GIT_ITERATOR_
TYPE_
SPOOLANDSORT
)
return
;
self
->
cb
=
scb
->
orig
;
self
->
type
=
scb
->
orig_type
;
self
->
ignore_case
=
!
self
->
ignore_case
;
self
->
flags
^=
GIT_ITERATOR_IGNORE_CASE
;
spoolandsort_iterator__free_callbacks
(
scb
);
}
...
...
@@ -935,9 +1029,14 @@ int git_iterator_spoolandsort_push(git_iterator *iter, bool ignore_case)
spoolandsort_callbacks
*
scb
;
int
(
*
entrycomp
)(
const
void
*
a
,
const
void
*
b
);
if
(
iter
->
ignore_case
==
ignore_case
)
if
(
((
iter
->
flags
&
GIT_ITERATOR_IGNORE_CASE
)
!=
0
)
==
(
ignore_case
!=
0
)
)
return
0
;
if
(
iter
->
type
==
GIT_ITERATOR_TYPE_EMPTY
)
{
iter
->
flags
=
(
iter
->
flags
^
GIT_ITERATOR_IGNORE_CASE
);
return
0
;
}
scb
=
git__calloc
(
1
,
sizeof
(
spoolandsort_callbacks
));
GITERR_CHECK_ALLOC
(
scb
);
...
...
@@ -978,8 +1077,8 @@ int git_iterator_spoolandsort_push(git_iterator *iter, bool ignore_case)
git_vector_sort
(
&
scb
->
entries
);
iter
->
cb
=
(
git_iterator_callbacks
*
)
scb
;
iter
->
type
=
GIT_ITERATOR_SPOOLANDSORT
;
iter
->
ignore_case
=
!
iter
->
ignore_case
;
iter
->
type
=
GIT_ITERATOR_
TYPE_
SPOOLANDSORT
;
iter
->
flags
^=
GIT_ITERATOR_IGNORE_CASE
;
return
0
;
...
...
@@ -988,13 +1087,29 @@ fail:
return
-
1
;
}
void
git_iterator_free
(
git_iterator
*
iter
)
{
if
(
iter
==
NULL
)
return
;
iter
->
cb
->
free
(
iter
);
git__free
(
iter
->
start
);
git__free
(
iter
->
end
);
memset
(
iter
,
0
,
sizeof
(
*
iter
));
git__free
(
iter
);
}
git_index
*
git_iterator_index_get_index
(
git_iterator
*
iter
)
{
if
(
iter
->
type
==
GIT_ITERATOR_INDEX
)
if
(
iter
->
type
==
GIT_ITERATOR_
TYPE_
INDEX
)
return
((
index_iterator
*
)
iter
)
->
index
;
if
(
iter
->
type
==
GIT_ITERATOR_SPOOLANDSORT
&&
((
spoolandsort_callbacks
*
)
iter
->
cb
)
->
orig_type
==
GIT_ITERATOR_INDEX
)
if
(
iter
->
type
==
GIT_ITERATOR_
TYPE_
SPOOLANDSORT
&&
((
spoolandsort_callbacks
*
)
iter
->
cb
)
->
orig_type
==
GIT_ITERATOR_
TYPE_
INDEX
)
return
((
index_iterator
*
)
iter
)
->
index
;
return
NULL
;
...
...
@@ -1002,7 +1117,7 @@ git_index *git_iterator_index_get_index(git_iterator *iter)
git_iterator_type_t
git_iterator_inner_type
(
git_iterator
*
iter
)
{
if
(
iter
->
type
==
GIT_ITERATOR_SPOOLANDSORT
)
if
(
iter
->
type
==
GIT_ITERATOR_
TYPE_
SPOOLANDSORT
)
return
((
spoolandsort_callbacks
*
)
iter
->
cb
)
->
orig_type
;
return
iter
->
type
;
...
...
@@ -1011,7 +1126,7 @@ git_iterator_type_t git_iterator_inner_type(git_iterator *iter)
int
git_iterator_current_tree_entry
(
git_iterator
*
iter
,
const
git_tree_entry
**
tree_entry
)
{
*
tree_entry
=
(
iter
->
type
!=
GIT_ITERATOR_TREE
)
?
NULL
:
*
tree_entry
=
(
iter
->
type
!=
GIT_ITERATOR_T
YPE_T
REE
)
?
NULL
:
tree_iterator__tree_entry
((
tree_iterator
*
)
iter
);
return
0
;
}
...
...
@@ -1024,10 +1139,14 @@ int git_iterator_current_parent_tree(
tree_iterator
*
ti
=
(
tree_iterator
*
)
iter
;
tree_iterator_frame
*
tf
;
const
char
*
scan
=
parent_path
;
int
(
*
strncomp
)(
const
char
*
a
,
const
char
*
b
,
size_t
sz
);
if
(
iter
->
type
!=
GIT_ITERATOR_TREE
||
ti
->
stack
==
NULL
)
if
(
iter
->
type
!=
GIT_ITERATOR_T
YPE_T
REE
||
ti
->
stack
==
NULL
)
goto
notfound
;
strncomp
=
((
iter
->
flags
&
GIT_ITERATOR_IGNORE_CASE
)
!=
0
)
?
git__strncasecmp
:
git__strncmp
;
for
(
tf
=
ti
->
tail
;
tf
!=
NULL
;
tf
=
tf
->
prev
)
{
const
git_tree_entry
*
te
;
...
...
@@ -1036,9 +1155,10 @@ int git_iterator_current_parent_tree(
return
0
;
}
te
=
git_tree_entry_byindex
(
tf
->
tree
,
tf
->
index
);
te
=
git_tree_entry_byindex
(
tf
->
tree
,
tf
->
icase_map
?
(
size_t
)
tf
->
icase_map
[
tf
->
index
]
:
tf
->
index
);
if
(
strncmp
(
scan
,
te
->
filename
,
te
->
filename_len
)
!=
0
)
if
(
strnc
o
mp
(
scan
,
te
->
filename
,
te
->
filename_len
)
!=
0
)
goto
notfound
;
scan
+=
te
->
filename_len
;
...
...
@@ -1059,7 +1179,7 @@ int git_iterator_current_is_ignored(git_iterator *iter)
{
workdir_iterator
*
wi
=
(
workdir_iterator
*
)
iter
;
if
(
iter
->
type
!=
GIT_ITERATOR_WORKDIR
)
if
(
iter
->
type
!=
GIT_ITERATOR_
TYPE_
WORKDIR
)
return
0
;
if
(
wi
->
is_ignored
!=
-
1
)
...
...
@@ -1076,7 +1196,7 @@ int git_iterator_advance_into_directory(
{
workdir_iterator
*
wi
=
(
workdir_iterator
*
)
iter
;
if
(
iter
->
type
==
GIT_ITERATOR_WORKDIR
&&
if
(
iter
->
type
==
GIT_ITERATOR_
TYPE_
WORKDIR
&&
wi
->
entry
.
path
&&
(
wi
->
entry
.
mode
==
GIT_FILEMODE_TREE
||
wi
->
entry
.
mode
==
GIT_FILEMODE_COMMIT
))
...
...
@@ -1089,8 +1209,7 @@ int git_iterator_advance_into_directory(
return
entry
?
git_iterator_current
(
iter
,
entry
)
:
0
;
}
int
git_iterator_cmp
(
git_iterator
*
iter
,
const
char
*
path_prefix
)
int
git_iterator_cmp
(
git_iterator
*
iter
,
const
char
*
path_prefix
)
{
const
git_index_entry
*
entry
;
...
...
@@ -1103,14 +1222,14 @@ int git_iterator_cmp(
if
(
!
path_prefix
)
return
-
1
;
return
ITERATOR_PREFIXCMP
(
*
iter
,
entry
->
path
,
path_prefix
);
return
iter
->
prefixcomp
(
entry
->
path
,
path_prefix
);
}
int
git_iterator_current_workdir_path
(
git_iterator
*
iter
,
git_buf
**
path
)
{
workdir_iterator
*
wi
=
(
workdir_iterator
*
)
iter
;
if
(
iter
->
type
!=
GIT_ITERATOR_WORKDIR
||
!
wi
->
entry
.
path
)
if
(
iter
->
type
!=
GIT_ITERATOR_
TYPE_
WORKDIR
||
!
wi
->
entry
.
path
)
*
path
=
NULL
;
else
*
path
=
&
wi
->
path
;
...
...
src/iterator.h
View file @
34a4ad46
...
...
@@ -12,20 +12,26 @@
#include "vector.h"
#include "buffer.h"
#define ITERATOR_PREFIXCMP(ITER, STR, PREFIX) (((ITER).ignore_case) ? \
#define ITERATOR_PREFIXCMP(ITER, STR, PREFIX) \
(((ITER).flags & GIT_ITERATOR_IGNORE_CASE) != 0 ? \
git__prefixcmp_icase((STR), (PREFIX)) : \
git__prefixcmp((STR), (PREFIX)))
typedef
struct
git_iterator
git_iterator
;
typedef
enum
{
GIT_ITERATOR_EMPTY
=
0
,
GIT_ITERATOR_TREE
=
1
,
GIT_ITERATOR_INDEX
=
2
,
GIT_ITERATOR_WORKDIR
=
3
,
GIT_ITERATOR_SPOOLANDSORT
=
4
GIT_ITERATOR_
TYPE_
EMPTY
=
0
,
GIT_ITERATOR_T
YPE_T
REE
=
1
,
GIT_ITERATOR_
TYPE_
INDEX
=
2
,
GIT_ITERATOR_
TYPE_
WORKDIR
=
3
,
GIT_ITERATOR_
TYPE_
SPOOLANDSORT
=
4
}
git_iterator_type_t
;
typedef
enum
{
GIT_ITERATOR_IGNORE_CASE
=
(
1
<<
0
),
/* ignore_case */
GIT_ITERATOR_DONT_IGNORE_CASE
=
(
1
<<
1
),
/* force ignore_case off */
}
git_iterator_flag_t
;
typedef
struct
{
int
(
*
current
)(
git_iterator
*
,
const
git_index_entry
**
);
int
(
*
at_end
)(
git_iterator
*
);
...
...
@@ -41,50 +47,60 @@ struct git_iterator {
git_repository
*
repo
;
char
*
start
;
char
*
end
;
bool
ignore_case
;
int
(
*
prefixcomp
)(
const
char
*
str
,
const
char
*
prefix
);
unsigned
int
flags
;
};
extern
int
git_iterator_for_nothing
(
git_iterator
**
iter
);
extern
int
git_iterator_for_nothing
(
git_iterator
**
out
,
git_iterator_flag_t
flags
);
/* tree iterators will match the ignore_case value from the index of the
* repository, unless you override with a non-zero flag value
*/
extern
int
git_iterator_for_tree_range
(
git_iterator
**
iter
,
git_tree
*
tree
,
const
char
*
start
,
const
char
*
end
);
git_iterator
**
out
,
git_tree
*
tree
,
git_iterator_flag_t
flags
,
const
char
*
start
,
const
char
*
end
);
GIT_INLINE
(
int
)
git_iterator_for_tree
(
git_iterator
**
iter
,
git_tree
*
tree
)
GIT_INLINE
(
int
)
git_iterator_for_tree
(
git_iterator
**
out
,
git_tree
*
tree
)
{
return
git_iterator_for_tree_range
(
iter
,
tree
,
NULL
,
NULL
);
return
git_iterator_for_tree_range
(
out
,
tree
,
0
,
NULL
,
NULL
);
}
/* index iterators will take the ignore_case value from the index; the
* ignore_case flags are not used
*/
extern
int
git_iterator_for_index_range
(
git_iterator
**
iter
,
git_index
*
index
,
const
char
*
start
,
const
char
*
end
);
GIT_INLINE
(
int
)
git_iterator_for_index
(
git_iterator
**
iter
,
git_index
*
index
)
{
return
git_iterator_for_index_range
(
iter
,
index
,
NULL
,
NULL
);
}
extern
int
git_iterator_for_repo_index_range
(
git_iterator
**
iter
,
git_repository
*
repo
,
const
char
*
start
,
const
char
*
end
);
git_iterator
**
out
,
git_index
*
index
,
git_iterator_flag_t
flags
,
const
char
*
start
,
const
char
*
end
);
GIT_INLINE
(
int
)
git_iterator_for_repo_index
(
git_iterator
**
iter
,
git_repository
*
repo
)
GIT_INLINE
(
int
)
git_iterator_for_index
(
git_iterator
**
out
,
git_index
*
index
)
{
return
git_iterator_for_
repo_index_range
(
iter
,
repo
,
NULL
,
NULL
);
return
git_iterator_for_
index_range
(
out
,
index
,
0
,
NULL
,
NULL
);
}
/* workdir iterators will match the ignore_case value from the index of the
* repository, unless you override with a non-zero flag value
*/
extern
int
git_iterator_for_workdir_range
(
git_iterator
**
iter
,
git_repository
*
repo
,
const
char
*
start
,
const
char
*
end
);
git_iterator
**
out
,
git_repository
*
repo
,
git_iterator_flag_t
flags
,
const
char
*
start
,
const
char
*
end
);
GIT_INLINE
(
int
)
git_iterator_for_workdir
(
git_iterator
**
iter
,
git_repository
*
repo
)
GIT_INLINE
(
int
)
git_iterator_for_workdir
(
git_iterator
**
out
,
git_repository
*
repo
)
{
return
git_iterator_for_workdir_range
(
iter
,
repo
,
NULL
,
NULL
);
return
git_iterator_for_workdir_range
(
out
,
repo
,
0
,
NULL
,
NULL
);
}
extern
void
git_iterator_free
(
git_iterator
*
iter
);
/* Spool all iterator values, resort with alternative ignore_case value
* and replace callbacks with spoolandsort alternates.
*/
...
...
@@ -130,21 +146,6 @@ GIT_INLINE(int) git_iterator_reset(
return
iter
->
cb
->
reset
(
iter
,
start
,
end
);
}
GIT_INLINE
(
void
)
git_iterator_free
(
git_iterator
*
iter
)
{
if
(
iter
==
NULL
)
return
;
iter
->
cb
->
free
(
iter
);
git__free
(
iter
->
start
);
git__free
(
iter
->
end
);
memset
(
iter
,
0
,
sizeof
(
*
iter
));
git__free
(
iter
);
}
GIT_INLINE
(
git_iterator_type_t
)
git_iterator_type
(
git_iterator
*
iter
)
{
return
iter
->
type
;
...
...
@@ -155,6 +156,16 @@ GIT_INLINE(git_repository *) git_iterator_owner(git_iterator *iter)
return
iter
->
repo
;
}
GIT_INLINE
(
git_iterator_flag_t
)
git_iterator_flags
(
git_iterator
*
iter
)
{
return
iter
->
flags
;
}
GIT_INLINE
(
bool
)
git_iterator_ignore_case
(
git_iterator
*
iter
)
{
return
((
iter
->
flags
&
GIT_ITERATOR_IGNORE_CASE
)
!=
0
);
}
extern
int
git_iterator_current_tree_entry
(
git_iterator
*
iter
,
const
git_tree_entry
**
tree_entry
);
...
...
src/path.c
View file @
34a4ad46
...
...
@@ -701,6 +701,30 @@ int git_path_cmp(
return
(
c1
<
c2
)
?
-
1
:
(
c1
>
c2
)
?
1
:
0
;
}
int
git_path_icmp
(
const
char
*
name1
,
size_t
len1
,
int
isdir1
,
const
char
*
name2
,
size_t
len2
,
int
isdir2
)
{
unsigned
char
c1
,
c2
;
size_t
len
=
len1
<
len2
?
len1
:
len2
;
int
cmp
;
cmp
=
strncasecmp
(
name1
,
name2
,
len
);
if
(
cmp
)
return
cmp
;
c1
=
name1
[
len
];
c2
=
name2
[
len
];
if
(
c1
==
'\0'
&&
isdir1
)
c1
=
'/'
;
if
(
c2
==
'\0'
&&
isdir2
)
c2
=
'/'
;
return
(
c1
<
c2
)
?
-
1
:
(
c1
>
c2
)
?
1
:
0
;
}
int
git_path_direach
(
git_buf
*
path
,
int
(
*
fn
)(
void
*
,
git_buf
*
),
...
...
src/path.h
View file @
34a4ad46
...
...
@@ -261,12 +261,17 @@ extern int git_path_direach(
void
*
state
);
/**
* Sort function to order two paths
.
* Sort function to order two paths
*/
extern
int
git_path_cmp
(
const
char
*
name1
,
size_t
len1
,
int
isdir1
,
const
char
*
name2
,
size_t
len2
,
int
isdir2
);
/** Path sort function that is case insensitive */
extern
int
git_path_icmp
(
const
char
*
name1
,
size_t
len1
,
int
isdir1
,
const
char
*
name2
,
size_t
len2
,
int
isdir2
);
/**
* Invoke callback up path directory by directory until the ceiling is
* reached (inclusive of a final call at the root_path).
...
...
src/status.c
View file @
34a4ad46
...
...
@@ -196,21 +196,24 @@ struct status_file_info {
char
*
expected
;
unsigned
int
count
;
unsigned
int
status
;
int
fnm_flags
;
int
ambiguous
;
};
static
int
get_one_status
(
const
char
*
path
,
unsigned
int
status
,
void
*
data
)
{
struct
status_file_info
*
sfi
=
data
;
int
(
*
strcomp
)(
const
char
*
a
,
const
char
*
b
);
sfi
->
count
++
;
sfi
->
status
=
status
;
strcomp
=
(
sfi
->
fnm_flags
&
FNM_CASEFOLD
)
?
git__strcasecmp
:
git__strcmp
;
if
(
sfi
->
count
>
1
||
(
strcmp
(
sfi
->
expected
,
path
)
!=
0
&&
p_fnmatch
(
sfi
->
expected
,
path
,
0
)
!=
0
))
{
giterr_set
(
GITERR_INVALID
,
"Ambiguous path '%s' given to git_status_file"
,
sfi
->
expected
);
(
strcomp
(
sfi
->
expected
,
path
)
!=
0
&&
p_fnmatch
(
sfi
->
expected
,
path
,
sfi
->
fnm_flags
)
!=
0
))
{
sfi
->
ambiguous
=
true
;
return
GIT_EAMBIGUOUS
;
}
...
...
@@ -226,11 +229,17 @@ int git_status_file(
int
error
;
git_status_options
opts
=
GIT_STATUS_OPTIONS_INIT
;
struct
status_file_info
sfi
=
{
0
};
git_index
*
index
;
assert
(
status_flags
&&
repo
&&
path
);
if
((
error
=
git_repository_index__weakptr
(
&
index
,
repo
))
<
0
)
return
error
;
if
((
sfi
.
expected
=
git__strdup
(
path
))
==
NULL
)
return
-
1
;
if
(
index
->
ignore_case
)
sfi
.
fnm_flags
=
FNM_CASEFOLD
;
opts
.
show
=
GIT_STATUS_SHOW_INDEX_AND_WORKDIR
;
opts
.
flags
=
GIT_STATUS_OPT_INCLUDE_IGNORED
|
...
...
@@ -242,8 +251,11 @@ int git_status_file(
error
=
git_status_foreach_ext
(
repo
,
&
opts
,
get_one_status
,
&
sfi
);
if
(
error
<
0
&&
sfi
.
ambiguous
)
if
(
error
<
0
&&
sfi
.
ambiguous
)
{
giterr_set
(
GITERR_INVALID
,
"Ambiguous path '%s' given to git_status_file"
,
sfi
.
expected
);
error
=
GIT_EAMBIGUOUS
;
}
if
(
!
error
&&
!
sfi
.
count
)
{
git_buf
full
=
GIT_BUF_INIT
;
...
...
src/submodule.c
View file @
34a4ad46
...
...
@@ -1130,10 +1130,12 @@ static int load_submodule_config_from_index(
git_repository
*
repo
,
git_oid
*
gitmodules_oid
)
{
int
error
;
git_index
*
index
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
if
((
error
=
git_iterator_for_repo_index
(
&
i
,
repo
))
<
0
)
if
((
error
=
git_repository_index__weakptr
(
&
index
,
repo
))
<
0
||
(
error
=
git_iterator_for_index
(
&
i
,
index
))
<
0
)
return
error
;
error
=
git_iterator_current
(
i
,
&
entry
);
...
...
src/tree.c
View file @
34a4ad46
...
...
@@ -55,14 +55,23 @@ static int valid_entry_name(const char *filename)
strcmp
(
filename
,
DOT_GIT
)
!=
0
));
}
static
int
entry_sort_cmp
(
const
void
*
a
,
const
void
*
b
)
int
git_tree_entry_cmp
(
const
git_tree_entry
*
e1
,
const
git_tree_entry
*
e2
)
{
const
git_tree_entry
*
entry_a
=
(
const
git_tree_entry
*
)(
a
);
const
git_tree_entry
*
entry_b
=
(
const
git_tree_entry
*
)(
b
);
return
git_path_cmp
(
entry_a
->
filename
,
entry_a
->
filename_len
,
git_tree_entry__is_tree
(
entry_a
),
entry_b
->
filename
,
entry_b
->
filename_len
,
git_tree_entry__is_tree
(
entry_b
));
e1
->
filename
,
e1
->
filename_len
,
git_tree_entry__is_tree
(
e1
),
e2
->
filename
,
e2
->
filename_len
,
git_tree_entry__is_tree
(
e2
));
}
int
git_tree_entry_icmp
(
const
git_tree_entry
*
e1
,
const
git_tree_entry
*
e2
)
{
return
git_path_icmp
(
e1
->
filename
,
e1
->
filename_len
,
git_tree_entry__is_tree
(
e1
),
e2
->
filename
,
e2
->
filename_len
,
git_tree_entry__is_tree
(
e2
));
}
static
int
entry_sort_cmp
(
const
void
*
a
,
const
void
*
b
)
{
return
git_tree_entry_cmp
((
const
git_tree_entry
*
)
a
,
(
const
git_tree_entry
*
)
b
);
}
static
git_tree_entry
*
alloc_entry
(
const
char
*
filename
)
...
...
src/tree.h
View file @
34a4ad46
...
...
@@ -39,6 +39,8 @@ GIT_INLINE(bool) git_tree_entry__is_tree(const struct git_tree_entry *e)
return
(
S_ISDIR
(
e
->
attr
)
&&
!
S_ISGITLINK
(
e
->
attr
));
}
extern
int
git_tree_entry_icmp
(
const
git_tree_entry
*
e1
,
const
git_tree_entry
*
e2
);
void
git_tree__free
(
git_tree
*
tree
);
int
git_tree__parse
(
git_tree
*
tree
,
git_odb_object
*
obj
);
...
...
src/tsort.c
View file @
34a4ad46
...
...
@@ -23,9 +23,8 @@
# define MIN(x,y) (((x) < (y) ? (x) : (y)))
#endif
typedef
int
(
*
cmp_ptr_t
)(
const
void
*
,
const
void
*
);
static
int
binsearch
(
void
**
dst
,
const
void
*
x
,
size_t
size
,
cmp_ptr_t
cmp
)
static
int
binsearch
(
void
**
dst
,
const
void
*
x
,
size_t
size
,
git__tsort_r_cmp
cmp
,
void
*
payload
)
{
int
l
,
c
,
r
;
void
*
lx
,
*
cx
;
...
...
@@ -38,12 +37,12 @@ static int binsearch(void **dst, const void *x, size_t size, cmp_ptr_t cmp)
lx
=
dst
[
l
];
/* check for beginning conditions */
if
(
cmp
(
x
,
lx
)
<
0
)
if
(
cmp
(
x
,
lx
,
payload
)
<
0
)
return
0
;
else
if
(
cmp
(
x
,
lx
)
==
0
)
{
else
if
(
cmp
(
x
,
lx
,
payload
)
==
0
)
{
int
i
=
1
;
while
(
cmp
(
x
,
dst
[
i
])
==
0
)
while
(
cmp
(
x
,
dst
[
i
]
,
payload
)
==
0
)
i
++
;
return
i
;
}
...
...
@@ -51,7 +50,7 @@ static int binsearch(void **dst, const void *x, size_t size, cmp_ptr_t cmp)
/* guaranteed not to be >= rx */
cx
=
dst
[
c
];
while
(
1
)
{
const
int
val
=
cmp
(
x
,
cx
);
const
int
val
=
cmp
(
x
,
cx
,
payload
);
if
(
val
<
0
)
{
if
(
c
-
l
<=
1
)
return
c
;
r
=
c
;
...
...
@@ -62,7 +61,7 @@ static int binsearch(void **dst, const void *x, size_t size, cmp_ptr_t cmp)
}
else
{
do
{
cx
=
dst
[
++
c
];
}
while
(
cmp
(
x
,
cx
)
==
0
);
}
while
(
cmp
(
x
,
cx
,
payload
)
==
0
);
return
c
;
}
c
=
l
+
((
r
-
l
)
>>
1
);
...
...
@@ -71,7 +70,8 @@ static int binsearch(void **dst, const void *x, size_t size, cmp_ptr_t cmp)
}
/* Binary insertion sort, but knowing that the first "start" entries are sorted. Used in timsort. */
static
void
bisort
(
void
**
dst
,
size_t
start
,
size_t
size
,
cmp_ptr_t
cmp
)
static
void
bisort
(
void
**
dst
,
size_t
start
,
size_t
size
,
git__tsort_r_cmp
cmp
,
void
*
payload
)
{
size_t
i
;
void
*
x
;
...
...
@@ -80,12 +80,12 @@ static void bisort(void **dst, size_t start, size_t size, cmp_ptr_t cmp)
for
(
i
=
start
;
i
<
size
;
i
++
)
{
int
j
;
/* If this entry is already correct, just move along */
if
(
cmp
(
dst
[
i
-
1
],
dst
[
i
])
<=
0
)
if
(
cmp
(
dst
[
i
-
1
],
dst
[
i
]
,
payload
)
<=
0
)
continue
;
/* Else we need to find the right place, shift everything over, and squeeze in */
x
=
dst
[
i
];
location
=
binsearch
(
dst
,
x
,
i
,
cmp
);
location
=
binsearch
(
dst
,
x
,
i
,
cmp
,
payload
);
for
(
j
=
(
int
)
i
-
1
;
j
>=
location
;
j
--
)
{
dst
[
j
+
1
]
=
dst
[
j
];
}
...
...
@@ -102,7 +102,8 @@ struct tsort_run {
struct
tsort_store
{
size_t
alloc
;
cmp_ptr_t
cmp
;
git__tsort_r_cmp
cmp
;
void
*
payload
;
void
**
storage
;
};
...
...
@@ -118,7 +119,8 @@ static void reverse_elements(void **dst, ssize_t start, ssize_t end)
}
}
static
ssize_t
count_run
(
void
**
dst
,
ssize_t
start
,
ssize_t
size
,
struct
tsort_store
*
store
)
static
ssize_t
count_run
(
void
**
dst
,
ssize_t
start
,
ssize_t
size
,
struct
tsort_store
*
store
)
{
ssize_t
curr
=
start
+
2
;
...
...
@@ -126,7 +128,7 @@ static ssize_t count_run(void **dst, ssize_t start, ssize_t size, struct tsort_s
return
1
;
if
(
start
>=
size
-
2
)
{
if
(
store
->
cmp
(
dst
[
size
-
2
],
dst
[
size
-
1
])
>
0
)
{
if
(
store
->
cmp
(
dst
[
size
-
2
],
dst
[
size
-
1
]
,
store
->
payload
)
>
0
)
{
void
*
tmp
=
dst
[
size
-
1
];
dst
[
size
-
1
]
=
dst
[
size
-
2
];
dst
[
size
-
2
]
=
tmp
;
...
...
@@ -135,13 +137,15 @@ static ssize_t count_run(void **dst, ssize_t start, ssize_t size, struct tsort_s
return
2
;
}
if
(
store
->
cmp
(
dst
[
start
],
dst
[
start
+
1
])
<=
0
)
{
while
(
curr
<
size
-
1
&&
store
->
cmp
(
dst
[
curr
-
1
],
dst
[
curr
])
<=
0
)
if
(
store
->
cmp
(
dst
[
start
],
dst
[
start
+
1
],
store
->
payload
)
<=
0
)
{
while
(
curr
<
size
-
1
&&
store
->
cmp
(
dst
[
curr
-
1
],
dst
[
curr
],
store
->
payload
)
<=
0
)
curr
++
;
return
curr
-
start
;
}
else
{
while
(
curr
<
size
-
1
&&
store
->
cmp
(
dst
[
curr
-
1
],
dst
[
curr
])
>
0
)
while
(
curr
<
size
-
1
&&
store
->
cmp
(
dst
[
curr
-
1
],
dst
[
curr
],
store
->
payload
)
>
0
)
curr
++
;
/* reverse in-place */
...
...
@@ -219,7 +223,7 @@ static void merge(void **dst, const struct tsort_run *stack, ssize_t stack_curr,
for
(
k
=
curr
;
k
<
curr
+
A
+
B
;
k
++
)
{
if
((
i
<
A
)
&&
(
j
<
curr
+
A
+
B
))
{
if
(
store
->
cmp
(
storage
[
i
],
dst
[
j
])
<=
0
)
if
(
store
->
cmp
(
storage
[
i
],
dst
[
j
]
,
store
->
payload
)
<=
0
)
dst
[
k
]
=
storage
[
i
++
];
else
dst
[
k
]
=
dst
[
j
++
];
...
...
@@ -235,7 +239,7 @@ static void merge(void **dst, const struct tsort_run *stack, ssize_t stack_curr,
for
(
k
=
curr
+
A
+
B
-
1
;
k
>=
curr
;
k
--
)
{
if
((
i
>=
0
)
&&
(
j
>=
curr
))
{
if
(
store
->
cmp
(
dst
[
j
],
storage
[
i
])
>
0
)
if
(
store
->
cmp
(
dst
[
j
],
storage
[
i
]
,
store
->
payload
)
>
0
)
dst
[
k
]
=
dst
[
j
--
];
else
dst
[
k
]
=
storage
[
i
--
];
...
...
@@ -307,7 +311,7 @@ static ssize_t collapse(void **dst, struct tsort_run *stack, ssize_t stack_curr,
if (run < minrun) run = minrun;\
if (run > (ssize_t)size - curr) run = size - curr;\
if (run > len) {\
bisort(&dst[curr], len, run, cmp);\
bisort(&dst[curr], len, run, cmp
, payload
);\
len = run;\
}\
run_stack[stack_curr].start = curr;\
...
...
@@ -329,7 +333,8 @@ static ssize_t collapse(void **dst, struct tsort_run *stack, ssize_t stack_curr,
}\
while (0)
void
git__tsort
(
void
**
dst
,
size_t
size
,
cmp_ptr_t
cmp
)
void
git__tsort_r
(
void
**
dst
,
size_t
size
,
git__tsort_r_cmp
cmp
,
void
*
payload
)
{
struct
tsort_store
_store
,
*
store
=
&
_store
;
struct
tsort_run
run_stack
[
128
];
...
...
@@ -340,7 +345,7 @@ void git__tsort(void **dst, size_t size, cmp_ptr_t cmp)
ssize_t
minrun
;
if
(
size
<
64
)
{
bisort
(
dst
,
1
,
size
,
cmp
);
bisort
(
dst
,
1
,
size
,
cmp
,
payload
);
return
;
}
...
...
@@ -351,6 +356,7 @@ void git__tsort(void **dst, size_t size, cmp_ptr_t cmp)
store
->
alloc
=
0
;
store
->
storage
=
NULL
;
store
->
cmp
=
cmp
;
store
->
payload
=
payload
;
PUSH_NEXT
();
PUSH_NEXT
();
...
...
@@ -365,3 +371,13 @@ void git__tsort(void **dst, size_t size, cmp_ptr_t cmp)
PUSH_NEXT
();
}
}
static
int
tsort_r_cmp
(
const
void
*
a
,
const
void
*
b
,
void
*
payload
)
{
return
((
git__tsort_cmp
)
payload
)(
a
,
b
);
}
void
git__tsort
(
void
**
dst
,
size_t
size
,
git__tsort_cmp
cmp
)
{
git__tsort_r
(
dst
,
size
,
tsort_r_cmp
,
cmp
);
}
src/util.c
View file @
34a4ad46
...
...
@@ -493,6 +493,37 @@ int git__bsearch(
return
(
cmp
==
0
)
?
0
:
-
1
;
}
int
git__bsearch_r
(
void
**
array
,
size_t
array_len
,
const
void
*
key
,
int
(
*
compare_r
)(
const
void
*
,
const
void
*
,
void
*
),
void
*
payload
,
size_t
*
position
)
{
unsigned
int
lim
;
int
cmp
=
-
1
;
void
**
part
,
**
base
=
array
;
for
(
lim
=
(
unsigned
int
)
array_len
;
lim
!=
0
;
lim
>>=
1
)
{
part
=
base
+
(
lim
>>
1
);
cmp
=
(
*
compare_r
)(
key
,
*
part
,
payload
);
if
(
cmp
==
0
)
{
base
=
part
;
break
;
}
if
(
cmp
>
0
)
{
/* key > p; take right partition */
base
=
part
+
1
;
lim
--
;
}
/* else take left partition */
}
if
(
position
)
*
position
=
(
base
-
array
);
return
(
cmp
==
0
)
?
0
:
-
1
;
}
/**
* A strcmp wrapper
*
...
...
src/util.h
View file @
34a4ad46
...
...
@@ -119,7 +119,15 @@ GIT_INLINE(const char *) git__next_line(const char *s)
return
s
;
}
extern
void
git__tsort
(
void
**
dst
,
size_t
size
,
int
(
*
cmp
)(
const
void
*
,
const
void
*
));
typedef
int
(
*
git__tsort_cmp
)(
const
void
*
a
,
const
void
*
b
);
extern
void
git__tsort
(
void
**
dst
,
size_t
size
,
git__tsort_cmp
cmp
);
typedef
int
(
*
git__tsort_r_cmp
)(
const
void
*
a
,
const
void
*
b
,
void
*
payload
);
extern
void
git__tsort_r
(
void
**
dst
,
size_t
size
,
git__tsort_r_cmp
cmp
,
void
*
payload
);
/**
* @param position If non-NULL, this will be set to the position where the
...
...
@@ -130,7 +138,15 @@ extern int git__bsearch(
void
**
array
,
size_t
array_len
,
const
void
*
key
,
int
(
*
compare
)(
const
void
*
,
const
void
*
),
int
(
*
compare
)(
const
void
*
key
,
const
void
*
element
),
size_t
*
position
);
extern
int
git__bsearch_r
(
void
**
array
,
size_t
array_len
,
const
void
*
key
,
int
(
*
compare_r
)(
const
void
*
key
,
const
void
*
element
,
void
*
payload
),
void
*
payload
,
size_t
*
position
);
extern
int
git__strcmp_cb
(
const
void
*
a
,
const
void
*
b
);
...
...
tests-clar/diff/iterator.c
View file @
34a4ad46
...
...
@@ -35,7 +35,8 @@ static void tree_iterator_test(
git_repository
*
repo
=
cl_git_sandbox_init
(
sandbox
);
cl_assert
(
t
=
resolve_commit_oid_to_tree
(
repo
,
treeish
));
cl_git_pass
(
git_iterator_for_tree_range
(
&
i
,
t
,
start
,
end
));
cl_git_pass
(
git_iterator_for_tree_range
(
&
i
,
t
,
GIT_ITERATOR_DONT_IGNORE_CASE
,
start
,
end
));
/* test loop */
cl_git_pass
(
git_iterator_current
(
i
,
&
entry
));
...
...
@@ -304,7 +305,8 @@ void test_diff_iterator__tree_special_functions(void)
repo
,
"24fa9a9fc4e202313e24b648087495441dab432b"
);
cl_assert
(
t
!=
NULL
);
cl_git_pass
(
git_iterator_for_tree_range
(
&
i
,
t
,
NULL
,
NULL
));
cl_git_pass
(
git_iterator_for_tree_range
(
&
i
,
t
,
GIT_ITERATOR_DONT_IGNORE_CASE
,
NULL
,
NULL
));
cl_git_pass
(
git_iterator_current
(
i
,
&
entry
));
while
(
entry
!=
NULL
)
{
...
...
@@ -355,12 +357,14 @@ static void index_iterator_test(
const
char
**
expected_names
,
const
char
**
expected_oids
)
{
git_index
*
index
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
int
count
=
0
;
git_repository
*
repo
=
cl_git_sandbox_init
(
sandbox
);
cl_git_pass
(
git_iterator_for_repo_index_range
(
&
i
,
repo
,
start
,
end
));
cl_git_pass
(
git_repository_index
(
&
index
,
repo
));
cl_git_pass
(
git_iterator_for_index_range
(
&
i
,
index
,
0
,
start
,
end
));
cl_git_pass
(
git_iterator_current
(
i
,
&
entry
));
while
(
entry
!=
NULL
)
{
...
...
@@ -378,6 +382,7 @@ static void index_iterator_test(
}
git_iterator_free
(
i
);
git_index_free
(
index
);
cl_assert_equal_i
(
expected_count
,
count
);
}
...
...
@@ -533,7 +538,7 @@ static void workdir_iterator_test(
int
count
=
0
,
count_all
=
0
,
count_all_post_reset
=
0
;
git_repository
*
repo
=
cl_git_sandbox_init
(
sandbox
);
cl_git_pass
(
git_iterator_for_workdir_range
(
&
i
,
repo
,
start
,
end
));
cl_git_pass
(
git_iterator_for_workdir_range
(
&
i
,
repo
,
0
,
start
,
end
));
cl_git_pass
(
git_iterator_current
(
i
,
&
entry
));
while
(
entry
!=
NULL
)
{
...
...
@@ -731,7 +736,7 @@ void test_diff_iterator__workdir_builtin_ignores(void)
cl_git_mkfile
(
"attr/sub/.git"
,
"whatever"
);
cl_git_pass
(
git_iterator_for_workdir_range
(
&
i
,
repo
,
"dir"
,
"sub/sub/file"
));
git_iterator_for_workdir_range
(
&
i
,
repo
,
0
,
"dir"
,
"sub/sub/file"
));
cl_git_pass
(
git_iterator_current
(
i
,
&
entry
));
for
(
idx
=
0
;
entry
!=
NULL
;
++
idx
)
{
...
...
@@ -750,3 +755,155 @@ void test_diff_iterator__workdir_builtin_ignores(void)
git_iterator_free
(
i
);
}
static
void
check_wd_first_through_third_range
(
git_repository
*
repo
,
const
char
*
start
,
const
char
*
end
)
{
git_iterator
*
i
;
const
git_index_entry
*
entry
;
int
idx
;
static
const
char
*
expected
[]
=
{
"FIRST"
,
"second"
,
"THIRD"
,
NULL
};
cl_git_pass
(
git_iterator_for_workdir_range
(
&
i
,
repo
,
GIT_ITERATOR_IGNORE_CASE
,
start
,
end
));
cl_git_pass
(
git_iterator_current
(
i
,
&
entry
));
for
(
idx
=
0
;
entry
!=
NULL
;
++
idx
)
{
cl_assert_equal_s
(
expected
[
idx
],
entry
->
path
);
if
(
S_ISDIR
(
entry
->
mode
))
cl_git_pass
(
git_iterator_advance_into_directory
(
i
,
&
entry
));
else
cl_git_pass
(
git_iterator_advance
(
i
,
&
entry
));
}
cl_assert
(
expected
[
idx
]
==
NULL
);
git_iterator_free
(
i
);
}
void
test_diff_iterator__workdir_handles_icase_range
(
void
)
{
git_repository
*
repo
;
repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
cl_git_remove_placeholders
(
git_repository_path
(
repo
),
"dummy-marker.txt"
);
cl_git_mkfile
(
"empty_standard_repo/before"
,
"whatever
\n
"
);
cl_git_mkfile
(
"empty_standard_repo/FIRST"
,
"whatever
\n
"
);
cl_git_mkfile
(
"empty_standard_repo/second"
,
"whatever
\n
"
);
cl_git_mkfile
(
"empty_standard_repo/THIRD"
,
"whatever
\n
"
);
cl_git_mkfile
(
"empty_standard_repo/zafter"
,
"whatever
\n
"
);
cl_git_mkfile
(
"empty_standard_repo/Zlast"
,
"whatever
\n
"
);
check_wd_first_through_third_range
(
repo
,
"first"
,
"third"
);
check_wd_first_through_third_range
(
repo
,
"FIRST"
,
"THIRD"
);
check_wd_first_through_third_range
(
repo
,
"first"
,
"THIRD"
);
check_wd_first_through_third_range
(
repo
,
"FIRST"
,
"third"
);
check_wd_first_through_third_range
(
repo
,
"FirSt"
,
"tHiRd"
);
}
static
void
check_tree_range
(
git_repository
*
repo
,
const
char
*
start
,
const
char
*
end
,
bool
ignore_case
,
int
expected_count
)
{
git_tree
*
head
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
int
count
;
cl_git_pass
(
git_repository_head_tree
(
&
head
,
repo
));
cl_git_pass
(
git_iterator_for_tree_range
(
&
i
,
head
,
ignore_case
?
GIT_ITERATOR_IGNORE_CASE
:
GIT_ITERATOR_DONT_IGNORE_CASE
,
start
,
end
));
cl_git_pass
(
git_iterator_current
(
i
,
&
entry
));
for
(
count
=
0
;
entry
!=
NULL
;
)
{
++
count
;
cl_git_pass
(
git_iterator_advance
(
i
,
&
entry
));
}
cl_assert_equal_i
(
expected_count
,
count
);
git_iterator_free
(
i
);
git_tree_free
(
head
);
}
void
test_diff_iterator__tree_handles_icase_range
(
void
)
{
git_repository
*
repo
;
repo
=
cl_git_sandbox_init
(
"testrepo"
);
check_tree_range
(
repo
,
"B"
,
"C"
,
false
,
0
);
check_tree_range
(
repo
,
"B"
,
"C"
,
true
,
1
);
check_tree_range
(
repo
,
"a"
,
"z"
,
false
,
3
);
check_tree_range
(
repo
,
"a"
,
"z"
,
true
,
4
);
}
static
void
check_index_range
(
git_repository
*
repo
,
const
char
*
start
,
const
char
*
end
,
bool
ignore_case
,
int
expected_count
)
{
git_index
*
index
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
int
count
,
caps
;
bool
is_ignoring_case
;
cl_git_pass
(
git_repository_index
(
&
index
,
repo
));
caps
=
git_index_caps
(
index
);
is_ignoring_case
=
((
caps
&
GIT_INDEXCAP_IGNORE_CASE
)
!=
0
);
if
(
ignore_case
!=
is_ignoring_case
)
cl_git_pass
(
git_index_set_caps
(
index
,
caps
^
GIT_INDEXCAP_IGNORE_CASE
));
cl_git_pass
(
git_iterator_for_index_range
(
&
i
,
index
,
0
,
start
,
end
));
cl_assert
(
git_iterator_ignore_case
(
i
)
==
ignore_case
);
cl_git_pass
(
git_iterator_current
(
i
,
&
entry
));
for
(
count
=
0
;
entry
!=
NULL
;
)
{
++
count
;
cl_git_pass
(
git_iterator_advance
(
i
,
&
entry
));
}
cl_assert_equal_i
(
expected_count
,
count
);
git_iterator_free
(
i
);
git_index_free
(
index
);
}
void
test_diff_iterator__index_handles_icase_range
(
void
)
{
git_repository
*
repo
;
git_index
*
index
;
git_tree
*
head
;
repo
=
cl_git_sandbox_init
(
"testrepo"
);
/* reset index to match HEAD */
cl_git_pass
(
git_repository_head_tree
(
&
head
,
repo
));
cl_git_pass
(
git_repository_index
(
&
index
,
repo
));
cl_git_pass
(
git_index_read_tree
(
index
,
head
));
cl_git_pass
(
git_index_write
(
index
));
git_tree_free
(
head
);
git_index_free
(
index
);
/* do some ranged iterator checks toggling case sensitivity */
check_index_range
(
repo
,
"B"
,
"C"
,
false
,
0
);
check_index_range
(
repo
,
"B"
,
"C"
,
true
,
1
);
check_index_range
(
repo
,
"a"
,
"z"
,
false
,
3
);
check_index_range
(
repo
,
"a"
,
"z"
,
true
,
4
);
}
tests-clar/status/worktree.c
View file @
34a4ad46
...
...
@@ -580,3 +580,90 @@ void test_status_worktree__conflicted_item(void)
git_index_free
(
index
);
}
static
void
stage_and_commit
(
git_repository
*
repo
,
const
char
*
path
)
{
git_oid
tree_oid
,
commit_oid
;
git_tree
*
tree
;
git_signature
*
signature
;
git_index
*
index
;
cl_git_pass
(
git_repository_index
(
&
index
,
repo
));
cl_git_pass
(
git_index_add_from_workdir
(
index
,
path
));
cl_git_pass
(
git_index_write
(
index
));
cl_git_pass
(
git_index_write_tree
(
&
tree_oid
,
index
));
git_index_free
(
index
);
cl_git_pass
(
git_tree_lookup
(
&
tree
,
repo
,
&
tree_oid
));
cl_git_pass
(
git_signature_new
(
&
signature
,
"nulltoken"
,
"emeric.fermas@gmail.com"
,
1323847743
,
60
));
cl_git_pass
(
git_commit_create_v
(
&
commit_oid
,
repo
,
"HEAD"
,
signature
,
signature
,
NULL
,
"Initial commit
\n\0
"
,
tree
,
0
));
git_tree_free
(
tree
);
git_signature_free
(
signature
);
}
static
void
assert_ignore_case
(
bool
should_ignore_case
,
int
expected_lower_cased_file_status
,
int
expected_camel_cased_file_status
)
{
git_config
*
config
;
unsigned
int
status
;
git_buf
lower_case_path
=
GIT_BUF_INIT
,
camel_case_path
=
GIT_BUF_INIT
;
git_repository
*
repo
,
*
repo2
;
repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
cl_git_remove_placeholders
(
git_repository_path
(
repo
),
"dummy-marker.txt"
);
cl_git_pass
(
git_repository_config
(
&
config
,
repo
));
cl_git_pass
(
git_config_set_bool
(
config
,
"core.ignorecase"
,
should_ignore_case
));
git_config_free
(
config
);
cl_git_pass
(
git_buf_joinpath
(
&
lower_case_path
,
git_repository_workdir
(
repo
),
"plop"
));
cl_git_mkfile
(
git_buf_cstr
(
&
lower_case_path
),
""
);
stage_and_commit
(
repo
,
"plop"
);
cl_git_pass
(
git_repository_open
(
&
repo2
,
"./empty_standard_repo"
));
cl_git_pass
(
git_status_file
(
&
status
,
repo2
,
"plop"
));
cl_assert_equal_i
(
GIT_STATUS_CURRENT
,
status
);
cl_git_pass
(
git_buf_joinpath
(
&
camel_case_path
,
git_repository_workdir
(
repo
),
"Plop"
));
cl_git_pass
(
p_rename
(
git_buf_cstr
(
&
lower_case_path
),
git_buf_cstr
(
&
camel_case_path
)));
cl_git_pass
(
git_status_file
(
&
status
,
repo2
,
"plop"
));
cl_assert_equal_i
(
expected_lower_cased_file_status
,
status
);
cl_git_pass
(
git_status_file
(
&
status
,
repo2
,
"Plop"
));
cl_assert_equal_i
(
expected_camel_cased_file_status
,
status
);
git_repository_free
(
repo2
);
git_buf_free
(
&
lower_case_path
);
git_buf_free
(
&
camel_case_path
);
}
void
test_status_worktree__file_status_honors_core_ignorecase_true
(
void
)
{
assert_ignore_case
(
true
,
GIT_STATUS_CURRENT
,
GIT_STATUS_CURRENT
);
}
void
test_status_worktree__file_status_honors_core_ignorecase_false
(
void
)
{
assert_ignore_case
(
false
,
GIT_STATUS_WT_DELETED
,
GIT_STATUS_WT_NEW
);
}
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