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
bd679796
Commit
bd679796
authored
Jul 10, 2013
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1685 from arrbee/submodule-status-fixes
Improve submodules status data caching and compatibility
parents
c0e529f3
125655fe
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
994 additions
and
461 deletions
+994
-461
include/git2/diff.h
+4
-1
include/git2/index.h
+8
-0
include/git2/repository.h
+4
-0
include/git2/submodule.h
+13
-56
include/git2/types.h
+34
-0
src/diff.c
+52
-31
src/index.c
+6
-0
src/repository.c
+9
-6
src/submodule.c
+349
-279
src/submodule.h
+55
-19
src/thread-utils.h
+5
-0
src/util.h
+3
-0
tests-clar/clar_libgit2.h
+3
-0
tests-clar/diff/submodules.c
+306
-36
tests-clar/diff/workdir.c
+4
-3
tests-clar/repo/open.c
+61
-4
tests-clar/status/submodules.c
+12
-9
tests-clar/submodule/modify.c
+5
-5
tests-clar/submodule/status.c
+23
-12
tests-clar/submodule/submodule_helpers.c
+35
-0
tests-clar/submodule/submodule_helpers.h
+3
-0
No files found.
include/git2/diff.h
View file @
bd679796
...
...
@@ -78,7 +78,7 @@ typedef enum {
GIT_DIFF_IGNORE_WHITESPACE_CHANGE
=
(
1
<<
3
),
/** Ignore whitespace at end of line */
GIT_DIFF_IGNORE_WHITESPACE_EOL
=
(
1
<<
4
),
/**
Exclude submodules from the diff completely
*/
/**
Treat all submodules as unmodified
*/
GIT_DIFF_IGNORE_SUBMODULES
=
(
1
<<
5
),
/** Use the "patience diff" algorithm (currently unimplemented) */
GIT_DIFF_PATIENCE
=
(
1
<<
6
),
...
...
@@ -314,6 +314,8 @@ typedef int (*git_diff_notify_cb)(
* - `notify_cb` is an optional callback function, notifying the consumer of
* which files are being examined as the diff is generated
* - `notify_payload` is the payload data to pass to the `notify_cb` function
* - `ignore_submodules` overrides the submodule ignore setting for all
* submodules in the diff.
*/
typedef
struct
{
unsigned
int
version
;
/**< version for the struct */
...
...
@@ -326,6 +328,7 @@ typedef struct {
git_off_t
max_size
;
/**< defaults to 512MB */
git_diff_notify_cb
notify_cb
;
void
*
notify_payload
;
git_submodule_ignore_t
ignore_submodules
;
/** << submodule ignore rule */
}
git_diff_options
;
#define GIT_DIFF_OPTIONS_VERSION 1
...
...
include/git2/index.h
View file @
bd679796
...
...
@@ -240,6 +240,14 @@ GIT_EXTERN(int) git_index_read(git_index *index);
GIT_EXTERN
(
int
)
git_index_write
(
git_index
*
index
);
/**
* Get the full path to the index file on disk.
*
* @param index an existing index object
* @return path to index file or NULL for in-memory index
*/
GIT_EXTERN
(
const
char
*
)
git_index_path
(
git_index
*
index
);
/**
* Read a tree into the index file with stats
*
* The current index contents will be replaced by the specified tree.
...
...
include/git2/repository.h
View file @
bd679796
...
...
@@ -94,10 +94,14 @@ GIT_EXTERN(int) git_repository_discover(
* changes from the `stat` system call). (E.g. Searching in a user's home
* directory "/home/user/source/" will not return "/.git/" as the found
* repo if "/" is a different filesystem than "/home".)
* * GIT_REPOSITORY_OPEN_BARE - Open repository as a bare repo regardless
* of core.bare config, and defer loading config file for faster setup.
* Unlike `git_repository_open_bare`, this can follow gitlinks.
*/
typedef
enum
{
GIT_REPOSITORY_OPEN_NO_SEARCH
=
(
1
<<
0
),
GIT_REPOSITORY_OPEN_CROSS_FS
=
(
1
<<
1
),
GIT_REPOSITORY_OPEN_BARE
=
(
1
<<
2
),
}
git_repository_open_flag_t
;
/**
...
...
include/git2/submodule.h
View file @
bd679796
...
...
@@ -14,51 +14,18 @@
/**
* @file git2/submodule.h
* @brief Git submodule management utilities
* @defgroup git_submodule Git submodule management routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Opaque structure representing a submodule.
*
* Submodule support in libgit2 builds a list of known submodules and keeps
* it in the repository. The list is built from the .gitmodules file, the
* .git/config file, the index, and the HEAD tree. Items in the working
* directory that look like submodules (i.e. a git repo) but are not
* mentioned in those places won't be tracked.
*/
typedef
struct
git_submodule
git_submodule
;
/**
* Values that could be specified for the update rule of a submodule.
*
* Use the DEFAULT value if you have altered the update value via
* `git_submodule_set_update()` and wish to reset to the original default.
*/
typedef
enum
{
GIT_SUBMODULE_UPDATE_DEFAULT
=
-
1
,
GIT_SUBMODULE_UPDATE_CHECKOUT
=
0
,
GIT_SUBMODULE_UPDATE_REBASE
=
1
,
GIT_SUBMODULE_UPDATE_MERGE
=
2
,
GIT_SUBMODULE_UPDATE_NONE
=
3
}
git_submodule_update_t
;
/**
* Values that could be specified for how closely to examine the
* working directory when getting submodule status.
*
* Use the DEFUALT value if you have altered the ignore value via
* `git_submodule_set_ignore()` and wish to reset to the original value.
* @defgroup git_submodule Git submodule management routines
* @ingroup Git
* @{
*/
typedef
enum
{
GIT_SUBMODULE_IGNORE_DEFAULT
=
-
1
,
/* reset to default */
GIT_SUBMODULE_IGNORE_NONE
=
0
,
/* any change or untracked == dirty */
GIT_SUBMODULE_IGNORE_UNTRACKED
=
1
,
/* dirty if tracked files change */
GIT_SUBMODULE_IGNORE_DIRTY
=
2
,
/* only dirty if HEAD moved */
GIT_SUBMODULE_IGNORE_ALL
=
3
/* never dirty */
}
git_submodule_ignore_t
;
GIT_BEGIN_DECL
/**
* Return codes for submodule status.
...
...
@@ -119,19 +86,9 @@ typedef enum {
GIT_SUBMODULE_STATUS_WD_UNTRACKED
=
(
1u
<<
13
),
}
git_submodule_status_t
;
#define GIT_SUBMODULE_STATUS__IN_FLAGS \
(GIT_SUBMODULE_STATUS_IN_HEAD | \
GIT_SUBMODULE_STATUS_IN_INDEX | \
GIT_SUBMODULE_STATUS_IN_CONFIG | \
GIT_SUBMODULE_STATUS_IN_WD)
#define GIT_SUBMODULE_STATUS__INDEX_FLAGS \
(GIT_SUBMODULE_STATUS_INDEX_ADDED | \
GIT_SUBMODULE_STATUS_INDEX_DELETED | \
GIT_SUBMODULE_STATUS_INDEX_MODIFIED)
#define GIT_SUBMODULE_STATUS__WD_FLAGS \
~(GIT_SUBMODULE_STATUS__IN_FLAGS | GIT_SUBMODULE_STATUS__INDEX_FLAGS)
#define GIT_SUBMODULE_STATUS__IN_FLAGS 0x000Fu
#define GIT_SUBMODULE_STATUS__INDEX_FLAGS 0x0070u
#define GIT_SUBMODULE_STATUS__WD_FLAGS 0x3F80u
#define GIT_SUBMODULE_STATUS_IS_UNMODIFIED(S) \
(((S) & ~GIT_SUBMODULE_STATUS__IN_FLAGS) == 0)
...
...
@@ -387,9 +344,9 @@ GIT_EXTERN(git_submodule_ignore_t) git_submodule_ignore(
* submodule is in memory. You should call `git_submodule_save()` if you
* want to persist the new ignore role.
*
* Calling this again with GIT_SUBMODULE_IGNORE_
DEFAUL
T or calling
* `git_submodule_reload()` will revert the rule to the value that was in
the
* original config.
* Calling this again with GIT_SUBMODULE_IGNORE_
RESE
T or calling
* `git_submodule_reload()` will revert the rule to the value that was in
*
the
original config.
*
* @return old value for ignore
*/
...
...
@@ -409,9 +366,9 @@ GIT_EXTERN(git_submodule_update_t) git_submodule_update(
* This sets the update rule in memory for the submodule. You should call
* `git_submodule_save()` if you want to persist the new update rule.
*
* Calling this again with GIT_SUBMODULE_UPDATE_
DEFAUL
T or calling
* `git_submodule_reload()` will revert the rule to the value that was in
the
* original config.
* Calling this again with GIT_SUBMODULE_UPDATE_
RESE
T or calling
* `git_submodule_reload()` will revert the rule to the value that was in
*
the
original config.
*
* @return old value for update
*/
...
...
include/git2/types.h
View file @
bd679796
...
...
@@ -229,6 +229,40 @@ typedef struct git_transfer_progress {
*/
typedef
int
(
*
git_transfer_progress_callback
)(
const
git_transfer_progress
*
stats
,
void
*
payload
);
/**
* Opaque structure representing a submodule.
*/
typedef
struct
git_submodule
git_submodule
;
/**
* Values that could be specified for the update rule of a submodule.
*
* Use the RESET value if you have altered the in-memory update value via
* `git_submodule_set_update()` and wish to reset to the original default.
*/
typedef
enum
{
GIT_SUBMODULE_UPDATE_RESET
=
-
1
,
GIT_SUBMODULE_UPDATE_CHECKOUT
=
1
,
GIT_SUBMODULE_UPDATE_REBASE
=
2
,
GIT_SUBMODULE_UPDATE_MERGE
=
3
,
GIT_SUBMODULE_UPDATE_NONE
=
4
}
git_submodule_update_t
;
/**
* Values that could be specified for how closely to examine the
* working directory when getting submodule status.
*
* Use the RESET value if you have altered the in-memory ignore value via
* `git_submodule_set_ignore()` and wish to reset to the original value.
*/
typedef
enum
{
GIT_SUBMODULE_IGNORE_RESET
=
-
1
,
/* reset to on-disk value */
GIT_SUBMODULE_IGNORE_NONE
=
1
,
/* any change or untracked == dirty */
GIT_SUBMODULE_IGNORE_UNTRACKED
=
2
,
/* dirty if tracked files change */
GIT_SUBMODULE_IGNORE_DIRTY
=
3
,
/* only dirty if HEAD moved */
GIT_SUBMODULE_IGNORE_ALL
=
4
/* never dirty */
}
git_submodule_ignore_t
;
/** @} */
GIT_END_DECL
...
...
src/diff.c
View file @
bd679796
...
...
@@ -13,6 +13,7 @@
#include "pathspec.h"
#include "index.h"
#include "odb.h"
#include "submodule.h"
#define DIFF_FLAG_IS_SET(DIFF,FLAG) (((DIFF)->opts.flags & (FLAG)) != 0)
#define DIFF_FLAG_ISNT_SET(DIFF,FLAG) (((DIFF)->opts.flags & (FLAG)) == 0)
...
...
@@ -77,10 +78,6 @@ static int diff_delta__from_one(
DIFF_FLAG_ISNT_SET
(
diff
,
GIT_DIFF_INCLUDE_UNTRACKED
))
return
0
;
if
(
entry
->
mode
==
GIT_FILEMODE_COMMIT
&&
DIFF_FLAG_IS_SET
(
diff
,
GIT_DIFF_IGNORE_SUBMODULES
))
return
0
;
if
(
!
git_pathspec__match
(
&
diff
->
pathspec
,
entry
->
path
,
DIFF_FLAG_IS_SET
(
diff
,
GIT_DIFF_DISABLE_PATHSPEC_MATCH
),
...
...
@@ -140,11 +137,6 @@ static int diff_delta__from_two(
DIFF_FLAG_ISNT_SET
(
diff
,
GIT_DIFF_INCLUDE_UNMODIFIED
))
return
0
;
if
(
old_entry
->
mode
==
GIT_FILEMODE_COMMIT
&&
new_entry
->
mode
==
GIT_FILEMODE_COMMIT
&&
DIFF_FLAG_IS_SET
(
diff
,
GIT_DIFF_IGNORE_SUBMODULES
))
return
0
;
if
(
DIFF_FLAG_IS_SET
(
diff
,
GIT_DIFF_REVERSE
))
{
uint32_t
temp_mode
=
old_mode
;
const
git_index_entry
*
temp_entry
=
old_entry
;
...
...
@@ -430,8 +422,18 @@ static int diff_list_apply_options(
if
(
!
opts
)
{
diff
->
opts
.
context_lines
=
config_int
(
cfg
,
"diff.context"
,
3
);
if
(
config_bool
(
cfg
,
"diff.ignoreSubmodules"
,
0
))
diff
->
opts
.
flags
|=
GIT_DIFF_IGNORE_SUBMODULES
;
/* add other defaults here */
}
/* if ignore_submodules not explicitly set, check diff config */
if
(
diff
->
opts
.
ignore_submodules
<=
0
)
{
const
char
*
str
;
if
(
git_config_get_string
(
&
str
,
cfg
,
"diff.ignoreSubmodules"
)
<
0
)
giterr_clear
();
else
if
(
str
!=
NULL
&&
git_submodule_parse_ignore
(
&
diff
->
opts
.
ignore_submodules
,
str
)
<
0
)
giterr_clear
();
}
/* if either prefix is not set, figure out appropriate value */
...
...
@@ -595,35 +597,44 @@ static int maybe_modified_submodule(
int
error
=
0
;
git_submodule
*
sub
;
unsigned
int
sm_status
=
0
;
const
git_oid
*
sm_oid
;
git_submodule_ignore_t
ign
=
diff
->
opts
.
ignore_submodules
;
*
status
=
GIT_DELTA_UNMODIFIED
;
if
(
!
DIFF_FLAG_IS_SET
(
diff
,
GIT_DIFF_IGNORE_SUBMODULES
)
&&
!
(
error
=
git_submodule_lookup
(
&
sub
,
diff
->
repo
,
info
->
nitem
->
path
))
&&
git_submodule_ignore
(
sub
)
!=
GIT_SUBMODULE_IGNORE_ALL
&&
!
(
error
=
git_submodule_status
(
&
sm_status
,
sub
)))
{
/* check IS_WD_UNMODIFIED because this case is only used
* when the new side of the diff is the working directory
*/
if
(
!
GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED
(
sm_status
))
*
status
=
GIT_DELTA_MODIFIED
;
if
(
DIFF_FLAG_IS_SET
(
diff
,
GIT_DIFF_IGNORE_SUBMODULES
)
||
ign
==
GIT_SUBMODULE_IGNORE_ALL
)
return
0
;
/* grab OID while we are here */
if
(
git_oid_iszero
(
&
info
->
nitem
->
oid
)
&&
(
sm_oid
=
git_submodule_wd_id
(
sub
))
!=
NULL
)
git_oid_cpy
(
found_oid
,
sm_oid
);
}
if
((
error
=
git_submodule_lookup
(
&
sub
,
diff
->
repo
,
info
->
nitem
->
path
))
<
0
)
{
/* GIT_EEXISTS means a
dir with .git in it was found - ignore it */
/* GIT_EEXISTS means
dir with .git in it was found - ignore it */
if
(
error
==
GIT_EEXISTS
)
{
giterr_clear
();
error
=
0
;
}
return
error
;
}
if
(
ign
<=
0
&&
git_submodule_ignore
(
sub
)
==
GIT_SUBMODULE_IGNORE_ALL
)
return
0
;
if
((
error
=
git_submodule__status
(
&
sm_status
,
NULL
,
NULL
,
found_oid
,
sub
,
ign
))
<
0
)
return
error
;
/* check IS_WD_UNMODIFIED because this case is only used
* when the new side of the diff is the working directory
*/
if
(
!
GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED
(
sm_status
))
*
status
=
GIT_DELTA_MODIFIED
;
/* now that we have a HEAD OID, check if HEAD moved */
if
((
sm_status
&
GIT_SUBMODULE_STATUS_IN_WD
)
!=
0
&&
!
git_oid_equal
(
&
info
->
oitem
->
oid
,
found_oid
))
*
status
=
GIT_DELTA_MODIFIED
;
return
0
;
}
static
int
maybe_modified
(
...
...
@@ -724,7 +735,7 @@ static int maybe_modified(
/* if we got here and decided that the files are modified, but we
* haven't calculated the OID of the new item, then calculate it now
*/
if
(
status
!=
GIT_DELTA_UN
MODIFIED
&&
git_oid_iszero
(
&
nitem
->
oid
))
{
if
(
status
==
GIT_DELTA_
MODIFIED
&&
git_oid_iszero
(
&
nitem
->
oid
))
{
if
(
git_oid_iszero
(
&
noid
))
{
if
(
git_diff__oid_for_file
(
diff
->
repo
,
nitem
->
path
,
nitem
->
mode
,
nitem
->
file_size
,
&
noid
)
<
0
)
...
...
@@ -847,7 +858,7 @@ static int handle_unmatched_new_item(
git_buf_clear
(
&
info
->
ignore_prefix
);
}
if
(
S_ISDIR
(
nitem
->
mode
)
)
{
if
(
nitem
->
mode
==
GIT_FILEMODE_TREE
)
{
bool
recurse_into_dir
=
contains_oitem
;
/* if not already inside an ignored dir, check if this is ignored */
...
...
@@ -951,6 +962,16 @@ static int handle_unmatched_new_item(
else
if
(
info
->
new_iter
->
type
!=
GIT_ITERATOR_TYPE_WORKDIR
)
delta_type
=
GIT_DELTA_ADDED
;
else
if
(
nitem
->
mode
==
GIT_FILEMODE_COMMIT
)
{
git_submodule
*
sm
;
/* ignore things that are not actual submodules */
if
(
git_submodule_lookup
(
&
sm
,
info
->
repo
,
nitem
->
path
)
!=
0
)
{
giterr_clear
();
delta_type
=
GIT_DELTA_IGNORED
;
}
}
/* Actually create the record for this item if necessary */
if
((
error
=
diff_delta__from_one
(
diff
,
delta_type
,
nitem
))
<
0
)
return
error
;
...
...
src/index.c
View file @
bd679796
...
...
@@ -516,6 +516,12 @@ int git_index_write(git_index *index)
return
0
;
}
const
char
*
git_index_path
(
git_index
*
index
)
{
assert
(
index
);
return
index
->
index_file_path
;
}
int
git_index_write_tree
(
git_oid
*
oid
,
git_index
*
index
)
{
git_repository
*
repo
;
...
...
src/repository.c
View file @
bd679796
...
...
@@ -266,7 +266,7 @@ static int find_ceiling_dir_offset(
buf
[
--
len
]
=
'\0'
;
if
(
!
strncmp
(
path
,
buf2
,
len
)
&&
path
[
len
]
==
'/'
&&
(
path
[
len
]
==
'/'
||
!
path
[
len
])
&&
len
>
max_len
)
{
max_len
=
len
;
...
...
@@ -322,17 +322,18 @@ static int find_repo(
git_buf
path
=
GIT_BUF_INIT
;
struct
stat
st
;
dev_t
initial_device
=
0
;
bool
try_with_dot_git
=
false
;
bool
try_with_dot_git
=
((
flags
&
GIT_REPOSITORY_OPEN_BARE
)
!=
0
)
;
int
ceiling_offset
;
git_buf_free
(
repo_path
);
if
((
error
=
git_path_prettify
_dir
(
&
path
,
start_path
,
NULL
))
<
0
)
if
((
error
=
git_path_prettify
(
&
path
,
start_path
,
NULL
))
<
0
)
return
error
;
ceiling_offset
=
find_ceiling_dir_offset
(
path
.
ptr
,
ceiling_dirs
);
if
((
error
=
git_buf_joinpath
(
&
path
,
path
.
ptr
,
DOT_GIT
))
<
0
)
if
(
!
try_with_dot_git
&&
(
error
=
git_buf_joinpath
(
&
path
,
path
.
ptr
,
DOT_GIT
))
<
0
)
return
error
;
while
(
!
error
&&
!
git_buf_len
(
repo_path
))
{
...
...
@@ -384,7 +385,7 @@ static int find_repo(
try_with_dot_git
=
!
try_with_dot_git
;
}
if
(
!
error
&&
parent_path
!=
NULL
)
{
if
(
!
error
&&
parent_path
&&
!
(
flags
&
GIT_REPOSITORY_OPEN_BARE
)
)
{
if
(
!
git_buf_len
(
repo_path
))
git_buf_clear
(
parent_path
);
else
{
...
...
@@ -460,7 +461,9 @@ int git_repository_open_ext(
repo
->
path_repository
=
git_buf_detach
(
&
path
);
GITERR_CHECK_ALLOC
(
repo
->
path_repository
);
if
((
error
=
load_config_data
(
repo
))
<
0
||
if
((
flags
&
GIT_REPOSITORY_OPEN_BARE
)
!=
0
)
repo
->
is_bare
=
1
;
else
if
((
error
=
load_config_data
(
repo
))
<
0
||
(
error
=
load_workdir
(
repo
,
&
parent
))
<
0
)
{
git_repository_free
(
repo
);
...
...
src/submodule.c
View file @
bd679796
...
...
@@ -9,9 +9,7 @@
#include "git2/config.h"
#include "git2/sys/config.h"
#include "git2/types.h"
#include "git2/repository.h"
#include "git2/index.h"
#include "git2/submodule.h"
#include "buffer.h"
#include "buf_text.h"
#include "vector.h"
...
...
@@ -32,6 +30,8 @@ static git_cvar_map _sm_update_map[] = {
{
GIT_CVAR_STRING
,
"rebase"
,
GIT_SUBMODULE_UPDATE_REBASE
},
{
GIT_CVAR_STRING
,
"merge"
,
GIT_SUBMODULE_UPDATE_MERGE
},
{
GIT_CVAR_STRING
,
"none"
,
GIT_SUBMODULE_UPDATE_NONE
},
{
GIT_CVAR_FALSE
,
NULL
,
GIT_SUBMODULE_UPDATE_NONE
},
{
GIT_CVAR_TRUE
,
NULL
,
GIT_SUBMODULE_UPDATE_CHECKOUT
},
};
static
git_cvar_map
_sm_ignore_map
[]
=
{
...
...
@@ -39,6 +39,8 @@ static git_cvar_map _sm_ignore_map[] = {
{
GIT_CVAR_STRING
,
"untracked"
,
GIT_SUBMODULE_IGNORE_UNTRACKED
},
{
GIT_CVAR_STRING
,
"dirty"
,
GIT_SUBMODULE_IGNORE_DIRTY
},
{
GIT_CVAR_STRING
,
"all"
,
GIT_SUBMODULE_IGNORE_ALL
},
{
GIT_CVAR_FALSE
,
NULL
,
GIT_SUBMODULE_IGNORE_NONE
},
{
GIT_CVAR_TRUE
,
NULL
,
GIT_SUBMODULE_IGNORE_ALL
},
};
static
kh_inline
khint_t
str_hash_no_trailing_slash
(
const
char
*
s
)
...
...
@@ -73,15 +75,11 @@ static int load_submodule_config(git_repository *repo);
static
git_config_backend
*
open_gitmodules
(
git_repository
*
,
bool
,
const
git_oid
*
);
static
int
lookup_head_remote
(
git_buf
*
url
,
git_repository
*
repo
);
static
int
submodule_get
(
git_submodule
**
,
git_repository
*
,
const
char
*
,
const
char
*
);
static
void
submodule_release
(
git_submodule
*
sm
,
int
decr
);
static
int
submodule_load_from_index
(
git_repository
*
,
const
git_index_entry
*
);
static
int
submodule_load_from_head
(
git_repository
*
,
const
char
*
,
const
git_oid
*
);
static
int
submodule_load_from_config
(
const
git_config_entry
*
,
void
*
);
static
int
submodule_load_from_wd_lite
(
git_submodule
*
,
const
char
*
,
void
*
);
static
int
submodule_update_config
(
git_submodule
*
,
const
char
*
,
const
char
*
,
bool
,
bool
);
static
void
submodule_mode_mismatch
(
git_repository
*
,
const
char
*
,
unsigned
int
);
static
int
submodule_index_status
(
unsigned
int
*
status
,
git_submodule
*
sm
);
static
int
submodule_wd_status
(
unsigned
int
*
status
,
git_submodule
*
sm
);
static
void
submodule_get_index_status
(
unsigned
int
*
,
git_submodule
*
);
static
void
submodule_get_wd_status
(
unsigned
int
*
,
git_submodule
*
,
git_repository
*
,
git_submodule_ignore_t
);
static
int
submodule_cmp
(
const
void
*
a
,
const
void
*
b
)
{
...
...
@@ -163,7 +161,7 @@ int git_submodule_foreach(
* us from issuing a callback twice for a submodule where the name
* and path are not the same.
*/
if
(
sm
->
refcount
>
1
)
{
if
(
GIT_REFCOUNT_VAL
(
sm
)
>
1
)
{
if
(
git_vector_bsearch
(
NULL
,
&
seen
,
sm
)
!=
GIT_ENOTFOUND
)
continue
;
if
((
error
=
git_vector_insert
(
&
seen
,
sm
))
<
0
)
...
...
@@ -195,9 +193,7 @@ void git_submodule_config_free(git_repository *repo)
if
(
smcfg
==
NULL
)
return
;
git_strmap_foreach_value
(
smcfg
,
sm
,
{
submodule_release
(
sm
,
1
);
});
git_strmap_foreach_value
(
smcfg
,
sm
,
{
git_submodule_free
(
sm
);
});
git_strmap_free
(
smcfg
);
}
...
...
@@ -338,7 +334,7 @@ int git_submodule_add_finalize(git_submodule *sm)
assert
(
sm
);
if
((
error
=
git_repository_index__weakptr
(
&
index
,
sm
->
owner
))
<
0
||
if
((
error
=
git_repository_index__weakptr
(
&
index
,
sm
->
repo
))
<
0
||
(
error
=
git_index_add_bypath
(
index
,
GIT_MODULES_FILE
))
<
0
)
return
error
;
...
...
@@ -348,7 +344,7 @@ int git_submodule_add_finalize(git_submodule *sm)
int
git_submodule_add_to_index
(
git_submodule
*
sm
,
int
write_index
)
{
int
error
;
git_repository
*
repo
,
*
sm_repo
=
NULL
;
git_repository
*
sm_repo
=
NULL
;
git_index
*
index
;
git_buf
path
=
GIT_BUF_INIT
;
git_commit
*
head
;
...
...
@@ -357,14 +353,12 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index)
assert
(
sm
);
repo
=
sm
->
owner
;
/* force reload of wd OID by git_submodule_open */
sm
->
flags
=
sm
->
flags
&
~
GIT_SUBMODULE_STATUS__WD_OID_VALID
;
if
((
error
=
git_repository_index__weakptr
(
&
index
,
repo
))
<
0
||
if
((
error
=
git_repository_index__weakptr
(
&
index
,
sm
->
repo
))
<
0
||
(
error
=
git_buf_joinpath
(
&
path
,
git_repository_workdir
(
repo
),
sm
->
path
))
<
0
||
&
path
,
git_repository_workdir
(
sm
->
repo
),
sm
->
path
))
<
0
||
(
error
=
git_submodule_open
(
&
sm_repo
,
sm
))
<
0
)
goto
cleanup
;
...
...
@@ -416,15 +410,34 @@ cleanup:
return
error
;
}
const
char
*
git_submodule_ignore_to_str
(
git_submodule_ignore_t
ignore
)
{
int
i
;
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
_sm_ignore_map
);
++
i
)
if
(
_sm_ignore_map
[
i
].
map_value
==
ignore
)
return
_sm_ignore_map
[
i
].
str_match
;
return
NULL
;
}
const
char
*
git_submodule_update_to_str
(
git_submodule_update_t
update
)
{
int
i
;
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
_sm_update_map
);
++
i
)
if
(
_sm_update_map
[
i
].
map_value
==
update
)
return
_sm_update_map
[
i
].
str_match
;
return
NULL
;
}
int
git_submodule_save
(
git_submodule
*
submodule
)
{
int
error
=
0
;
git_config_backend
*
mods
;
git_buf
key
=
GIT_BUF_INIT
;
const
char
*
val
;
assert
(
submodule
);
mods
=
open_gitmodules
(
submodule
->
owner
,
true
,
NULL
);
mods
=
open_gitmodules
(
submodule
->
repo
,
true
,
NULL
);
if
(
!
mods
)
{
giterr_set
(
GITERR_SUBMODULE
,
"Adding submodules to a bare repository is not supported (for now)"
);
...
...
@@ -445,22 +458,14 @@ int git_submodule_save(git_submodule *submodule)
goto
cleanup
;
if
(
!
(
error
=
submodule_config_key_trunc_puts
(
&
key
,
"update"
))
&&
submodule
->
update
!=
GIT_SUBMODULE_UPDATE_DEFAULT
)
{
const
char
*
val
=
(
submodule
->
update
==
GIT_SUBMODULE_UPDATE_CHECKOUT
)
?
NULL
:
_sm_update_map
[
submodule
->
update
].
str_match
;
(
val
=
git_submodule_update_to_str
(
submodule
->
update
))
!=
NULL
)
error
=
git_config_file_set_string
(
mods
,
key
.
ptr
,
val
);
}
if
(
error
<
0
)
goto
cleanup
;
if
(
!
(
error
=
submodule_config_key_trunc_puts
(
&
key
,
"ignore"
))
&&
submodule
->
ignore
!=
GIT_SUBMODULE_IGNORE_DEFAULT
)
{
const
char
*
val
=
(
submodule
->
ignore
==
GIT_SUBMODULE_IGNORE_NONE
)
?
NULL
:
_sm_ignore_map
[
submodule
->
ignore
].
str_match
;
(
val
=
git_submodule_ignore_to_str
(
submodule
->
ignore
))
!=
NULL
)
error
=
git_config_file_set_string
(
mods
,
key
.
ptr
,
val
);
}
if
(
error
<
0
)
goto
cleanup
;
...
...
@@ -487,7 +492,7 @@ cleanup:
git_repository
*
git_submodule_owner
(
git_submodule
*
submodule
)
{
assert
(
submodule
);
return
submodule
->
owner
;
return
submodule
->
repo
;
}
const
char
*
git_submodule_name
(
git_submodule
*
submodule
)
...
...
@@ -544,11 +549,12 @@ const git_oid *git_submodule_wd_id(git_submodule *submodule)
{
assert
(
submodule
);
/* load unless we think we have a valid oid */
if
(
!
(
submodule
->
flags
&
GIT_SUBMODULE_STATUS__WD_OID_VALID
))
{
git_repository
*
subrepo
;
/* calling submodule open grabs the HEAD OID if possible */
if
(
!
git_submodule_open
(
&
subrepo
,
submodule
))
if
(
!
git_submodule_open
_bare
(
&
subrepo
,
submodule
))
git_repository_free
(
subrepo
);
else
giterr_clear
();
...
...
@@ -563,7 +569,8 @@ const git_oid *git_submodule_wd_id(git_submodule *submodule)
git_submodule_ignore_t
git_submodule_ignore
(
git_submodule
*
submodule
)
{
assert
(
submodule
);
return
submodule
->
ignore
;
return
(
submodule
->
ignore
<
GIT_SUBMODULE_IGNORE_NONE
)
?
GIT_SUBMODULE_IGNORE_NONE
:
submodule
->
ignore
;
}
git_submodule_ignore_t
git_submodule_set_ignore
(
...
...
@@ -573,7 +580,7 @@ git_submodule_ignore_t git_submodule_set_ignore(
assert
(
submodule
);
if
(
ignore
==
GIT_SUBMODULE_IGNORE_
DEFAUL
T
)
if
(
ignore
==
GIT_SUBMODULE_IGNORE_
RESE
T
)
ignore
=
submodule
->
ignore_default
;
old
=
submodule
->
ignore
;
...
...
@@ -584,7 +591,8 @@ git_submodule_ignore_t git_submodule_set_ignore(
git_submodule_update_t
git_submodule_update
(
git_submodule
*
submodule
)
{
assert
(
submodule
);
return
submodule
->
update
;
return
(
submodule
->
update
<
GIT_SUBMODULE_UPDATE_CHECKOUT
)
?
GIT_SUBMODULE_UPDATE_CHECKOUT
:
submodule
->
update
;
}
git_submodule_update_t
git_submodule_set_update
(
...
...
@@ -594,7 +602,7 @@ git_submodule_update_t git_submodule_set_update(
assert
(
submodule
);
if
(
update
==
GIT_SUBMODULE_UPDATE_
DEFAUL
T
)
if
(
update
==
GIT_SUBMODULE_UPDATE_
RESE
T
)
update
=
submodule
->
update_default
;
old
=
submodule
->
update
;
...
...
@@ -625,6 +633,7 @@ int git_submodule_set_fetch_recurse_submodules(
int
git_submodule_init
(
git_submodule
*
submodule
,
int
overwrite
)
{
int
error
;
const
char
*
val
;
/* write "submodule.NAME.url" */
...
...
@@ -641,14 +650,10 @@ int git_submodule_init(git_submodule *submodule, int overwrite)
/* write "submodule.NAME.update" if not default */
if
(
submodule
->
update
==
GIT_SUBMODULE_UPDATE_CHECKOUT
)
val
=
(
submodule
->
update
==
GIT_SUBMODULE_UPDATE_CHECKOUT
)
?
NULL
:
git_submodule_update_to_str
(
submodule
->
update
);
error
=
submodule_update_config
(
submodule
,
"update"
,
NULL
,
(
overwrite
!=
0
),
false
);
else
if
(
submodule
->
update
!=
GIT_SUBMODULE_UPDATE_DEFAULT
)
error
=
submodule_update_config
(
submodule
,
"update"
,
_sm_update_map
[
submodule
->
update
].
str_match
,
(
overwrite
!=
0
),
false
);
submodule
,
"update"
,
val
,
(
overwrite
!=
0
),
false
);
return
error
;
}
...
...
@@ -667,51 +672,70 @@ int git_submodule_sync(git_submodule *submodule)
submodule
,
"url"
,
submodule
->
url
,
true
,
true
);
}
int
git_submodule_open
(
git_repository
**
subrepo
,
git_submodule
*
submodule
)
static
int
git_submodule__open
(
git_repository
**
subrepo
,
git_submodule
*
sm
,
bool
bare
)
{
int
error
;
git_buf
path
=
GIT_BUF_INIT
;
git_repository
*
repo
;
const
char
*
w
orkdir
;
unsigned
int
flags
=
GIT_REPOSITORY_OPEN_NO_SEARCH
;
const
char
*
w
d
;
assert
(
s
ubmodule
&&
subrepo
);
assert
(
s
m
&&
subrepo
);
repo
=
submodule
->
owner
;
workdir
=
git_repository_workdir
(
repo
);
if
(
!
workdir
)
{
giterr_set
(
GITERR_REPOSITORY
,
"Cannot open submodule repository in a bare repo"
);
return
GIT_ENOTFOUND
;
}
if
(
git_repository__ensure_not_bare
(
sm
->
repo
,
"open submodule repository"
)
<
0
)
return
GIT_EBAREREPO
;
if
((
submodule
->
flags
&
GIT_SUBMODULE_STATUS_IN_WD
)
==
0
)
{
giterr_set
(
GITERR_REPOSITORY
,
"Cannot open submodule repository that is not checked out"
);
return
GIT_ENOTFOUND
;
}
wd
=
git_repository_workdir
(
sm
->
repo
);
if
(
git_buf_joinpath
(
&
path
,
workdir
,
submodule
->
path
)
<
0
)
if
(
git_buf_joinpath
(
&
path
,
wd
,
sm
->
path
)
<
0
||
git_buf_joinpath
(
&
path
,
path
.
ptr
,
DOT_GIT
)
<
0
)
return
-
1
;
error
=
git_repository_open
(
subrepo
,
path
.
ptr
);
sm
->
flags
=
sm
->
flags
&
~
(
GIT_SUBMODULE_STATUS_IN_WD
|
GIT_SUBMODULE_STATUS__WD_OID_VALID
|
GIT_SUBMODULE_STATUS__WD_SCANNED
);
git_buf_free
(
&
path
);
if
(
bare
)
flags
|=
GIT_REPOSITORY_OPEN_BARE
;
/* if we have opened the submodule successfully, let's grab the HEAD OID */
error
=
git_repository_open_ext
(
subrepo
,
path
.
ptr
,
flags
,
wd
);
/* if we opened the submodule successfully, grab HEAD OID, etc. */
if
(
!
error
)
{
if
(
!
git_reference_name_to_id
(
&
submodule
->
wd_oid
,
*
subrepo
,
GIT_HEAD_FILE
))
submodule
->
flags
|=
GIT_SUBMODULE_STATUS__WD_OID_VALID
;
sm
->
flags
|=
GIT_SUBMODULE_STATUS_IN_WD
|
GIT_SUBMODULE_STATUS__WD_SCANNED
;
if
(
!
git_reference_name_to_id
(
&
sm
->
wd_oid
,
*
subrepo
,
GIT_HEAD_FILE
))
sm
->
flags
|=
GIT_SUBMODULE_STATUS__WD_OID_VALID
;
else
giterr_clear
();
}
else
if
(
git_path_exists
(
path
.
ptr
))
{
sm
->
flags
|=
GIT_SUBMODULE_STATUS__WD_SCANNED
|
GIT_SUBMODULE_STATUS_IN_WD
;
}
else
{
git_buf_rtruncate_at_char
(
&
path
,
'/'
);
/* remove "/.git" */
if
(
git_path_isdir
(
path
.
ptr
))
sm
->
flags
|=
GIT_SUBMODULE_STATUS__WD_SCANNED
;
}
git_buf_free
(
&
path
);
return
error
;
}
int
git_submodule_open_bare
(
git_repository
**
subrepo
,
git_submodule
*
sm
)
{
return
git_submodule__open
(
subrepo
,
sm
,
true
);
}
int
git_submodule_open
(
git_repository
**
subrepo
,
git_submodule
*
sm
)
{
return
git_submodule__open
(
subrepo
,
sm
,
false
);
}
int
git_submodule_reload_all
(
git_repository
*
repo
)
{
assert
(
repo
);
...
...
@@ -719,74 +743,99 @@ int git_submodule_reload_all(git_repository *repo)
return
load_submodule_config
(
repo
);
}
int
git_submodule_reload
(
git_submodule
*
submodule
)
static
void
submodule_update_from_index_entry
(
git_submodule
*
sm
,
const
git_index_entry
*
ie
)
{
git_repository
*
repo
;
git_index
*
index
;
int
error
;
size_t
pos
;
git_tree
*
head
;
git_config_backend
*
mods
;
bool
already_found
=
(
sm
->
flags
&
GIT_SUBMODULE_STATUS_IN_INDEX
)
!=
0
;
assert
(
submodule
);
if
(
!
S_ISGITLINK
(
ie
->
mode
))
{
if
(
!
already_found
)
sm
->
flags
|=
GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
}
else
{
if
(
already_found
)
sm
->
flags
|=
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
else
git_oid_cpy
(
&
sm
->
index_oid
,
&
ie
->
oid
);
/* refresh index data */
sm
->
flags
|=
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS__INDEX_OID_VALID
;
}
}
static
int
submodule_update_index
(
git_submodule
*
sm
)
{
git_index
*
index
;
const
git_index_entry
*
ie
;
repo
=
submodule
->
owner
;
if
(
git_repository_index__weakptr
(
&
index
,
repo
)
<
0
)
if
(
git_repository_index__weakptr
(
&
index
,
sm
->
repo
)
<
0
)
return
-
1
;
s
ubmodule
->
flags
=
submodule
->
flags
&
s
m
->
flags
=
sm
->
flags
&
~
(
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS__INDEX_OID_VALID
);
if
(
!
git_index_find
(
&
pos
,
index
,
submodule
->
path
))
{
const
git_index_entry
*
entry
=
git_index_get_byindex
(
index
,
pos
)
;
if
(
!
(
ie
=
git_index_get_bypath
(
index
,
sm
->
path
,
0
)))
return
0
;
if
(
S_ISGITLINK
(
entry
->
mode
))
{
if
((
error
=
submodule_load_from_index
(
repo
,
entry
))
<
0
)
return
error
;
}
else
{
submodule_mode_mismatch
(
repo
,
entry
->
path
,
GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
);
}
}
submodule_update_from_index_entry
(
sm
,
ie
);
/* refresh HEAD tree data */
return
0
;
}
if
(
!
(
error
=
git_repository_head_tree
(
&
head
,
repo
)))
{
static
void
submodule_update_from_head_data
(
git_submodule
*
sm
,
mode_t
mode
,
const
git_oid
*
id
)
{
if
(
!
S_ISGITLINK
(
mode
))
sm
->
flags
|=
GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
else
{
git_oid_cpy
(
&
sm
->
head_oid
,
id
);
sm
->
flags
|=
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
}
}
static
int
submodule_update_head
(
git_submodule
*
submodule
)
{
git_tree
*
head
=
NULL
;
git_tree_entry
*
te
;
submodule
->
flags
=
submodule
->
flags
&
~
(
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS__HEAD_OID_VALID
);
if
(
!
(
error
=
git_tree_entry_bypath
(
&
te
,
head
,
submodule
->
path
)))
{
if
(
S_ISGITLINK
(
te
->
attr
))
{
error
=
submodule_load_from_head
(
repo
,
submodule
->
path
,
&
te
->
oid
);
}
else
{
submodule_mode_mismatch
(
repo
,
submodule
->
path
,
GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
);
}
git_tree_entry_free
(
te
);
}
else
if
(
error
==
GIT_ENOTFOUND
)
{
/* if we can't look up file in current head, then done */
if
(
git_repository_head_tree
(
&
head
,
submodule
->
repo
)
<
0
||
git_tree_entry_bypath
(
&
te
,
head
,
submodule
->
path
)
<
0
)
giterr_clear
();
error
=
0
;
}
else
submodule_update_from_head_data
(
submodule
,
te
->
attr
,
&
te
->
oid
);
git_tree_free
(
head
);
}
return
0
;
}
if
(
error
<
0
)
return
error
;
int
git_submodule_reload
(
git_submodule
*
submodule
)
{
int
error
=
0
;
git_config_backend
*
mods
;
assert
(
submodule
);
/* refresh index data */
if
(
submodule_update_index
(
submodule
)
<
0
)
return
-
1
;
/* refresh HEAD tree data */
if
(
submodule_update_head
(
submodule
)
<
0
)
return
-
1
;
/* refresh config data */
if
((
mods
=
open_gitmodules
(
repo
,
false
,
NULL
))
!=
NULL
)
{
mods
=
open_gitmodules
(
submodule
->
repo
,
false
,
NULL
);
if
(
mods
!=
NULL
)
{
git_buf
path
=
GIT_BUF_INIT
;
git_buf_sets
(
&
path
,
"submodule
\\
."
);
...
...
@@ -797,7 +846,7 @@ int git_submodule_reload(git_submodule *submodule)
error
=
-
1
;
else
error
=
git_config_file_foreach_match
(
mods
,
path
.
ptr
,
submodule_load_from_config
,
repo
);
mods
,
path
.
ptr
,
submodule_load_from_config
,
submodule
->
repo
);
git_buf_free
(
&
path
);
git_config_file_free
(
mods
);
...
...
@@ -816,38 +865,90 @@ int git_submodule_reload(git_submodule *submodule)
return
error
;
}
int
git_submodule_status
(
unsigned
int
*
status
,
git_submodule
*
submodule
)
static
void
submodule_copy_oid_maybe
(
git_oid
*
tgt
,
const
git_oid
*
src
,
bool
valid
)
{
int
error
=
0
;
unsigned
int
status_val
;
if
(
tgt
)
{
if
(
valid
)
memcpy
(
tgt
,
src
,
sizeof
(
*
tgt
));
else
memset
(
tgt
,
0
,
sizeof
(
*
tgt
));
}
}
assert
(
status
&&
submodule
);
int
git_submodule__status
(
unsigned
int
*
out_status
,
git_oid
*
out_head_id
,
git_oid
*
out_index_id
,
git_oid
*
out_wd_id
,
git_submodule
*
sm
,
git_submodule_ignore_t
ign
)
{
unsigned
int
status
;
git_repository
*
smrepo
=
NULL
;
status_val
=
GIT_SUBMODULE_STATUS__CLEAR_INTERNAL
(
submodule
->
flags
);
if
(
ign
<
GIT_SUBMODULE_IGNORE_NONE
)
ign
=
sm
->
ignore
;
if
(
submodule
->
ignore
!=
GIT_SUBMODULE_IGNORE_ALL
)
{
if
(
!
(
error
=
submodule_index_status
(
&
status_val
,
submodule
)))
error
=
submodule_wd_status
(
&
status_val
,
submodule
);
/* only return location info if ignore == all */
if
(
ign
==
GIT_SUBMODULE_IGNORE_ALL
)
{
*
out_status
=
(
sm
->
flags
&
GIT_SUBMODULE_STATUS__IN_FLAGS
);
return
0
;
}
*
status
=
status_val
;
/* refresh the index OID */
if
(
submodule_update_index
(
sm
)
<
0
)
return
-
1
;
return
error
;
/* refresh the HEAD OID */
if
(
submodule_update_head
(
sm
)
<
0
)
return
-
1
;
/* for ignore == dirty, don't scan the working directory */
if
(
ign
==
GIT_SUBMODULE_IGNORE_DIRTY
)
{
/* git_submodule_open_bare will load WD OID data */
if
(
git_submodule_open_bare
(
&
smrepo
,
sm
)
<
0
)
giterr_clear
();
else
git_repository_free
(
smrepo
);
smrepo
=
NULL
;
}
else
if
(
git_submodule_open
(
&
smrepo
,
sm
)
<
0
)
{
giterr_clear
();
smrepo
=
NULL
;
}
status
=
GIT_SUBMODULE_STATUS__CLEAR_INTERNAL
(
sm
->
flags
);
submodule_get_index_status
(
&
status
,
sm
);
submodule_get_wd_status
(
&
status
,
sm
,
smrepo
,
ign
);
git_repository_free
(
smrepo
);
*
out_status
=
status
;
submodule_copy_oid_maybe
(
out_head_id
,
&
sm
->
head_oid
,
(
sm
->
flags
&
GIT_SUBMODULE_STATUS__HEAD_OID_VALID
)
!=
0
);
submodule_copy_oid_maybe
(
out_index_id
,
&
sm
->
index_oid
,
(
sm
->
flags
&
GIT_SUBMODULE_STATUS__INDEX_OID_VALID
)
!=
0
);
submodule_copy_oid_maybe
(
out_wd_id
,
&
sm
->
wd_oid
,
(
sm
->
flags
&
GIT_SUBMODULE_STATUS__WD_OID_VALID
)
!=
0
);
return
0
;
}
int
git_submodule_location
(
unsigned
int
*
location_status
,
git_submodule
*
submodule
)
int
git_submodule_status
(
unsigned
int
*
status
,
git_submodule
*
sm
)
{
assert
(
location_status
&&
submodule
);
assert
(
status
&&
sm
);
*
location_status
=
submodule
->
flags
&
(
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
GIT_SUBMODULE_STATUS_IN_WD
);
return
git_submodule__status
(
status
,
NULL
,
NULL
,
NULL
,
sm
,
0
);
}
return
0
;
int
git_submodule_location
(
unsigned
int
*
location
,
git_submodule
*
sm
)
{
assert
(
location
&&
sm
);
return
git_submodule__status
(
location
,
NULL
,
NULL
,
NULL
,
sm
,
GIT_SUBMODULE_IGNORE_ALL
);
}
...
...
@@ -857,54 +958,50 @@ int git_submodule_location(
static
git_submodule
*
submodule_alloc
(
git_repository
*
repo
,
const
char
*
name
)
{
size_t
namelen
;
git_submodule
*
sm
;
if
(
!
name
||
!
strlen
(
name
))
{
if
(
!
name
||
!
(
namelen
=
strlen
(
name
)
))
{
giterr_set
(
GITERR_SUBMODULE
,
"Invalid submodule name"
);
return
NULL
;
}
sm
=
git__calloc
(
1
,
sizeof
(
git_submodule
));
if
(
sm
==
NULL
)
goto
fail
;
return
NULL
;
sm
->
path
=
sm
->
name
=
git__strdup
(
name
);
if
(
!
sm
->
name
)
goto
fail
;
sm
->
name
=
sm
->
path
=
git__strdup
(
name
);
if
(
!
sm
->
name
)
{
git__free
(
sm
);
return
NULL
;
}
sm
->
owner
=
repo
;
sm
->
refcount
=
1
;
GIT_REFCOUNT_INC
(
sm
);
sm
->
ignore
=
sm
->
ignore_default
=
GIT_SUBMODULE_IGNORE_NONE
;
sm
->
update
=
sm
->
update_default
=
GIT_SUBMODULE_UPDATE_CHECKOUT
;
sm
->
repo
=
repo
;
return
sm
;
fail:
submodule_release
(
sm
,
0
);
return
NULL
;
}
static
void
submodule_release
(
git_submodule
*
sm
,
int
decr
)
static
void
submodule_release
(
git_submodule
*
sm
)
{
if
(
!
sm
)
return
;
sm
->
refcount
-=
decr
;
if
(
sm
->
refcount
==
0
)
{
if
(
sm
->
name
!=
sm
->
path
)
{
if
(
sm
->
path
!=
sm
->
name
)
git__free
(
sm
->
path
);
sm
->
path
=
NULL
;
}
git__free
(
sm
->
name
);
sm
->
name
=
NULL
;
git__free
(
sm
->
url
);
sm
->
url
=
NULL
;
sm
->
owner
=
NULL
;
git__memzero
(
sm
,
sizeof
(
*
sm
));
git__free
(
sm
);
}
}
void
git_submodule_free
(
git_submodule
*
sm
)
{
if
(
!
sm
)
return
;
GIT_REFCOUNT_DEC
(
sm
,
submodule_release
);
}
static
int
submodule_get
(
...
...
@@ -934,10 +1031,10 @@ static int submodule_get(
pos
=
kh_put
(
str
,
smcfg
,
sm
->
name
,
&
error
);
if
(
error
<
0
)
{
submodule_release
(
sm
,
1
);
git_submodule_free
(
sm
);
sm
=
NULL
;
}
else
if
(
error
==
0
)
{
submodule_release
(
sm
,
1
);
git_submodule_free
(
sm
);
sm
=
git_strmap_value_at
(
smcfg
,
pos
);
}
else
{
git_strmap_set_value_at
(
smcfg
,
pos
,
sm
);
...
...
@@ -951,50 +1048,41 @@ static int submodule_get(
return
(
sm
!=
NULL
)
?
0
:
-
1
;
}
static
int
submodule_load_from_index
(
git_repository
*
repo
,
const
git_index_entry
*
entry
)
static
int
submodule_config_error
(
const
char
*
property
,
const
char
*
value
)
{
git_submodule
*
sm
;
if
(
submodule_get
(
&
sm
,
repo
,
entry
->
path
,
NULL
)
<
0
)
giterr_set
(
GITERR_INVALID
,
"Invalid value for submodule '%s' property: '%s'"
,
property
,
value
);
return
-
1
;
}
if
(
sm
->
flags
&
GIT_SUBMODULE_STATUS_IN_INDEX
)
{
sm
->
flags
|=
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
return
0
;
}
sm
->
flags
|=
GIT_SUBMODULE_STATUS_IN_INDEX
;
int
git_submodule_parse_ignore
(
git_submodule_ignore_t
*
out
,
const
char
*
value
)
{
int
val
;
git_oid_cpy
(
&
sm
->
index_oid
,
&
entry
->
oid
);
sm
->
flags
|=
GIT_SUBMODULE_STATUS__INDEX_OID_VALID
;
if
(
git_config_lookup_map_value
(
&
val
,
_sm_ignore_map
,
ARRAY_SIZE
(
_sm_ignore_map
),
value
)
<
0
)
{
*
out
=
GIT_SUBMODULE_IGNORE_NONE
;
return
submodule_config_error
(
"ignore"
,
value
);
}
*
out
=
(
git_submodule_ignore_t
)
val
;
return
0
;
}
static
int
submodule_load_from_head
(
git_repository
*
repo
,
const
char
*
path
,
const
git_oid
*
oid
)
int
git_submodule_parse_update
(
git_submodule_update_t
*
out
,
const
char
*
value
)
{
git_submodule
*
sm
;
if
(
submodule_get
(
&
sm
,
repo
,
path
,
NULL
)
<
0
)
return
-
1
;
sm
->
flags
|=
GIT_SUBMODULE_STATUS_IN_HEAD
;
int
val
;
git_oid_cpy
(
&
sm
->
head_oid
,
oid
);
sm
->
flags
|=
GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
if
(
git_config_lookup_map_value
(
&
val
,
_sm_update_map
,
ARRAY_SIZE
(
_sm_update_map
),
value
)
<
0
)
{
*
out
=
GIT_SUBMODULE_UPDATE_CHECKOUT
;
return
submodule_config_error
(
"update"
,
value
);
}
*
out
=
(
git_submodule_update_t
)
val
;
return
0
;
}
static
int
submodule_config_error
(
const
char
*
property
,
const
char
*
value
)
{
giterr_set
(
GITERR_INVALID
,
"Invalid value for submodule '%s' property: '%s'"
,
property
,
value
);
return
-
1
;
}
static
int
submodule_load_from_config
(
const
git_config_entry
*
entry
,
void
*
data
)
{
...
...
@@ -1047,11 +1135,11 @@ static int submodule_load_from_config(
git_strmap_insert2
(
smcfg
,
alternate
,
sm
,
old_sm
,
error
);
if
(
error
>=
0
)
sm
->
refcount
++
;
/* inserted under a new key */
GIT_REFCOUNT_INC
(
sm
)
;
/* inserted under a new key */
/* if we replaced an old module under this key, release the old one */
if
(
old_sm
&&
((
git_submodule
*
)
old_sm
)
!=
sm
)
{
submodule_release
(
old_sm
,
1
);
git_submodule_free
(
old_sm
);
/* TODO: log warning about multiple submodules with same path */
}
}
...
...
@@ -1076,22 +1164,18 @@ static int submodule_load_from_config(
return
-
1
;
}
else
if
(
strcasecmp
(
property
,
"update"
)
==
0
)
{
int
val
;
if
(
git_config_lookup_map_value
(
&
val
,
_sm_update_map
,
ARRAY_SIZE
(
_sm_update_map
),
value
)
<
0
)
return
submodule_config_error
(
"update"
,
value
);
sm
->
update_default
=
sm
->
update
=
(
git_submodule_update_t
)
val
;
if
(
git_submodule_parse_update
(
&
sm
->
update
,
value
)
<
0
)
return
-
1
;
sm
->
update_default
=
sm
->
update
;
}
else
if
(
strcasecmp
(
property
,
"fetchRecurseSubmodules"
)
==
0
)
{
if
(
git__parse_bool
(
&
sm
->
fetch_recurse
,
value
)
<
0
)
return
submodule_config_error
(
"fetchRecurseSubmodules"
,
value
);
}
else
if
(
strcasecmp
(
property
,
"ignore"
)
==
0
)
{
int
val
;
if
(
git_config_lookup_map_value
(
&
val
,
_sm_ignore_map
,
ARRAY_SIZE
(
_sm_ignore_map
),
value
)
<
0
)
return
submodule_config_error
(
"ignore"
,
value
);
sm
->
ignore_default
=
sm
->
ignore
=
(
git_submodule_ignore_t
)
val
;
if
(
git_submodule_parse_ignore
(
&
sm
->
ignore
,
value
)
<
0
)
return
-
1
;
sm
->
ignore_default
=
sm
->
ignore
;
}
/* ignore other unknown submodule properties */
...
...
@@ -1101,13 +1185,15 @@ static int submodule_load_from_config(
static
int
submodule_load_from_wd_lite
(
git_submodule
*
sm
,
const
char
*
name
,
void
*
payload
)
{
git_repository
*
repo
=
git_submodule_owner
(
sm
);
git_buf
path
=
GIT_BUF_INIT
;
GIT_UNUSED
(
name
);
GIT_UNUSED
(
payload
);
if
(
git_buf_joinpath
(
&
path
,
git_repository_workdir
(
repo
),
sm
->
path
)
<
0
)
if
(
git_repository_is_bare
(
sm
->
repo
))
return
0
;
if
(
git_buf_joinpath
(
&
path
,
git_repository_workdir
(
sm
->
repo
),
sm
->
path
)
<
0
)
return
-
1
;
if
(
git_path_isdir
(
path
.
ptr
))
...
...
@@ -1121,18 +1207,6 @@ static int submodule_load_from_wd_lite(
return
0
;
}
static
void
submodule_mode_mismatch
(
git_repository
*
repo
,
const
char
*
path
,
unsigned
int
flag
)
{
khiter_t
pos
=
git_strmap_lookup_index
(
repo
->
submodules
,
path
);
if
(
git_strmap_valid_index
(
repo
->
submodules
,
pos
))
{
git_submodule
*
sm
=
git_strmap_value_at
(
repo
->
submodules
,
pos
);
sm
->
flags
|=
flag
;
}
}
static
int
load_submodule_config_from_index
(
git_repository
*
repo
,
git_oid
*
gitmodules_oid
)
{
...
...
@@ -1146,19 +1220,22 @@ static int load_submodule_config_from_index(
return
error
;
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
khiter_t
pos
=
git_strmap_lookup_index
(
repo
->
submodules
,
entry
->
path
);
git_submodule
*
sm
;
if
(
S_ISGITLINK
(
entry
->
mode
))
{
error
=
submodule_load_from_index
(
repo
,
entry
);
if
(
error
<
0
)
break
;
}
else
{
submodule_mode_mismatch
(
repo
,
entry
->
path
,
GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
);
if
(
git_strmap_valid_index
(
repo
->
submodules
,
pos
))
{
sm
=
git_strmap_value_at
(
repo
->
submodules
,
pos
);
if
(
strcmp
(
entry
->
path
,
GIT_MODULES_FILE
)
==
0
)
if
(
S_ISGITLINK
(
entry
->
mode
))
submodule_update_from_index_entry
(
sm
,
entry
);
else
sm
->
flags
|=
GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
}
else
if
(
S_ISGITLINK
(
entry
->
mode
))
{
if
(
!
submodule_get
(
&
sm
,
repo
,
entry
->
path
,
NULL
))
submodule_update_from_index_entry
(
sm
,
entry
);
}
else
if
(
strcmp
(
entry
->
path
,
GIT_MODULES_FILE
)
==
0
)
git_oid_cpy
(
gitmodules_oid
,
&
entry
->
oid
);
}
}
if
(
error
==
GIT_ITEROVER
)
error
=
0
;
...
...
@@ -1188,17 +1265,23 @@ static int load_submodule_config_from_head(
}
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
khiter_t
pos
=
git_strmap_lookup_index
(
repo
->
submodules
,
entry
->
path
);
git_submodule
*
sm
;
if
(
S_ISGITLINK
(
entry
->
mode
))
{
error
=
submodule_load_from_head
(
repo
,
entry
->
path
,
&
entry
->
oid
);
if
(
error
<
0
)
break
;
}
else
{
submodule_mode_mismatch
(
repo
,
entry
->
path
,
GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
);
if
(
git_strmap_valid_index
(
repo
->
submodules
,
pos
))
{
sm
=
git_strmap_value_at
(
repo
->
submodules
,
pos
);
if
(
strcmp
(
entry
->
path
,
GIT_MODULES_FILE
)
==
0
&&
git_oid_iszero
(
gitmodules_oid
))
if
(
S_ISGITLINK
(
entry
->
mode
))
submodule_update_from_head_data
(
sm
,
entry
->
mode
,
&
entry
->
oid
);
else
sm
->
flags
|=
GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
}
else
if
(
S_ISGITLINK
(
entry
->
mode
))
{
if
(
!
submodule_get
(
&
sm
,
repo
,
entry
->
path
,
NULL
))
submodule_update_from_head_data
(
sm
,
entry
->
mode
,
&
entry
->
oid
);
}
else
if
(
strcmp
(
entry
->
path
,
GIT_MODULES_FILE
)
==
0
&&
git_oid_iszero
(
gitmodules_oid
))
{
git_oid_cpy
(
gitmodules_oid
,
&
entry
->
oid
);
}
}
...
...
@@ -1384,7 +1467,7 @@ static int submodule_update_config(
assert
(
submodule
);
error
=
git_repository_config__weakptr
(
&
config
,
submodule
->
owner
);
error
=
git_repository_config__weakptr
(
&
config
,
submodule
->
repo
);
if
(
error
<
0
)
return
error
;
...
...
@@ -1412,11 +1495,13 @@ cleanup:
return
error
;
}
static
int
submodule
_index_status
(
unsigned
int
*
status
,
git_submodule
*
sm
)
static
void
submodule_get
_index_status
(
unsigned
int
*
status
,
git_submodule
*
sm
)
{
const
git_oid
*
head_oid
=
git_submodule_head_id
(
sm
);
const
git_oid
*
index_oid
=
git_submodule_index_id
(
sm
);
*
status
=
*
status
&
~
GIT_SUBMODULE_STATUS__INDEX_FLAGS
;
if
(
!
head_oid
)
{
if
(
index_oid
)
*
status
|=
GIT_SUBMODULE_STATUS_INDEX_ADDED
;
...
...
@@ -1425,27 +1510,22 @@ static int submodule_index_status(unsigned int *status, git_submodule *sm)
*
status
|=
GIT_SUBMODULE_STATUS_INDEX_DELETED
;
else
if
(
!
git_oid_equal
(
head_oid
,
index_oid
))
*
status
|=
GIT_SUBMODULE_STATUS_INDEX_MODIFIED
;
return
0
;
}
static
int
submodule_wd_status
(
unsigned
int
*
status
,
git_submodule
*
sm
)
static
void
submodule_get_wd_status
(
unsigned
int
*
status
,
git_submodule
*
sm
,
git_repository
*
sm_repo
,
git_submodule_ignore_t
ign
)
{
int
error
=
0
;
const
git_oid
*
wd_oid
,
*
index_oid
;
git_repository
*
sm_repo
=
NULL
;
/* open repo now if we need it (so wd_id() call won't reopen) */
if
((
sm
->
ignore
==
GIT_SUBMODULE_IGNORE_NONE
||
sm
->
ignore
==
GIT_SUBMODULE_IGNORE_UNTRACKED
)
&&
(
sm
->
flags
&
GIT_SUBMODULE_STATUS_IN_WD
)
!=
0
)
{
if
((
error
=
git_submodule_open
(
&
sm_repo
,
sm
))
<
0
)
return
error
;
}
const
git_oid
*
index_oid
=
git_submodule_index_id
(
sm
);
const
git_oid
*
wd_oid
=
(
sm
->
flags
&
GIT_SUBMODULE_STATUS__WD_OID_VALID
)
?
&
sm
->
wd_oid
:
NULL
;
git_tree
*
sm_head
=
NULL
;
git_diff_options
opt
=
GIT_DIFF_OPTIONS_INIT
;
git_diff_list
*
diff
;
index_oid
=
git_submodule_index_id
(
sm
);
wd_oid
=
git_submodule_wd_id
(
sm
);
*
status
=
*
status
&
~
GIT_SUBMODULE_STATUS__WD_FLAGS
;
if
(
!
index_oid
)
{
if
(
wd_oid
)
...
...
@@ -1461,44 +1541,39 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
else
if
(
!
git_oid_equal
(
index_oid
,
wd_oid
))
*
status
|=
GIT_SUBMODULE_STATUS_WD_MODIFIED
;
if
(
sm_repo
!=
NULL
)
{
git_tree
*
sm_head
;
git_diff_options
opt
=
GIT_DIFF_OPTIONS_INIT
;
git_diff_list
*
diff
;
/* if we have no repo, then we're done */
if
(
!
sm_repo
)
return
;
/* the diffs below could be optimized with an early termination
* option to the git_diff functions, but for now this is sufficient
* (and certainly no worse that what core git does).
*/
/* perform head-to-index diff on submodule */
if
((
error
=
git_repository_head_tree
(
&
sm_head
,
sm_repo
))
<
0
)
return
error
;
if
(
sm
->
ignore
==
GIT_SUBMODULE_IGNORE_NONE
)
if
(
ign
==
GIT_SUBMODULE_IGNORE_NONE
)
opt
.
flags
|=
GIT_DIFF_INCLUDE_UNTRACKED
;
error
=
git_diff_tree_to_index
(
&
diff
,
sm_repo
,
sm_head
,
NULL
,
&
opt
);
if
(
!
error
)
{
/* if we don't have an orphaned head, check diff with index */
if
(
git_repository_head_tree
(
&
sm_head
,
sm_repo
)
<
0
)
giterr_clear
();
else
{
/* perform head to index diff on submodule */
if
(
git_diff_tree_to_index
(
&
diff
,
sm_repo
,
sm_head
,
NULL
,
&
opt
)
<
0
)
giterr_clear
();
else
{
if
(
git_diff_num_deltas
(
diff
)
>
0
)
*
status
|=
GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED
;
git_diff_list_free
(
diff
);
diff
=
NULL
;
}
git_tree_free
(
sm_head
);
if
(
error
<
0
)
return
error
;
}
/* perform index-to-workdir diff on submodule */
error
=
git_diff_index_to_workdir
(
&
diff
,
sm_repo
,
NULL
,
&
opt
);
if
(
!
error
)
{
if
(
git_diff_index_to_workdir
(
&
diff
,
sm_repo
,
NULL
,
&
opt
)
<
0
)
giterr_clear
();
else
{
size_t
untracked
=
git_diff_num_deltas_of_type
(
diff
,
GIT_DELTA_UNTRACKED
);
...
...
@@ -1511,9 +1586,4 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
git_diff_list_free
(
diff
);
diff
=
NULL
;
}
git_repository_free
(
sm_repo
);
}
return
error
;
}
src/submodule.h
View file @
bd679796
...
...
@@ -7,6 +7,10 @@
#ifndef INCLUDE_submodule_h__
#define INCLUDE_submodule_h__
#include "git2/submodule.h"
#include "git2/repository.h"
#include "fileops.h"
/* Notes:
*
* Submodule information can be in four places: the index, the config files
...
...
@@ -44,44 +48,51 @@
* an entry for every submodule found in the HEAD and index, and for every
* submodule described in .gitmodules. The fields are as follows:
*
* - `owner` is the git_repository containing this submodule
* - `rc` tracks the refcount of how many hash table entries in the
* git_submodule_cache there are for this submodule. It only comes into
* play if the name and path of the submodule differ.
*
* - `name` is the name of the submodule from .gitmodules.
* - `path` is the path to the submodule from the repo root. It is almost
* always the same as `name`.
* - `url` is the url for the submodule.
* - `tree_oid` is the SHA1 for the submodule path in the repo HEAD.
* - `index_oid` is the SHA1 for the submodule recorded in the index.
* - `workdir_oid` is the SHA1 for the HEAD of the checked out submodule.
* - `update` is a git_submodule_update_t value - see gitmodules(5) update.
* - `update_default` is the update value from the config
* - `ignore` is a git_submodule_ignore_t value - see gitmodules(5) ignore.
* - `ignore_default` is the ignore value from the config
* - `fetch_recurse` is 0 or 1 - see gitmodules(5) fetchRecurseSubmodules.
* - `refcount` tracks how many hashmap entries there are for this submodule.
* It only comes into play if the name and path of the submodule differ.
* - `flags` is for internal use, tracking where this submodule has been
* found (head, index, config, workdir) and other misc info about it.
*
* - `repo` is the parent repository that contains this submodule.
* - `flags` after for internal use, tracking where this submodule has been
* found (head, index, config, workdir) and known status info, etc.
* - `head_oid` is the SHA1 for the submodule path in the repo HEAD.
* - `index_oid` is the SHA1 for the submodule recorded in the index.
* - `wd_oid` is the SHA1 for the HEAD of the checked out submodule.
*
* If the submodule has been added to .gitmodules but not yet git added,
* then the `index_oid` will be
valid and zero. If the submodule has been
*
deleted, but the delete has not been committed yet, then the `index_oid`
* will be set, but the `url` will be NULL.
* then the `index_oid` will be
zero but still marked valid. If the
*
submodule has been deleted, but the delete has not been committed yet,
*
then the `index_oid`
will be set, but the `url` will be NULL.
*/
struct
git_submodule
{
git_repository
*
owner
;
git_refcount
rc
;
/* information from config */
char
*
name
;
char
*
path
;
/* important: may
point to same string data as "name"
*/
char
*
path
;
/* important: may
just point to "name" string
*/
char
*
url
;
uint32_t
flags
;
git_oid
head_oid
;
git_oid
index_oid
;
git_oid
wd_oid
;
/* information from config */
git_submodule_update_t
update
;
git_submodule_update_t
update_default
;
git_submodule_ignore_t
ignore
;
git_submodule_ignore_t
ignore_default
;
int
fetch_recurse
;
/* internal information */
int
refcount
;
git_repository
*
repo
;
uint32_t
flags
;
git_oid
head_oid
;
git_oid
index_oid
;
git_oid
wd_oid
;
};
/* Additional flags on top of public GIT_SUBMODULE_STATUS values */
...
...
@@ -99,4 +110,29 @@ enum {
#define GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(S) \
((S) & ~(0xFFFFFFFFu << 20))
/* Internal status fn returns status and optionally the various OIDs */
extern
int
git_submodule__status
(
unsigned
int
*
out_status
,
git_oid
*
out_head_id
,
git_oid
*
out_index_id
,
git_oid
*
out_wd_id
,
git_submodule
*
sm
,
git_submodule_ignore_t
ign
);
/* Open submodule repository as bare repo for quick HEAD check, etc. */
extern
int
git_submodule_open_bare
(
git_repository
**
repo
,
git_submodule
*
submodule
);
/* Release reference to submodule object - not currently for external use */
extern
void
git_submodule_free
(
git_submodule
*
sm
);
extern
int
git_submodule_parse_ignore
(
git_submodule_ignore_t
*
out
,
const
char
*
value
);
extern
int
git_submodule_parse_update
(
git_submodule_update_t
*
out
,
const
char
*
value
);
extern
const
char
*
git_submodule_ignore_to_str
(
git_submodule_ignore_t
);
extern
const
char
*
git_submodule_update_to_str
(
git_submodule_update_t
);
#endif
src/thread-utils.h
View file @
bd679796
...
...
@@ -43,6 +43,11 @@ GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
a
->
val
=
val
;
}
GIT_INLINE
(
int
)
git_atomic_get
(
git_atomic
*
a
)
{
return
(
int
)
a
->
val
;
}
#ifdef GIT_THREADS
#define git_thread pthread_t
...
...
src/util.h
View file @
bd679796
...
...
@@ -221,6 +221,9 @@ typedef void (*git_refcount_freeptr)(void *r);
#define GIT_REFCOUNT_OWNER(r) (((git_refcount *)(r))->owner)
#define GIT_REFCOUNT_VAL(r) git_atomic_get(&((git_refcount *)(r))->refcount)
static
signed
char
from_hex
[]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
/* 00 */
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
/* 10 */
...
...
tests-clar/clar_libgit2.h
View file @
bd679796
...
...
@@ -29,6 +29,9 @@
void
cl_git_report_failure
(
int
,
const
char
*
,
int
,
const
char
*
);
#define cl_assert_at_line(expr,file,line) \
clar__assert((expr) != 0, file, line, "Expression is not true: " #expr, NULL, 1)
#define cl_assert_equal_sz(sz1,sz2) cl_assert_equal_i((int)sz1, (int)(sz2))
/*
...
...
tests-clar/diff/submodules.c
View file @
bd679796
...
...
@@ -5,39 +5,17 @@
static
git_repository
*
g_repo
=
NULL
;
static
void
setup_submodules
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"submodules"
);
cl_fixture_sandbox
(
"testrepo.git"
);
rewrite_gitmodules
(
git_repository_workdir
(
g_repo
));
p_rename
(
"submodules/testrepo/.gitted"
,
"submodules/testrepo/.git"
);
}
static
void
setup_submodules2
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"submod2"
);
cl_fixture_sandbox
(
"submod2_target"
);
p_rename
(
"submod2_target/.gitted"
,
"submod2_target/.git"
);
rewrite_gitmodules
(
git_repository_workdir
(
g_repo
));
p_rename
(
"submod2/not-submodule/.gitted"
,
"submod2/not-submodule/.git"
);
p_rename
(
"submod2/not/.gitted"
,
"submod2/not/.git"
);
}
void
test_diff_submodules__initialize
(
void
)
{
}
void
test_diff_submodules__cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
cl_fixture_cleanup
(
"testrepo.git"
);
cl_fixture_cleanup
(
"submod2_target"
);
cleanup_fixture_submodules
();
}
static
void
check_diff_patches
(
git_diff_list
*
diff
,
const
char
**
expected
)
static
void
check_diff_patches_at_line
(
git_diff_list
*
diff
,
const
char
**
expected
,
const
char
*
file
,
int
line
)
{
const
git_diff_delta
*
delta
;
git_diff_patch
*
patch
=
NULL
;
...
...
@@ -48,24 +26,30 @@ static void check_diff_patches(git_diff_list *diff, const char **expected)
cl_git_pass
(
git_diff_get_patch
(
&
patch
,
&
delta
,
diff
,
d
));
if
(
delta
->
status
==
GIT_DELTA_UNMODIFIED
)
{
cl_assert
(
expected
[
d
]
==
NULL
);
cl_assert
_at_line
(
expected
[
d
]
==
NULL
,
file
,
line
);
continue
;
}
if
(
expected
[
d
]
&&
!
strcmp
(
expected
[
d
],
"<SKIP>"
))
continue
;
if
(
expected
[
d
]
&&
!
strcmp
(
expected
[
d
],
"<END>"
))
cl_assert
(
0
);
if
(
expected
[
d
]
&&
!
strcmp
(
expected
[
d
],
"<END>"
))
{
cl_git_pass
(
git_diff_patch_to_str
(
&
patch_text
,
patch
));
cl_assert_at_line
(
!
strcmp
(
expected
[
d
],
"<END>"
),
file
,
line
);
}
cl_git_pass
(
git_diff_patch_to_str
(
&
patch_text
,
patch
));
cl_assert_equal_s
(
expected
[
d
],
patch_text
);
clar__assert_equal_s
(
expected
[
d
],
patch_text
,
file
,
line
,
"expected diff did not match actual diff"
,
1
);
git__free
(
patch_text
);
}
cl_assert
(
expected
[
d
]
&&
!
strcmp
(
expected
[
d
],
"<END>"
)
);
cl_assert
_at_line
(
expected
[
d
]
&&
!
strcmp
(
expected
[
d
],
"<END>"
),
file
,
line
);
}
#define check_diff_patches(diff, exp) \
check_diff_patches_at_line(diff, exp, __FILE__, __LINE__)
void
test_diff_submodules__unmodified_submodule
(
void
)
{
git_diff_options
opts
=
GIT_DIFF_OPTIONS_INIT
;
...
...
@@ -81,11 +65,12 @@ void test_diff_submodules__unmodified_submodule(void)
"<END>"
};
setup
_submodules
();
g_repo
=
setup_fixture
_submodules
();
opts
.
flags
=
GIT_DIFF_INCLUDE_IGNORED
|
GIT_DIFF_INCLUDE_UNTRACKED
|
GIT_DIFF_INCLUDE_UNMODIFIED
;
opts
.
old_prefix
=
"a"
;
opts
.
new_prefix
=
"b"
;
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected
);
...
...
@@ -107,7 +92,7 @@ void test_diff_submodules__dirty_submodule(void)
"<END>"
};
setup
_submodules
();
g_repo
=
setup_fixture
_submodules
();
cl_git_rewritefile
(
"submodules/testrepo/README"
,
"heyheyhey"
);
cl_git_mkfile
(
"submodules/testrepo/all_new.txt"
,
"never seen before"
);
...
...
@@ -115,20 +100,73 @@ void test_diff_submodules__dirty_submodule(void)
opts
.
flags
=
GIT_DIFF_INCLUDE_IGNORED
|
GIT_DIFF_INCLUDE_UNTRACKED
|
GIT_DIFF_INCLUDE_UNMODIFIED
;
opts
.
old_prefix
=
"a"
;
opts
.
new_prefix
=
"b"
;
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected
);
git_diff_list_free
(
diff
);
}
void
test_diff_submodules__dirty_submodule_2
(
void
)
{
git_diff_options
opts
=
GIT_DIFF_OPTIONS_INIT
;
git_diff_list
*
diff
=
NULL
,
*
diff2
=
NULL
;
char
*
smpath
=
"testrepo"
;
static
const
char
*
expected_none
[]
=
{
"<END>"
};
static
const
char
*
expected_dirty
[]
=
{
"diff --git a/testrepo b/testrepo
\n
index a65fedf..a65fedf 160000
\n
--- a/testrepo
\n
+++ b/testrepo
\n
@@ -1 +1 @@
\n
-Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750
\n
+Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750-dirty
\n
"
,
/* testrepo.git */
"<END>"
};
g_repo
=
setup_fixture_submodules
();
cl_git_pass
(
git_submodule_reload_all
(
g_repo
));
opts
.
flags
=
GIT_DIFF_INCLUDE_UNTRACKED
|
GIT_DIFF_INCLUDE_UNTRACKED_CONTENT
|
GIT_DIFF_RECURSE_UNTRACKED_DIRS
|
GIT_DIFF_DISABLE_PATHSPEC_MATCH
;
opts
.
old_prefix
=
"a"
;
opts
.
new_prefix
=
"b"
;
opts
.
pathspec
.
count
=
1
;
opts
.
pathspec
.
strings
=
&
smpath
;
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_none
);
git_diff_list_free
(
diff
);
cl_git_rewritefile
(
"submodules/testrepo/README"
,
"heyheyhey"
);
cl_git_mkfile
(
"submodules/testrepo/all_new.txt"
,
"never seen before"
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_dirty
);
{
git_tree
*
head
;
cl_git_pass
(
git_repository_head_tree
(
&
head
,
g_repo
));
cl_git_pass
(
git_diff_tree_to_index
(
&
diff2
,
g_repo
,
head
,
NULL
,
&
opts
));
cl_git_pass
(
git_diff_merge
(
diff
,
diff2
));
git_diff_list_free
(
diff2
);
git_tree_free
(
head
);
check_diff_patches
(
diff
,
expected_dirty
);
}
git_diff_list_free
(
diff
);
cl_git_pass
(
git_submodule_reload_all
(
g_repo
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_dirty
);
git_diff_list_free
(
diff
);
}
void
test_diff_submodules__submod2_index_to_wd
(
void
)
{
git_diff_options
opts
=
GIT_DIFF_OPTIONS_INIT
;
git_diff_list
*
diff
=
NULL
;
static
const
char
*
expected
[]
=
{
"<SKIP>"
,
/* .gitmodules */
NULL
,
/* not-submodule */
NULL
,
/* not */
"diff --git a/sm_changed_file b/sm_changed_file
\n
index 4800958..4800958 160000
\n
--- a/sm_changed_file
\n
+++ b/sm_changed_file
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty
\n
"
,
/* sm_changed_file */
"diff --git a/sm_changed_head b/sm_changed_head
\n
index 4800958..3d9386c 160000
\n
--- a/sm_changed_head
\n
+++ b/sm_changed_head
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247
\n
"
,
/* sm_changed_head */
"diff --git a/sm_changed_index b/sm_changed_index
\n
index 4800958..4800958 160000
\n
--- a/sm_changed_index
\n
+++ b/sm_changed_index
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty
\n
"
,
/* sm_changed_index */
...
...
@@ -137,9 +175,10 @@ void test_diff_submodules__submod2_index_to_wd(void)
"<END>"
};
setup_submodules
2
();
g_repo
=
setup_fixture_submod
2
();
opts
.
flags
=
GIT_DIFF_INCLUDE_UNTRACKED
;
opts
.
old_prefix
=
"a"
;
opts
.
new_prefix
=
"b"
;
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected
);
...
...
@@ -157,11 +196,12 @@ void test_diff_submodules__submod2_head_to_index(void)
"<END>"
};
setup_submodules
2
();
g_repo
=
setup_fixture_submod
2
();
cl_git_pass
(
git_repository_head_tree
(
&
head
,
g_repo
));
opts
.
flags
=
GIT_DIFF_INCLUDE_UNTRACKED
;
opts
.
old_prefix
=
"a"
;
opts
.
new_prefix
=
"b"
;
cl_git_pass
(
git_diff_tree_to_index
(
&
diff
,
g_repo
,
head
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected
);
...
...
@@ -169,3 +209,233 @@ void test_diff_submodules__submod2_head_to_index(void)
git_tree_free
(
head
);
}
void
test_diff_submodules__invalid_cache
(
void
)
{
git_diff_options
opts
=
GIT_DIFF_OPTIONS_INIT
;
git_diff_list
*
diff
=
NULL
;
git_submodule
*
sm
;
char
*
smpath
=
"sm_changed_head"
;
git_repository
*
smrepo
;
git_index
*
smindex
;
static
const
char
*
expected_baseline
[]
=
{
"diff --git a/sm_changed_head b/sm_changed_head
\n
index 4800958..3d9386c 160000
\n
--- a/sm_changed_head
\n
+++ b/sm_changed_head
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247
\n
"
,
/* sm_changed_head */
"<END>"
};
static
const
char
*
expected_unchanged
[]
=
{
"<END>"
};
static
const
char
*
expected_dirty
[]
=
{
"diff --git a/sm_changed_head b/sm_changed_head
\n
index 3d9386c..3d9386c 160000
\n
--- a/sm_changed_head
\n
+++ b/sm_changed_head
\n
@@ -1 +1 @@
\n
-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247
\n
+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247-dirty
\n
"
,
"<END>"
};
static
const
char
*
expected_moved
[]
=
{
"diff --git a/sm_changed_head b/sm_changed_head
\n
index 3d9386c..0910a13 160000
\n
--- a/sm_changed_head
\n
+++ b/sm_changed_head
\n
@@ -1 +1 @@
\n
-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247
\n
+Subproject commit 0910a13dfa2210496f6c590d75bc360dd11b2a1b
\n
"
,
"<END>"
};
static
const
char
*
expected_moved_dirty
[]
=
{
"diff --git a/sm_changed_head b/sm_changed_head
\n
index 3d9386c..0910a13 160000
\n
--- a/sm_changed_head
\n
+++ b/sm_changed_head
\n
@@ -1 +1 @@
\n
-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247
\n
+Subproject commit 0910a13dfa2210496f6c590d75bc360dd11b2a1b-dirty
\n
"
,
"<END>"
};
g_repo
=
setup_fixture_submod2
();
opts
.
flags
=
GIT_DIFF_INCLUDE_UNTRACKED
;
opts
.
old_prefix
=
"a"
;
opts
.
new_prefix
=
"b"
;
opts
.
pathspec
.
count
=
1
;
opts
.
pathspec
.
strings
=
&
smpath
;
/* baseline */
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_baseline
);
git_diff_list_free
(
diff
);
/* update index with new HEAD */
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
smpath
));
cl_git_pass
(
git_submodule_add_to_index
(
sm
,
1
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_unchanged
);
git_diff_list_free
(
diff
);
/* create untracked file in submodule working directory */
cl_git_mkfile
(
"submod2/sm_changed_head/new_around_here"
,
"hello"
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_NONE
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_dirty
);
git_diff_list_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_UNTRACKED
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_unchanged
);
git_diff_list_free
(
diff
);
/* modify tracked file in submodule working directory */
cl_git_append2file
(
"submod2/sm_changed_head/file_to_modify"
,
"
\n
more stuff
\n
"
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_dirty
);
git_diff_list_free
(
diff
);
cl_git_pass
(
git_submodule_reload_all
(
g_repo
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
smpath
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_dirty
);
git_diff_list_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_DIRTY
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_unchanged
);
git_diff_list_free
(
diff
);
/* add file to index in submodule */
cl_git_pass
(
git_submodule_open
(
&
smrepo
,
sm
));
cl_git_pass
(
git_repository_index
(
&
smindex
,
smrepo
));
cl_git_pass
(
git_index_add_bypath
(
smindex
,
"file_to_modify"
));
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_UNTRACKED
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_dirty
);
git_diff_list_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_DIRTY
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_unchanged
);
git_diff_list_free
(
diff
);
/* commit changed index of submodule */
{
git_object
*
parent
;
git_oid
tree_id
,
commit_id
;
git_tree
*
tree
;
git_signature
*
sig
;
git_reference
*
ref
;
cl_git_pass
(
git_revparse_ext
(
&
parent
,
&
ref
,
smrepo
,
"HEAD"
));
cl_git_pass
(
git_index_write_tree
(
&
tree_id
,
smindex
));
cl_git_pass
(
git_index_write
(
smindex
));
cl_git_pass
(
git_tree_lookup
(
&
tree
,
smrepo
,
&
tree_id
));
cl_git_pass
(
git_signature_new
(
&
sig
,
"Sm Test"
,
"sm@tester.test"
,
1372350000
,
480
));
cl_git_pass
(
git_commit_create_v
(
&
commit_id
,
smrepo
,
git_reference_name
(
ref
),
sig
,
sig
,
NULL
,
"Move it"
,
tree
,
1
,
parent
));
git_object_free
(
parent
);
git_tree_free
(
tree
);
git_reference_free
(
ref
);
git_signature_free
(
sig
);
}
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_DIRTY
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_moved
);
git_diff_list_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_ALL
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_unchanged
);
git_diff_list_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_NONE
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_moved_dirty
);
git_diff_list_free
(
diff
);
p_unlink
(
"submod2/sm_changed_head/new_around_here"
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_moved
);
git_diff_list_free
(
diff
);
git_index_free
(
smindex
);
git_repository_free
(
smrepo
);
}
void
test_diff_submodules__diff_ignore_options
(
void
)
{
git_diff_options
opts
=
GIT_DIFF_OPTIONS_INIT
;
git_diff_list
*
diff
=
NULL
;
git_config
*
cfg
;
static
const
char
*
expected_normal
[]
=
{
"<SKIP>"
,
/* .gitmodules */
"diff --git a/sm_changed_file b/sm_changed_file
\n
index 4800958..4800958 160000
\n
--- a/sm_changed_file
\n
+++ b/sm_changed_file
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty
\n
"
,
/* sm_changed_file */
"diff --git a/sm_changed_head b/sm_changed_head
\n
index 4800958..3d9386c 160000
\n
--- a/sm_changed_head
\n
+++ b/sm_changed_head
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247
\n
"
,
/* sm_changed_head */
"diff --git a/sm_changed_index b/sm_changed_index
\n
index 4800958..4800958 160000
\n
--- a/sm_changed_index
\n
+++ b/sm_changed_index
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty
\n
"
,
/* sm_changed_index */
"diff --git a/sm_changed_untracked_file b/sm_changed_untracked_file
\n
index 4800958..4800958 160000
\n
--- a/sm_changed_untracked_file
\n
+++ b/sm_changed_untracked_file
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty
\n
"
,
/* sm_changed_untracked_file */
"diff --git a/sm_missing_commits b/sm_missing_commits
\n
index 4800958..5e49635 160000
\n
--- a/sm_missing_commits
\n
+++ b/sm_missing_commits
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad
\n
"
,
/* sm_missing_commits */
"<END>"
};
static
const
char
*
expected_ignore_all
[]
=
{
"<SKIP>"
,
/* .gitmodules */
"<END>"
};
static
const
char
*
expected_ignore_dirty
[]
=
{
"<SKIP>"
,
/* .gitmodules */
"diff --git a/sm_changed_head b/sm_changed_head
\n
index 4800958..3d9386c 160000
\n
--- a/sm_changed_head
\n
+++ b/sm_changed_head
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247
\n
"
,
/* sm_changed_head */
"diff --git a/sm_missing_commits b/sm_missing_commits
\n
index 4800958..5e49635 160000
\n
--- a/sm_missing_commits
\n
+++ b/sm_missing_commits
\n
@@ -1 +1 @@
\n
-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0
\n
+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad
\n
"
,
/* sm_missing_commits */
"<END>"
};
g_repo
=
setup_fixture_submod2
();
opts
.
flags
=
GIT_DIFF_INCLUDE_UNTRACKED
;
opts
.
old_prefix
=
"a"
;
opts
.
new_prefix
=
"b"
;
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_normal
);
git_diff_list_free
(
diff
);
opts
.
flags
|=
GIT_DIFF_IGNORE_SUBMODULES
;
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_ignore_all
);
git_diff_list_free
(
diff
);
opts
.
flags
&=
~
GIT_DIFF_IGNORE_SUBMODULES
;
opts
.
ignore_submodules
=
GIT_SUBMODULE_IGNORE_ALL
;
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_ignore_all
);
git_diff_list_free
(
diff
);
opts
.
ignore_submodules
=
GIT_SUBMODULE_IGNORE_DIRTY
;
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_ignore_dirty
);
git_diff_list_free
(
diff
);
opts
.
ignore_submodules
=
0
;
cl_git_pass
(
git_repository_config
(
&
cfg
,
g_repo
));
cl_git_pass
(
git_config_set_bool
(
cfg
,
"diff.ignoreSubmodules"
,
false
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_normal
);
git_diff_list_free
(
diff
);
cl_git_pass
(
git_config_set_bool
(
cfg
,
"diff.ignoreSubmodules"
,
true
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_ignore_all
);
git_diff_list_free
(
diff
);
cl_git_pass
(
git_config_set_string
(
cfg
,
"diff.ignoreSubmodules"
,
"none"
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_normal
);
git_diff_list_free
(
diff
);
cl_git_pass
(
git_config_set_string
(
cfg
,
"diff.ignoreSubmodules"
,
"dirty"
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_ignore_dirty
);
git_diff_list_free
(
diff
);
git_config_free
(
cfg
);
}
tests-clar/diff/workdir.c
View file @
bd679796
...
...
@@ -776,6 +776,7 @@ void test_diff_workdir__submodules(void)
opts
.
flags
=
GIT_DIFF_INCLUDE_UNTRACKED
|
GIT_DIFF_INCLUDE_IGNORED
|
GIT_DIFF_RECURSE_UNTRACKED_DIRS
|
GIT_DIFF_INCLUDE_UNTRACKED_CONTENT
;
...
...
@@ -806,7 +807,7 @@ void test_diff_workdir__submodules(void)
* only significant difference is that those Added items will show up
* as Untracked items in the pure libgit2 diff.
*
* Then add in the two extra
untrack
ed items "not" and "not-submodule"
* Then add in the two extra
ignor
ed items "not" and "not-submodule"
* to get the 12 files reported here.
*/
...
...
@@ -815,8 +816,8 @@ void test_diff_workdir__submodules(void)
cl_assert_equal_i
(
0
,
exp
.
file_status
[
GIT_DELTA_ADDED
]);
cl_assert_equal_i
(
0
,
exp
.
file_status
[
GIT_DELTA_DELETED
]);
cl_assert_equal_i
(
2
,
exp
.
file_status
[
GIT_DELTA_MODIFIED
]);
cl_assert_equal_i
(
0
,
exp
.
file_status
[
GIT_DELTA_IGNORED
]);
cl_assert_equal_i
(
10
,
exp
.
file_status
[
GIT_DELTA_UNTRACKED
]);
cl_assert_equal_i
(
2
,
exp
.
file_status
[
GIT_DELTA_IGNORED
]);
cl_assert_equal_i
(
8
,
exp
.
file_status
[
GIT_DELTA_UNTRACKED
]);
/* the following numbers match "git diff 873585" exactly */
...
...
tests-clar/repo/open.c
View file @
bd679796
...
...
@@ -69,14 +69,23 @@ void test_repo_open__open_with_discover(void)
cl_fixture_cleanup
(
"attr"
);
}
static
void
make_gitlink_dir
(
const
char
*
dir
,
const
char
*
linktext
)
{
git_buf
path
=
GIT_BUF_INIT
;
cl_git_pass
(
git_futils_mkdir
(
dir
,
NULL
,
0777
,
GIT_MKDIR_VERIFY_DIR
));
cl_git_pass
(
git_buf_joinpath
(
&
path
,
dir
,
".git"
));
cl_git_rewritefile
(
path
.
ptr
,
linktext
);
git_buf_free
(
&
path
);
}
void
test_repo_open__gitlinked
(
void
)
{
/* need to have both repo dir and workdir set up correctly */
git_repository
*
repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
git_repository
*
repo2
;
cl_must_pass
(
p_mkdir
(
"alternate"
,
0777
));
cl_git_mkfile
(
"alternate/.git"
,
"gitdir: ../empty_standard_repo/.git"
);
make_gitlink_dir
(
"alternate"
,
"gitdir: ../empty_standard_repo/.git"
);
cl_git_pass
(
git_repository_open
(
&
repo2
,
"alternate"
));
...
...
@@ -193,12 +202,11 @@ void test_repo_open__bad_gitlinks(void)
cl_git_sandbox_init
(
"attr"
);
cl_git_pass
(
p_mkdir
(
"alternate"
,
0777
));
cl_git_pass
(
p_mkdir
(
"invalid"
,
0777
));
cl_git_pass
(
git_futils_mkdir_r
(
"invalid2/.git"
,
NULL
,
0777
));
for
(
scan
=
bad_links
;
*
scan
!=
NULL
;
scan
++
)
{
cl_git_rewritefile
(
"alternate/.git
"
,
*
scan
);
make_gitlink_dir
(
"alternate
"
,
*
scan
);
cl_git_fail
(
git_repository_open_ext
(
&
repo
,
"alternate"
,
0
,
NULL
));
}
...
...
@@ -315,3 +323,52 @@ void test_repo_open__no_config(void)
git_repository_free
(
repo
);
cl_fixture_cleanup
(
"empty_standard_repo"
);
}
void
test_repo_open__force_bare
(
void
)
{
/* need to have both repo dir and workdir set up correctly */
git_repository
*
repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
git_repository
*
barerepo
;
make_gitlink_dir
(
"alternate"
,
"gitdir: ../empty_standard_repo/.git"
);
cl_assert
(
!
git_repository_is_bare
(
repo
));
cl_git_pass
(
git_repository_open
(
&
barerepo
,
"alternate"
));
cl_assert
(
!
git_repository_is_bare
(
barerepo
));
git_repository_free
(
barerepo
);
cl_git_pass
(
git_repository_open_bare
(
&
barerepo
,
"empty_standard_repo/.git"
));
cl_assert
(
git_repository_is_bare
(
barerepo
));
git_repository_free
(
barerepo
);
cl_git_fail
(
git_repository_open_bare
(
&
barerepo
,
"alternate/.git"
));
cl_git_pass
(
git_repository_open_ext
(
&
barerepo
,
"alternate/.git"
,
GIT_REPOSITORY_OPEN_BARE
,
NULL
));
cl_assert
(
git_repository_is_bare
(
barerepo
));
git_repository_free
(
barerepo
);
cl_git_pass
(
p_mkdir
(
"empty_standard_repo/subdir"
,
0777
));
cl_git_mkfile
(
"empty_standard_repo/subdir/something.txt"
,
"something"
);
cl_git_fail
(
git_repository_open_bare
(
&
barerepo
,
"empty_standard_repo/subdir"
));
cl_git_pass
(
git_repository_open_ext
(
&
barerepo
,
"empty_standard_repo/subdir"
,
GIT_REPOSITORY_OPEN_BARE
,
NULL
));
cl_assert
(
git_repository_is_bare
(
barerepo
));
git_repository_free
(
barerepo
);
cl_git_pass
(
p_mkdir
(
"alternate/subdir"
,
0777
));
cl_git_pass
(
p_mkdir
(
"alternate/subdir/sub2"
,
0777
));
cl_git_mkfile
(
"alternate/subdir/sub2/something.txt"
,
"something"
);
cl_git_fail
(
git_repository_open_bare
(
&
barerepo
,
"alternate/subdir/sub2"
));
cl_git_pass
(
git_repository_open_ext
(
&
barerepo
,
"alternate/subdir/sub2"
,
GIT_REPOSITORY_OPEN_BARE
,
NULL
));
cl_assert
(
git_repository_is_bare
(
barerepo
));
git_repository_free
(
barerepo
);
}
tests-clar/status/submodules.c
View file @
bd679796
...
...
@@ -9,25 +9,19 @@ static git_repository *g_repo = NULL;
void
test_status_submodules__initialize
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"submodules"
);
cl_fixture_sandbox
(
"testrepo.git"
);
rewrite_gitmodules
(
git_repository_workdir
(
g_repo
));
p_rename
(
"submodules/testrepo/.gitted"
,
"submodules/testrepo/.git"
);
}
void
test_status_submodules__cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
cl_fixture_cleanup
(
"testrepo.git"
);
cleanup_fixture_submodules
();
}
void
test_status_submodules__api
(
void
)
{
git_submodule
*
sm
;
g_repo
=
setup_fixture_submodules
();
cl_assert
(
git_submodule_lookup
(
NULL
,
g_repo
,
"nonexistent"
)
==
GIT_ENOTFOUND
);
cl_assert
(
git_submodule_lookup
(
NULL
,
g_repo
,
"modified"
)
==
GIT_ENOTFOUND
);
...
...
@@ -42,6 +36,8 @@ void test_status_submodules__0(void)
{
int
counts
=
0
;
g_repo
=
setup_fixture_submodules
();
cl_assert
(
git_path_isdir
(
"submodules/.git"
));
cl_assert
(
git_path_isdir
(
"submodules/testrepo/.git"
));
cl_assert
(
git_path_isfile
(
"submodules/.gitmodules"
));
...
...
@@ -86,6 +82,8 @@ void test_status_submodules__1(void)
{
status_entry_counts
counts
;
g_repo
=
setup_fixture_submodules
();
cl_assert
(
git_path_isdir
(
"submodules/.git"
));
cl_assert
(
git_path_isdir
(
"submodules/testrepo/.git"
));
cl_assert
(
git_path_isfile
(
"submodules/.gitmodules"
));
...
...
@@ -104,6 +102,7 @@ void test_status_submodules__1(void)
void
test_status_submodules__single_file
(
void
)
{
unsigned
int
status
=
0
;
g_repo
=
setup_fixture_submodules
();
cl_git_pass
(
git_status_file
(
&
status
,
g_repo
,
"testrepo"
)
);
cl_assert
(
!
status
);
}
...
...
@@ -134,6 +133,8 @@ void test_status_submodules__moved_head(void)
GIT_STATUS_WT_NEW
};
g_repo
=
setup_fixture_submodules
();
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
cl_git_pass
(
git_submodule_open
(
&
smrepo
,
sm
));
...
...
@@ -192,6 +193,8 @@ void test_status_submodules__dirty_workdir_only(void)
GIT_STATUS_WT_NEW
};
g_repo
=
setup_fixture_submodules
();
cl_git_rewritefile
(
"submodules/testrepo/README"
,
"heyheyhey"
);
cl_git_mkfile
(
"submodules/testrepo/all_new.txt"
,
"never seen before"
);
...
...
tests-clar/submodule/modify.c
View file @
bd679796
...
...
@@ -204,10 +204,10 @@ void test_submodule_modify__edit_and_save(void)
cl_git_pass
(
git_submodule_set_url
(
sm1
,
old_url
));
cl_assert_equal_i
(
(
int
)
GIT_SUBMODULE_IGNORE_UNTRACKED
,
(
int
)
git_submodule_set_ignore
(
sm1
,
GIT_SUBMODULE_IGNORE_
DEFAUL
T
));
(
int
)
git_submodule_set_ignore
(
sm1
,
GIT_SUBMODULE_IGNORE_
RESE
T
));
cl_assert_equal_i
(
(
int
)
GIT_SUBMODULE_UPDATE_REBASE
,
(
int
)
git_submodule_set_update
(
sm1
,
GIT_SUBMODULE_UPDATE_
DEFAUL
T
));
(
int
)
git_submodule_set_update
(
sm1
,
GIT_SUBMODULE_UPDATE_
RESE
T
));
cl_assert_equal_i
(
1
,
git_submodule_set_fetch_recurse_submodules
(
sm1
,
old_fetchrecurse
));
...
...
@@ -228,10 +228,10 @@ void test_submodule_modify__edit_and_save(void)
cl_git_pass
(
git_submodule_save
(
sm1
));
/* attempt to "revert" values */
git_submodule_set_ignore
(
sm1
,
GIT_SUBMODULE_IGNORE_
DEFAUL
T
);
git_submodule_set_update
(
sm1
,
GIT_SUBMODULE_UPDATE_
DEFAUL
T
);
git_submodule_set_ignore
(
sm1
,
GIT_SUBMODULE_IGNORE_
RESE
T
);
git_submodule_set_update
(
sm1
,
GIT_SUBMODULE_UPDATE_
RESE
T
);
/* but ignore and update should NOT revert because the
DEFAUL
T
/* but ignore and update should NOT revert because the
RESE
T
* should now be the newly saved value...
*/
cl_assert_equal_i
(
...
...
tests-clar/submodule/status.c
View file @
bd679796
...
...
@@ -9,21 +9,12 @@ static git_repository *g_repo = NULL;
void
test_submodule_status__initialize
(
void
)
{
g_repo
=
cl_git_sandbox_init
(
"submod2"
);
cl_fixture_sandbox
(
"submod2_target"
);
p_rename
(
"submod2_target/.gitted"
,
"submod2_target/.git"
);
/* must create submod2_target before rewrite so prettify will work */
rewrite_gitmodules
(
git_repository_workdir
(
g_repo
));
p_rename
(
"submod2/not-submodule/.gitted"
,
"submod2/not-submodule/.git"
);
p_rename
(
"submod2/not/.gitted"
,
"submod2/not/.git"
);
g_repo
=
setup_fixture_submod2
();
}
void
test_submodule_status__cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
cl_fixture_cleanup
(
"submod2_target"
);
cleanup_fixture_submodules
();
}
void
test_submodule_status__unchanged
(
void
)
...
...
@@ -326,6 +317,7 @@ void test_submodule_status__ignore_all(void)
typedef
struct
{
size_t
counter
;
const
char
**
paths
;
int
*
statuses
;
}
submodule_expectations
;
static
int
confirm_submodule_status
(
...
...
@@ -336,6 +328,7 @@ static int confirm_submodule_status(
while
(
git__suffixcmp
(
exp
->
paths
[
exp
->
counter
],
"/"
)
==
0
)
exp
->
counter
++
;
cl_assert_equal_i
(
exp
->
statuses
[
exp
->
counter
],
(
int
)
status_flags
);
cl_assert_equal_s
(
exp
->
paths
[
exp
->
counter
++
],
path
);
GIT_UNUSED
(
status_flags
);
...
...
@@ -365,7 +358,24 @@ void test_submodule_status__iterator(void)
"sm_unchanged"
,
NULL
};
submodule_expectations
exp
=
{
0
,
expected
};
static
int
expected_flags
[]
=
{
GIT_STATUS_INDEX_MODIFIED
|
GIT_STATUS_WT_MODIFIED
,
/* ".gitmodules" */
0
,
/* "just_a_dir/" will be skipped */
GIT_STATUS_CURRENT
,
/* "just_a_dir/contents" */
GIT_STATUS_CURRENT
,
/* "just_a_file" */
GIT_STATUS_IGNORED
,
/* "not" (contains .git) */
GIT_STATUS_IGNORED
,
/* "not-submodule" (contains .git) */
GIT_STATUS_CURRENT
,
/* "README.txt */
GIT_STATUS_INDEX_NEW
,
/* "sm_added_and_uncommited" */
GIT_STATUS_WT_MODIFIED
,
/* "sm_changed_file" */
GIT_STATUS_WT_MODIFIED
,
/* "sm_changed_head" */
GIT_STATUS_WT_MODIFIED
,
/* "sm_changed_index" */
GIT_STATUS_WT_MODIFIED
,
/* "sm_changed_untracked_file" */
GIT_STATUS_WT_MODIFIED
,
/* "sm_missing_commits" */
GIT_STATUS_CURRENT
,
/* "sm_unchanged" */
0
};
submodule_expectations
exp
=
{
0
,
expected
,
expected_flags
};
git_status_options
opts
=
GIT_STATUS_OPTIONS_INIT
;
cl_git_pass
(
git_iterator_for_workdir
(
&
iter
,
g_repo
,
...
...
@@ -378,6 +388,7 @@ void test_submodule_status__iterator(void)
opts
.
flags
=
GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
GIT_STATUS_OPT_INCLUDE_UNMODIFIED
|
GIT_STATUS_OPT_INCLUDE_IGNORED
|
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
;
cl_git_pass
(
git_status_foreach_ext
(
...
...
tests-clar/submodule/submodule_helpers.c
View file @
bd679796
...
...
@@ -82,3 +82,38 @@ void rewrite_gitmodules(const char *workdir)
git_buf_free
(
&
out_f
);
git_buf_free
(
&
path
);
}
git_repository
*
setup_fixture_submodules
(
void
)
{
git_repository
*
repo
=
cl_git_sandbox_init
(
"submodules"
);
cl_fixture_sandbox
(
"testrepo.git"
);
rewrite_gitmodules
(
git_repository_workdir
(
repo
));
p_rename
(
"submodules/testrepo/.gitted"
,
"submodules/testrepo/.git"
);
return
repo
;
}
git_repository
*
setup_fixture_submod2
(
void
)
{
git_repository
*
repo
=
cl_git_sandbox_init
(
"submod2"
);
cl_fixture_sandbox
(
"submod2_target"
);
p_rename
(
"submod2_target/.gitted"
,
"submod2_target/.git"
);
rewrite_gitmodules
(
git_repository_workdir
(
repo
));
p_rename
(
"submod2/not-submodule/.gitted"
,
"submod2/not-submodule/.git"
);
p_rename
(
"submod2/not/.gitted"
,
"submod2/not/.git"
);
return
repo
;
}
void
cleanup_fixture_submodules
(
void
)
{
cl_git_sandbox_cleanup
();
/* just try to clean up both possible extras */
cl_fixture_cleanup
(
"testrepo.git"
);
cl_fixture_cleanup
(
"submod2_target"
);
}
tests-clar/submodule/submodule_helpers.h
View file @
bd679796
extern
void
rewrite_gitmodules
(
const
char
*
workdir
);
extern
git_repository
*
setup_fixture_submodules
(
void
);
extern
git_repository
*
setup_fixture_submod2
(
void
);
extern
void
cleanup_fixture_submodules
(
void
);
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