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
f2d110f1
Commit
f2d110f1
authored
Jun 20, 2013
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1662 from arrbee/examples-like-git
Command line status example (with bug fixes)
parents
8b2fa181
94ef2a35
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
596 additions
and
19 deletions
+596
-19
examples/Makefile
+1
-1
examples/status.c
+443
-0
include/git2/status.h
+8
-0
src/attr_file.c
+1
-1
src/diff.c
+14
-9
src/index.c
+5
-5
src/status.c
+10
-2
src/submodule.c
+1
-1
src/vector.h
+9
-0
tests-clar/diff/workdir.c
+20
-0
tests-clar/status/status_helpers.c
+3
-0
tests-clar/status/status_helpers.h
+1
-0
tests-clar/status/worktree.c
+80
-0
No files found.
examples/Makefile
View file @
f2d110f1
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
CC
=
gcc
CC
=
gcc
CFLAGS
=
-g
-I
../include
-I
../src
-Wall
-Wextra
-Wmissing-prototypes
-Wno-missing-field-initializers
CFLAGS
=
-g
-I
../include
-I
../src
-Wall
-Wextra
-Wmissing-prototypes
-Wno-missing-field-initializers
LFLAGS
=
-L
../build
-lgit2
-lz
LFLAGS
=
-L
../build
-lgit2
-lz
APPS
=
general showindex diff rev-list cat-file
APPS
=
general showindex diff rev-list cat-file
status
all
:
$(APPS)
all
:
$(APPS)
...
...
examples/status.c
0 → 100644
View file @
f2d110f1
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include <git2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum
{
FORMAT_DEFAULT
=
0
,
FORMAT_LONG
=
1
,
FORMAT_SHORT
=
2
,
FORMAT_PORCELAIN
=
3
,
};
#define MAX_PATHSPEC 8
/*
* This example demonstrates the use of the libgit2 status APIs,
* particularly the `git_status_list` object, to roughly simulate the
* output of running `git status`. It serves as a simple example of
* using those APIs to get basic status information.
*
* This does not have:
* - Robust error handling
* - Colorized or paginated output formatting
*
* This does have:
* - Examples of translating command line arguments to the status
* options settings to mimic `git status` results.
* - A sample status formatter that matches the default "long" format
* from `git status`
* - A sample status formatter that matches the "short" format
*/
static
void
check
(
int
error
,
const
char
*
message
,
const
char
*
extra
)
{
const
git_error
*
lg2err
;
const
char
*
lg2msg
=
""
,
*
lg2spacer
=
""
;
if
(
!
error
)
return
;
if
((
lg2err
=
giterr_last
())
!=
NULL
&&
lg2err
->
message
!=
NULL
)
{
lg2msg
=
lg2err
->
message
;
lg2spacer
=
" - "
;
}
if
(
extra
)
fprintf
(
stderr
,
"%s '%s' [%d]%s%s
\n
"
,
message
,
extra
,
error
,
lg2spacer
,
lg2msg
);
else
fprintf
(
stderr
,
"%s [%d]%s%s
\n
"
,
message
,
error
,
lg2spacer
,
lg2msg
);
exit
(
1
);
}
static
void
fail
(
const
char
*
message
)
{
check
(
-
1
,
message
,
NULL
);
}
static
void
show_branch
(
git_repository
*
repo
,
int
format
)
{
int
error
=
0
;
const
char
*
branch
=
NULL
;
git_reference
*
head
=
NULL
;
error
=
git_repository_head
(
&
head
,
repo
);
if
(
error
==
GIT_EORPHANEDHEAD
||
error
==
GIT_ENOTFOUND
)
branch
=
NULL
;
else
if
(
!
error
)
{
branch
=
git_reference_name
(
head
);
if
(
!
strncmp
(
branch
,
"refs/heads/"
,
strlen
(
"refs/heads/"
)))
branch
+=
strlen
(
"refs/heads/"
);
}
else
check
(
error
,
"failed to get current branch"
,
NULL
);
if
(
format
==
FORMAT_LONG
)
printf
(
"# On branch %s
\n
"
,
branch
?
branch
:
"Not currently on any branch."
);
else
printf
(
"## %s
\n
"
,
branch
?
branch
:
"HEAD (no branch)"
);
git_reference_free
(
head
);
}
static
void
print_long
(
git_repository
*
repo
,
git_status_list
*
status
)
{
size_t
i
,
maxi
=
git_status_list_entrycount
(
status
);
const
git_status_entry
*
s
;
int
header
=
0
,
changes_in_index
=
0
;
int
changed_in_workdir
=
0
,
rm_in_workdir
=
0
;
const
char
*
old_path
,
*
new_path
;
(
void
)
repo
;
/* print index changes */
for
(
i
=
0
;
i
<
maxi
;
++
i
)
{
char
*
istatus
=
NULL
;
s
=
git_status_byindex
(
status
,
i
);
if
(
s
->
status
==
GIT_STATUS_CURRENT
)
continue
;
if
(
s
->
status
&
GIT_STATUS_WT_DELETED
)
rm_in_workdir
=
1
;
if
(
s
->
status
&
GIT_STATUS_INDEX_NEW
)
istatus
=
"new file: "
;
if
(
s
->
status
&
GIT_STATUS_INDEX_MODIFIED
)
istatus
=
"modified: "
;
if
(
s
->
status
&
GIT_STATUS_INDEX_DELETED
)
istatus
=
"deleted: "
;
if
(
s
->
status
&
GIT_STATUS_INDEX_RENAMED
)
istatus
=
"renamed: "
;
if
(
s
->
status
&
GIT_STATUS_INDEX_TYPECHANGE
)
istatus
=
"typechange:"
;
if
(
istatus
==
NULL
)
continue
;
if
(
!
header
)
{
printf
(
"# Changes to be committed:
\n
"
);
printf
(
"# (use
\"
git reset HEAD <file>...
\"
to unstage)
\n
"
);
printf
(
"#
\n
"
);
header
=
1
;
}
old_path
=
s
->
head_to_index
->
old_file
.
path
;
new_path
=
s
->
head_to_index
->
new_file
.
path
;
if
(
old_path
&&
new_path
&&
strcmp
(
old_path
,
new_path
))
printf
(
"#
\t
%s %s -> %s
\n
"
,
istatus
,
old_path
,
new_path
);
else
printf
(
"#
\t
%s %s
\n
"
,
istatus
,
old_path
?
old_path
:
new_path
);
}
if
(
header
)
{
changes_in_index
=
1
;
printf
(
"#
\n
"
);
}
header
=
0
;
/* print workdir changes to tracked files */
for
(
i
=
0
;
i
<
maxi
;
++
i
)
{
char
*
wstatus
=
NULL
;
s
=
git_status_byindex
(
status
,
i
);
if
(
s
->
status
==
GIT_STATUS_CURRENT
||
s
->
index_to_workdir
==
NULL
)
continue
;
if
(
s
->
status
&
GIT_STATUS_WT_MODIFIED
)
wstatus
=
"modified: "
;
if
(
s
->
status
&
GIT_STATUS_WT_DELETED
)
wstatus
=
"deleted: "
;
if
(
s
->
status
&
GIT_STATUS_WT_RENAMED
)
wstatus
=
"renamed: "
;
if
(
s
->
status
&
GIT_STATUS_WT_TYPECHANGE
)
wstatus
=
"typechange:"
;
if
(
wstatus
==
NULL
)
continue
;
if
(
!
header
)
{
printf
(
"# Changes not staged for commit:
\n
"
);
printf
(
"# (use
\"
git add%s <file>...
\"
to update what will be committed)
\n
"
,
rm_in_workdir
?
"/rm"
:
""
);
printf
(
"# (use
\"
git checkout -- <file>...
\"
to discard changes in working directory)
\n
"
);
printf
(
"#
\n
"
);
header
=
1
;
}
old_path
=
s
->
index_to_workdir
->
old_file
.
path
;
new_path
=
s
->
index_to_workdir
->
new_file
.
path
;
if
(
old_path
&&
new_path
&&
strcmp
(
old_path
,
new_path
))
printf
(
"#
\t
%s %s -> %s
\n
"
,
wstatus
,
old_path
,
new_path
);
else
printf
(
"#
\t
%s %s
\n
"
,
wstatus
,
old_path
?
old_path
:
new_path
);
}
if
(
header
)
{
changed_in_workdir
=
1
;
printf
(
"#
\n
"
);
}
header
=
0
;
/* print untracked files */
header
=
0
;
for
(
i
=
0
;
i
<
maxi
;
++
i
)
{
s
=
git_status_byindex
(
status
,
i
);
if
(
s
->
status
==
GIT_STATUS_WT_NEW
)
{
if
(
!
header
)
{
printf
(
"# Untracked files:
\n
"
);
printf
(
"# (use
\"
git add <file>...
\"
to include in what will be committed)
\n
"
);
printf
(
"#
\n
"
);
header
=
1
;
}
printf
(
"#
\t
%s
\n
"
,
s
->
index_to_workdir
->
old_file
.
path
);
}
}
header
=
0
;
/* print ignored files */
for
(
i
=
0
;
i
<
maxi
;
++
i
)
{
s
=
git_status_byindex
(
status
,
i
);
if
(
s
->
status
==
GIT_STATUS_IGNORED
)
{
if
(
!
header
)
{
printf
(
"# Ignored files:
\n
"
);
printf
(
"# (use
\"
git add -f <file>...
\"
to include in what will be committed)
\n
"
);
printf
(
"#
\n
"
);
header
=
1
;
}
printf
(
"#
\t
%s
\n
"
,
s
->
index_to_workdir
->
old_file
.
path
);
}
}
if
(
!
changes_in_index
&&
changed_in_workdir
)
printf
(
"no changes added to commit (use
\"
git add
\"
and/or
\"
git commit -a
\"
)
\n
"
);
}
static
void
print_short
(
git_repository
*
repo
,
git_status_list
*
status
)
{
size_t
i
,
maxi
=
git_status_list_entrycount
(
status
);
const
git_status_entry
*
s
;
char
istatus
,
wstatus
;
const
char
*
extra
,
*
a
,
*
b
,
*
c
;
for
(
i
=
0
;
i
<
maxi
;
++
i
)
{
s
=
git_status_byindex
(
status
,
i
);
if
(
s
->
status
==
GIT_STATUS_CURRENT
)
continue
;
a
=
b
=
c
=
NULL
;
istatus
=
wstatus
=
' '
;
extra
=
""
;
if
(
s
->
status
&
GIT_STATUS_INDEX_NEW
)
istatus
=
'A'
;
if
(
s
->
status
&
GIT_STATUS_INDEX_MODIFIED
)
istatus
=
'M'
;
if
(
s
->
status
&
GIT_STATUS_INDEX_DELETED
)
istatus
=
'D'
;
if
(
s
->
status
&
GIT_STATUS_INDEX_RENAMED
)
istatus
=
'R'
;
if
(
s
->
status
&
GIT_STATUS_INDEX_TYPECHANGE
)
istatus
=
'T'
;
if
(
s
->
status
&
GIT_STATUS_WT_NEW
)
{
if
(
istatus
==
' '
)
istatus
=
'?'
;
wstatus
=
'?'
;
}
if
(
s
->
status
&
GIT_STATUS_WT_MODIFIED
)
wstatus
=
'M'
;
if
(
s
->
status
&
GIT_STATUS_WT_DELETED
)
wstatus
=
'D'
;
if
(
s
->
status
&
GIT_STATUS_WT_RENAMED
)
wstatus
=
'R'
;
if
(
s
->
status
&
GIT_STATUS_WT_TYPECHANGE
)
wstatus
=
'T'
;
if
(
s
->
status
&
GIT_STATUS_IGNORED
)
{
istatus
=
'!'
;
wstatus
=
'!'
;
}
if
(
istatus
==
'?'
&&
wstatus
==
'?'
)
continue
;
if
(
s
->
index_to_workdir
&&
s
->
index_to_workdir
->
new_file
.
mode
==
GIT_FILEMODE_COMMIT
)
{
git_submodule
*
sm
=
NULL
;
unsigned
int
smstatus
=
0
;
if
(
!
git_submodule_lookup
(
&
sm
,
repo
,
s
->
index_to_workdir
->
new_file
.
path
)
&&
!
git_submodule_status
(
&
smstatus
,
sm
))
{
if
(
smstatus
&
GIT_SUBMODULE_STATUS_WD_MODIFIED
)
extra
=
" (new commits)"
;
else
if
(
smstatus
&
GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED
)
extra
=
" (modified content)"
;
else
if
(
smstatus
&
GIT_SUBMODULE_STATUS_WD_WD_MODIFIED
)
extra
=
" (modified content)"
;
else
if
(
smstatus
&
GIT_SUBMODULE_STATUS_WD_UNTRACKED
)
extra
=
" (untracked content)"
;
}
}
if
(
s
->
head_to_index
)
{
a
=
s
->
head_to_index
->
old_file
.
path
;
b
=
s
->
head_to_index
->
new_file
.
path
;
}
if
(
s
->
index_to_workdir
)
{
if
(
!
a
)
a
=
s
->
index_to_workdir
->
old_file
.
path
;
if
(
!
b
)
b
=
s
->
index_to_workdir
->
old_file
.
path
;
c
=
s
->
index_to_workdir
->
new_file
.
path
;
}
if
(
istatus
==
'R'
)
{
if
(
wstatus
==
'R'
)
printf
(
"%c%c %s %s %s%s
\n
"
,
istatus
,
wstatus
,
a
,
b
,
c
,
extra
);
else
printf
(
"%c%c %s %s%s
\n
"
,
istatus
,
wstatus
,
a
,
b
,
extra
);
}
else
{
if
(
wstatus
==
'R'
)
printf
(
"%c%c %s %s%s
\n
"
,
istatus
,
wstatus
,
a
,
c
,
extra
);
else
printf
(
"%c%c %s%s
\n
"
,
istatus
,
wstatus
,
a
,
extra
);
}
}
for
(
i
=
0
;
i
<
maxi
;
++
i
)
{
s
=
git_status_byindex
(
status
,
i
);
if
(
s
->
status
==
GIT_STATUS_WT_NEW
)
printf
(
"?? %s
\n
"
,
s
->
index_to_workdir
->
old_file
.
path
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
git_repository
*
repo
=
NULL
;
int
i
,
npaths
=
0
,
format
=
FORMAT_DEFAULT
,
zterm
=
0
,
showbranch
=
0
;
git_status_options
opt
=
GIT_STATUS_OPTIONS_INIT
;
git_status_list
*
status
;
char
*
repodir
=
"."
,
*
pathspec
[
MAX_PATHSPEC
];
opt
.
show
=
GIT_STATUS_SHOW_INDEX_AND_WORKDIR
;
opt
.
flags
=
GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
|
GIT_STATUS_OPT_SORT_CASE_SENSITIVELY
;
for
(
i
=
1
;
i
<
argc
;
++
i
)
{
if
(
argv
[
i
][
0
]
!=
'-'
)
{
if
(
npaths
<
MAX_PATHSPEC
)
pathspec
[
npaths
++
]
=
argv
[
i
];
else
fail
(
"Example only supports a limited pathspec"
);
}
else
if
(
!
strcmp
(
argv
[
i
],
"-s"
)
||
!
strcmp
(
argv
[
i
],
"--short"
))
format
=
FORMAT_SHORT
;
else
if
(
!
strcmp
(
argv
[
i
],
"--long"
))
format
=
FORMAT_LONG
;
else
if
(
!
strcmp
(
argv
[
i
],
"--porcelain"
))
format
=
FORMAT_PORCELAIN
;
else
if
(
!
strcmp
(
argv
[
i
],
"-b"
)
||
!
strcmp
(
argv
[
i
],
"--branch"
))
showbranch
=
1
;
else
if
(
!
strcmp
(
argv
[
i
],
"-z"
))
{
zterm
=
1
;
if
(
format
==
FORMAT_DEFAULT
)
format
=
FORMAT_PORCELAIN
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"--ignored"
))
opt
.
flags
|=
GIT_STATUS_OPT_INCLUDE_IGNORED
;
else
if
(
!
strcmp
(
argv
[
i
],
"-uno"
)
||
!
strcmp
(
argv
[
i
],
"--untracked-files=no"
))
opt
.
flags
&=
~
GIT_STATUS_OPT_INCLUDE_UNTRACKED
;
else
if
(
!
strcmp
(
argv
[
i
],
"-unormal"
)
||
!
strcmp
(
argv
[
i
],
"--untracked-files=normal"
))
opt
.
flags
|=
GIT_STATUS_OPT_INCLUDE_UNTRACKED
;
else
if
(
!
strcmp
(
argv
[
i
],
"-uall"
)
||
!
strcmp
(
argv
[
i
],
"--untracked-files=all"
))
opt
.
flags
|=
GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
;
else
if
(
!
strcmp
(
argv
[
i
],
"--ignore-submodules=all"
))
opt
.
flags
|=
GIT_STATUS_OPT_EXCLUDE_SUBMODULES
;
else
if
(
!
strncmp
(
argv
[
i
],
"--git-dir="
,
strlen
(
"--git-dir="
)))
repodir
=
argv
[
i
]
+
strlen
(
"--git-dir="
);
else
check
(
-
1
,
"Unsupported option"
,
argv
[
i
]);
}
if
(
format
==
FORMAT_DEFAULT
)
format
=
FORMAT_LONG
;
if
(
format
==
FORMAT_LONG
)
showbranch
=
1
;
if
(
npaths
>
0
)
{
opt
.
pathspec
.
strings
=
pathspec
;
opt
.
pathspec
.
count
=
npaths
;
}
/*
* Try to open the repository at the given path (or at the current
* directory if none was given).
*/
check
(
git_repository_open_ext
(
&
repo
,
repodir
,
0
,
NULL
),
"Could not open repository"
,
repodir
);
if
(
git_repository_is_bare
(
repo
))
fail
(
"Cannot report status on bare repository"
);
/*
* Run status on the repository
*
* Because we want to simluate a full "git status" run and want to
* support some command line options, we use `git_status_foreach_ext()`
* instead of just the plain status call. This allows (a) iterating
* over the index and then the workdir and (b) extra flags that control
* which files are included. If you just want simple status (e.g. to
* enumerate files that are modified) then you probably don't need the
* extended API.
*/
check
(
git_status_list_new
(
&
status
,
repo
,
&
opt
),
"Could not get status"
,
NULL
);
if
(
showbranch
)
show_branch
(
repo
,
format
);
if
(
format
==
FORMAT_LONG
)
print_long
(
repo
,
status
);
else
print_short
(
repo
,
status
);
git_status_list_free
(
status
);
git_repository_free
(
repo
);
return
0
;
}
include/git2/status.h
View file @
f2d110f1
...
@@ -111,6 +111,12 @@ typedef enum {
...
@@ -111,6 +111,12 @@ typedef enum {
* - GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR indicates tha rename
* - GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR indicates tha rename
* detection should be run between the index and the working directory
* detection should be run between the index and the working directory
* and enabled GIT_STATUS_WT_RENAMED as a possible status flag.
* and enabled GIT_STATUS_WT_RENAMED as a possible status flag.
* - GIT_STATUS_OPT_SORT_CASE_SENSITIVELY overrides the native case
* sensitivity for the file system and forces the output to be in
* case-sensitive order
* - GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY overrides the native case
* sensitivity for the file system and forces the output to be in
* case-insensitive order
*
*
* Calling `git_status_foreach()` is like calling the extended version
* Calling `git_status_foreach()` is like calling the extended version
* with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED,
* with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED,
...
@@ -127,6 +133,8 @@ typedef enum {
...
@@ -127,6 +133,8 @@ typedef enum {
GIT_STATUS_OPT_RECURSE_IGNORED_DIRS
=
(
1u
<<
6
),
GIT_STATUS_OPT_RECURSE_IGNORED_DIRS
=
(
1u
<<
6
),
GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
=
(
1u
<<
7
),
GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
=
(
1u
<<
7
),
GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR
=
(
1u
<<
8
),
GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR
=
(
1u
<<
8
),
GIT_STATUS_OPT_SORT_CASE_SENSITIVELY
=
(
1u
<<
9
),
GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY
=
(
1u
<<
10
),
}
git_status_opt_t
;
}
git_status_opt_t
;
#define GIT_STATUS_OPT_DEFAULTS \
#define GIT_STATUS_OPT_DEFAULTS \
...
...
src/attr_file.c
View file @
f2d110f1
...
@@ -498,7 +498,7 @@ int git_attr_assignment__parse(
...
@@ -498,7 +498,7 @@ int git_attr_assignment__parse(
assert
(
assigns
&&
!
assigns
->
length
);
assert
(
assigns
&&
!
assigns
->
length
);
assigns
->
_cmp
=
sort_by_hash_and_name
;
git_vector_set_cmp
(
assigns
,
sort_by_hash_and_name
)
;
while
(
*
scan
&&
*
scan
!=
'\n'
)
{
while
(
*
scan
&&
*
scan
!=
'\n'
)
{
const
char
*
name_start
,
*
value_start
;
const
char
*
name_start
,
*
value_start
;
...
...
src/diff.c
View file @
f2d110f1
...
@@ -365,7 +365,7 @@ static git_diff_list *diff_list_alloc(
...
@@ -365,7 +365,7 @@ static git_diff_list *diff_list_alloc(
diff
->
pfxcomp
=
git__prefixcmp_icase
;
diff
->
pfxcomp
=
git__prefixcmp_icase
;
diff
->
entrycomp
=
git_index_entry__cmp_icase
;
diff
->
entrycomp
=
git_index_entry__cmp_icase
;
diff
->
deltas
.
_cmp
=
git_diff_delta__casecmp
;
git_vector_set_cmp
(
&
diff
->
deltas
,
git_diff_delta__casecmp
)
;
}
}
return
diff
;
return
diff
;
...
@@ -786,10 +786,15 @@ static int diff_scan_inside_untracked_dir(
...
@@ -786,10 +786,15 @@ static int diff_scan_inside_untracked_dir(
/* need to recurse into non-ignored directories */
/* need to recurse into non-ignored directories */
if
(
!
is_ignored
&&
S_ISDIR
(
info
->
nitem
->
mode
))
{
if
(
!
is_ignored
&&
S_ISDIR
(
info
->
nitem
->
mode
))
{
if
((
error
=
git_iterator_advance_into
(
error
=
git_iterator_advance_into
(
&
info
->
nitem
,
info
->
new_iter
);
&
info
->
nitem
,
info
->
new_iter
))
<
0
)
break
;
if
(
!
error
)
continue
;
continue
;
else
if
(
error
==
GIT_ENOTFOUND
)
{
error
=
0
;
is_ignored
=
true
;
/* treat empty as ignored */
}
else
break
;
/* real error, must stop */
}
}
/* found a non-ignored item - treat parent dir as untracked */
/* found a non-ignored item - treat parent dir as untracked */
...
@@ -1160,7 +1165,7 @@ int git_diff_tree_to_index(
...
@@ -1160,7 +1165,7 @@ int git_diff_tree_to_index(
d
->
pfxcomp
=
git__prefixcmp_icase
;
d
->
pfxcomp
=
git__prefixcmp_icase
;
d
->
entrycomp
=
git_index_entry__cmp_icase
;
d
->
entrycomp
=
git_index_entry__cmp_icase
;
d
->
deltas
.
_cmp
=
git_diff_delta__casecmp
;
git_vector_set_cmp
(
&
d
->
deltas
,
git_diff_delta__casecmp
)
;
git_vector_sort
(
&
d
->
deltas
);
git_vector_sort
(
&
d
->
deltas
);
}
}
}
}
...
@@ -1261,10 +1266,10 @@ int git_diff__paired_foreach(
...
@@ -1261,10 +1266,10 @@ int git_diff__paired_foreach(
/* force case-sensitive delta sort */
/* force case-sensitive delta sort */
if
(
icase_mismatch
)
{
if
(
icase_mismatch
)
{
if
(
head2idx
->
opts
.
flags
&
GIT_DIFF_DELTAS_ARE_ICASE
)
{
if
(
head2idx
->
opts
.
flags
&
GIT_DIFF_DELTAS_ARE_ICASE
)
{
head2idx
->
deltas
.
_cmp
=
git_diff_delta__cmp
;
git_vector_set_cmp
(
&
head2idx
->
deltas
,
git_diff_delta__cmp
)
;
git_vector_sort
(
&
head2idx
->
deltas
);
git_vector_sort
(
&
head2idx
->
deltas
);
}
else
{
}
else
{
idx2wd
->
deltas
.
_cmp
=
git_diff_delta__cmp
;
git_vector_set_cmp
(
&
idx2wd
->
deltas
,
git_diff_delta__cmp
)
;
git_vector_sort
(
&
idx2wd
->
deltas
);
git_vector_sort
(
&
idx2wd
->
deltas
);
}
}
}
}
...
@@ -1296,10 +1301,10 @@ int git_diff__paired_foreach(
...
@@ -1296,10 +1301,10 @@ int git_diff__paired_foreach(
/* restore case-insensitive delta sort */
/* restore case-insensitive delta sort */
if
(
icase_mismatch
)
{
if
(
icase_mismatch
)
{
if
(
head2idx
->
opts
.
flags
&
GIT_DIFF_DELTAS_ARE_ICASE
)
{
if
(
head2idx
->
opts
.
flags
&
GIT_DIFF_DELTAS_ARE_ICASE
)
{
head2idx
->
deltas
.
_cmp
=
git_diff_delta__casecmp
;
git_vector_set_cmp
(
&
head2idx
->
deltas
,
git_diff_delta__casecmp
)
;
git_vector_sort
(
&
head2idx
->
deltas
);
git_vector_sort
(
&
head2idx
->
deltas
);
}
else
{
}
else
{
idx2wd
->
deltas
.
_cmp
=
git_diff_delta__casecmp
;
git_vector_set_cmp
(
&
idx2wd
->
deltas
,
git_diff_delta__casecmp
)
;
git_vector_sort
(
&
idx2wd
->
deltas
);
git_vector_sort
(
&
idx2wd
->
deltas
);
}
}
}
}
...
...
src/index.c
View file @
f2d110f1
...
@@ -290,16 +290,16 @@ void git_index__set_ignore_case(git_index *index, bool ignore_case)
...
@@ -290,16 +290,16 @@ void git_index__set_ignore_case(git_index *index, bool ignore_case)
{
{
index
->
ignore_case
=
ignore_case
;
index
->
ignore_case
=
ignore_case
;
index
->
entries
.
_cmp
=
ignore_case
?
index_icmp
:
index_cmp
;
index
->
entries_cmp_path
=
ignore_case
?
index_icmp_path
:
index_cmp_path
;
index
->
entries_cmp_path
=
ignore_case
?
index_icmp_path
:
index_cmp_path
;
index
->
entries_search
=
ignore_case
?
index_isrch
:
index_srch
;
index
->
entries_search
=
ignore_case
?
index_isrch
:
index_srch
;
index
->
entries_search_path
=
ignore_case
?
index_isrch_path
:
index_srch_path
;
index
->
entries_search_path
=
ignore_case
?
index_isrch_path
:
index_srch_path
;
index
->
entries
.
sorted
=
0
;
git_vector_set_cmp
(
&
index
->
entries
,
ignore_case
?
index_icmp
:
index_cmp
);
git_vector_sort
(
&
index
->
entries
);
git_vector_sort
(
&
index
->
entries
);
index
->
reuc
.
_cmp
=
ignore_case
?
reuc_icmp
:
reuc_cmp
;
index
->
reuc_search
=
ignore_case
?
reuc_isrch
:
reuc_srch
;
index
->
reuc_search
=
ignore_case
?
reuc_isrch
:
reuc_srch
;
index
->
reuc
.
sorted
=
0
;
git_vector_set_cmp
(
&
index
->
reuc
,
ignore_case
?
reuc_icmp
:
reuc_cmp
);
git_vector_sort
(
&
index
->
reuc
);
git_vector_sort
(
&
index
->
reuc
);
}
}
...
@@ -2024,7 +2024,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
...
@@ -2024,7 +2024,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
git_vector_sort
(
&
index
->
entries
);
git_vector_sort
(
&
index
->
entries
);
entries
.
_cmp
=
index
->
entries
.
_cmp
;
git_vector_set_cmp
(
&
entries
,
index
->
entries
.
_cmp
)
;
git_vector_swap
(
&
entries
,
&
index
->
entries
);
git_vector_swap
(
&
entries
,
&
index
->
entries
);
git_index_clear
(
index
);
git_index_clear
(
index
);
...
...
src/status.c
View file @
f2d110f1
...
@@ -335,8 +335,16 @@ int git_status_list_new(
...
@@ -335,8 +335,16 @@ int git_status_list_new(
status
->
head2idx
,
status
->
idx2wd
,
status_collect
,
status
))
<
0
)
status
->
head2idx
,
status
->
idx2wd
,
status_collect
,
status
))
<
0
)
goto
done
;
goto
done
;
if
((
flags
&
GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
)
!=
0
||
if
(
flags
&
GIT_STATUS_OPT_SORT_CASE_SENSITIVELY
)
(
flags
&
GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR
)
!=
0
)
git_vector_set_cmp
(
&
status
->
paired
,
status_entry_cmp
);
if
(
flags
&
GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY
)
git_vector_set_cmp
(
&
status
->
paired
,
status_entry_icmp
);
if
((
flags
&
(
GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
|
GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR
|
GIT_STATUS_OPT_SORT_CASE_SENSITIVELY
|
GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY
))
!=
0
)
git_vector_sort
(
&
status
->
paired
);
git_vector_sort
(
&
status
->
paired
);
done
:
done
:
...
...
src/submodule.c
View file @
f2d110f1
...
@@ -151,7 +151,7 @@ int git_submodule_foreach(
...
@@ -151,7 +151,7 @@ int git_submodule_foreach(
int
error
;
int
error
;
git_submodule
*
sm
;
git_submodule
*
sm
;
git_vector
seen
=
GIT_VECTOR_INIT
;
git_vector
seen
=
GIT_VECTOR_INIT
;
seen
.
_cmp
=
submodule_cmp
;
git_vector_set_cmp
(
&
seen
,
submodule_cmp
)
;
assert
(
repo
&&
callback
);
assert
(
repo
&&
callback
);
...
...
src/vector.h
View file @
f2d110f1
...
@@ -78,4 +78,13 @@ void git_vector_remove_matching(
...
@@ -78,4 +78,13 @@ void git_vector_remove_matching(
int
git_vector_resize_to
(
git_vector
*
v
,
size_t
new_length
);
int
git_vector_resize_to
(
git_vector
*
v
,
size_t
new_length
);
int
git_vector_set
(
void
**
old
,
git_vector
*
v
,
size_t
position
,
void
*
value
);
int
git_vector_set
(
void
**
old
,
git_vector
*
v
,
size_t
position
,
void
*
value
);
/** Set the comparison function used for sorting the vector */
GIT_INLINE
(
void
)
git_vector_set_cmp
(
git_vector
*
v
,
git_vector_cmp
cmp
)
{
if
(
cmp
!=
v
->
_cmp
)
{
v
->
_cmp
=
cmp
;
v
->
sorted
=
0
;
}
}
#endif
#endif
tests-clar/diff/workdir.c
View file @
f2d110f1
...
@@ -1109,6 +1109,26 @@ void test_diff_workdir__untracked_directory_scenarios(void)
...
@@ -1109,6 +1109,26 @@ void test_diff_workdir__untracked_directory_scenarios(void)
git_diff_list_free
(
diff
);
git_diff_list_free
(
diff
);
/* empty directory in empty directory */
cl_git_pass
(
p_mkdir
(
"status/subdir/directory/empty"
,
0777
));
memset
(
&
exp
,
0
,
sizeof
(
exp
));
exp
.
names
=
files1
;
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
cl_git_pass
(
git_diff_foreach
(
diff
,
diff_file_cb
,
NULL
,
NULL
,
&
exp
));
cl_assert_equal_i
(
4
,
exp
.
files
);
cl_assert_equal_i
(
0
,
exp
.
file_status
[
GIT_DELTA_ADDED
]);
cl_assert_equal_i
(
1
,
exp
.
file_status
[
GIT_DELTA_DELETED
]);
cl_assert_equal_i
(
1
,
exp
.
file_status
[
GIT_DELTA_MODIFIED
]);
cl_assert_equal_i
(
1
,
exp
.
file_status
[
GIT_DELTA_IGNORED
]);
cl_assert_equal_i
(
1
,
exp
.
file_status
[
GIT_DELTA_UNTRACKED
]);
git_diff_list_free
(
diff
);
/* directory with only ignored files */
/* directory with only ignored files */
cl_git_pass
(
p_mkdir
(
"status/subdir/directory/deeper"
,
0777
));
cl_git_pass
(
p_mkdir
(
"status/subdir/directory/deeper"
,
0777
));
...
...
tests-clar/status/status_helpers.c
View file @
f2d110f1
...
@@ -6,6 +6,9 @@ int cb_status__normal(
...
@@ -6,6 +6,9 @@ int cb_status__normal(
{
{
status_entry_counts
*
counts
=
payload
;
status_entry_counts
*
counts
=
payload
;
if
(
counts
->
debug
)
cb_status__print
(
path
,
status_flags
,
NULL
);
if
(
counts
->
entry_count
>=
counts
->
expected_entry_count
)
{
if
(
counts
->
entry_count
>=
counts
->
expected_entry_count
)
{
counts
->
wrong_status_flags_count
++
;
counts
->
wrong_status_flags_count
++
;
goto
exit
;
goto
exit
;
...
...
tests-clar/status/status_helpers.h
View file @
f2d110f1
...
@@ -8,6 +8,7 @@ typedef struct {
...
@@ -8,6 +8,7 @@ typedef struct {
const
unsigned
int
*
expected_statuses
;
const
unsigned
int
*
expected_statuses
;
const
char
**
expected_paths
;
const
char
**
expected_paths
;
int
expected_entry_count
;
int
expected_entry_count
;
bool
debug
;
}
status_entry_counts
;
}
status_entry_counts
;
/* cb_status__normal takes payload of "status_entry_counts *" */
/* cb_status__normal takes payload of "status_entry_counts *" */
...
...
tests-clar/status/worktree.c
View file @
f2d110f1
...
@@ -743,3 +743,83 @@ void test_status_worktree__simple_delete_indexed(void)
...
@@ -743,3 +743,83 @@ void test_status_worktree__simple_delete_indexed(void)
GIT_STATUS_WT_DELETED
,
git_status_byindex
(
status
,
0
)
->
status
);
GIT_STATUS_WT_DELETED
,
git_status_byindex
(
status
,
0
)
->
status
);
git_status_list_free
(
status
);
git_status_list_free
(
status
);
}
}
static
const
char
*
icase_paths
[]
=
{
"B"
,
"c"
,
"g"
,
"H"
};
static
unsigned
int
icase_statuses
[]
=
{
GIT_STATUS_WT_MODIFIED
,
GIT_STATUS_WT_DELETED
,
GIT_STATUS_WT_MODIFIED
,
GIT_STATUS_WT_DELETED
,
};
static
const
char
*
case_paths
[]
=
{
"B"
,
"H"
,
"c"
,
"g"
};
static
unsigned
int
case_statuses
[]
=
{
GIT_STATUS_WT_MODIFIED
,
GIT_STATUS_WT_DELETED
,
GIT_STATUS_WT_DELETED
,
GIT_STATUS_WT_MODIFIED
,
};
void
test_status_worktree__sorting_by_case
(
void
)
{
git_repository
*
repo
=
cl_git_sandbox_init
(
"icase"
);
git_index
*
index
;
git_status_options
opts
=
GIT_STATUS_OPTIONS_INIT
;
bool
native_ignore_case
;
status_entry_counts
counts
;
cl_git_pass
(
git_repository_index
(
&
index
,
repo
));
native_ignore_case
=
(
git_index_caps
(
index
)
&
GIT_INDEXCAP_IGNORE_CASE
)
!=
0
;
git_index_free
(
index
);
memset
(
&
counts
,
0
,
sizeof
(
counts
));
counts
.
expected_entry_count
=
0
;
counts
.
expected_paths
=
NULL
;
counts
.
expected_statuses
=
NULL
;
cl_git_pass
(
git_status_foreach_ext
(
repo
,
&
opts
,
cb_status__normal
,
&
counts
));
cl_assert_equal_i
(
counts
.
expected_entry_count
,
counts
.
entry_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_status_flags_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_sorted_path
);
cl_git_rewritefile
(
"icase/B"
,
"new stuff"
);
cl_must_pass
(
p_unlink
(
"icase/c"
));
cl_git_rewritefile
(
"icase/g"
,
"new stuff"
);
cl_must_pass
(
p_unlink
(
"icase/H"
));
memset
(
&
counts
,
0
,
sizeof
(
counts
));
counts
.
expected_entry_count
=
4
;
if
(
native_ignore_case
)
{
counts
.
expected_paths
=
icase_paths
;
counts
.
expected_statuses
=
icase_statuses
;
}
else
{
counts
.
expected_paths
=
case_paths
;
counts
.
expected_statuses
=
case_statuses
;
}
cl_git_pass
(
git_status_foreach_ext
(
repo
,
&
opts
,
cb_status__normal
,
&
counts
));
cl_assert_equal_i
(
counts
.
expected_entry_count
,
counts
.
entry_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_status_flags_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_sorted_path
);
opts
.
flags
=
GIT_STATUS_OPT_SORT_CASE_SENSITIVELY
;
memset
(
&
counts
,
0
,
sizeof
(
counts
));
counts
.
expected_entry_count
=
4
;
counts
.
expected_paths
=
case_paths
;
counts
.
expected_statuses
=
case_statuses
;
cl_git_pass
(
git_status_foreach_ext
(
repo
,
&
opts
,
cb_status__normal
,
&
counts
));
cl_assert_equal_i
(
counts
.
expected_entry_count
,
counts
.
entry_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_status_flags_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_sorted_path
);
opts
.
flags
=
GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY
;
memset
(
&
counts
,
0
,
sizeof
(
counts
));
counts
.
expected_entry_count
=
4
;
counts
.
expected_paths
=
icase_paths
;
counts
.
expected_statuses
=
icase_statuses
;
cl_git_pass
(
git_status_foreach_ext
(
repo
,
&
opts
,
cb_status__normal
,
&
counts
));
cl_assert_equal_i
(
counts
.
expected_entry_count
,
counts
.
entry_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_status_flags_count
);
cl_assert_equal_i
(
0
,
counts
.
wrong_sorted_path
);
}
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