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
daacf96d
Commit
daacf96d
authored
Jun 24, 2015
by
Carlos Martín Nieto
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3097 from libgit2/cmn/submodule-config-state
Remove run-time configuration settings from submodules
parents
e1f434f8
783672fa
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
633 additions
and
1032 deletions
+633
-1032
examples/status.c
+10
-16
include/git2/diff.h
+1
-1
include/git2/submodule.h
+41
-72
include/git2/types.h
+2
-10
src/checkout.c
+2
-8
src/config.c
+20
-0
src/config.h
+6
-0
src/diff_file.c
+1
-1
src/repository.c
+0
-1
src/repository.h
+0
-1
src/submodule.c
+409
-662
src/submodule.h
+0
-24
tests/diff/submodules.c
+8
-8
tests/diff/tree.c
+1
-1
tests/submodule/init.c
+3
-3
tests/submodule/modify.c
+77
-126
tests/submodule/nosubs.c
+0
-44
tests/submodule/status.c
+27
-38
tests/submodule/submodule_helpers.c
+4
-7
tests/submodule/update.c
+21
-9
No files found.
examples/status.c
View file @
daacf96d
...
...
@@ -384,25 +384,19 @@ static void print_short(git_repository *repo, git_status_list *status)
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
))
{
if
(
!
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
(
!
git_submodule_status
(
&
smstatus
,
repo
,
s
->
index_to_workdir
->
new_file
.
path
,
GIT_SUBMODULE_IGNORE_FALLBACK
))
{
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)"
;
}
git_submodule_free
(
sm
);
}
/**
...
...
include/git2/diff.h
View file @
daacf96d
...
...
@@ -399,7 +399,7 @@ typedef struct {
* `git_diff_options_init` programmatic initialization.
*/
#define GIT_DIFF_OPTIONS_INIT \
{GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_
DEFAULT
, {NULL,0}, NULL, NULL, 3}
{GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_
FALLBACK
, {NULL,0}, NULL, NULL, 3}
/**
* Initializes a `git_diff_options` with default values. Equivalent to
...
...
include/git2/submodule.h
View file @
daacf96d
...
...
@@ -301,20 +301,6 @@ GIT_EXTERN(int) git_submodule_add_to_index(
int
write_index
);
/**
* Write submodule settings to .gitmodules file.
*
* This commits any in-memory changes to the submodule to the gitmodules
* file on disk. You may also be interested in `git_submodule_init()` which
* writes submodule info to ".git/config" (which is better for local changes
* to submodule settings) and/or `git_submodule_sync()` which writes
* settings about remotes to the actual submodule repository.
*
* @param submodule The submodule to write.
* @return 0 on success, <0 on failure.
*/
GIT_EXTERN
(
int
)
git_submodule_save
(
git_submodule
*
submodule
);
/**
* Get the containing repository for a submodule.
*
* This returns a pointer to the repository that contains the submodule.
...
...
@@ -373,36 +359,31 @@ GIT_EXTERN(int) git_submodule_resolve_url(git_buf *out, git_repository *repo, co
GIT_EXTERN
(
const
char
*
)
git_submodule_branch
(
git_submodule
*
submodule
);
/**
* Set the branch for the submodule
.
* Set the branch for the submodule
in the configuration
*
* This sets the branch in memory for the submodule. This will be used for
* any following submodule actions while this submodule data is in memory.
*
* After calling this, you may wish to call `git_submodule_save()` to write
* the changes back to the ".gitmodules" file and `git_submodule_sync()` to
* After calling this, you may wish to call `git_submodule_sync()` to
* write the changes to the checked out submodule repository.
*
* @param submodule Pointer to the submodule object
* @param repo the repository to affect
* @param name the name of the submodule to configure
* @param branch Branch that should be used for the submodule
* @return 0 on success, <0 on failure
*/
GIT_EXTERN
(
int
)
git_submodule_set_branch
(
git_
submodule
*
submodul
e
,
const
char
*
branch
);
GIT_EXTERN
(
int
)
git_submodule_set_branch
(
git_
repository
*
repo
,
const
char
*
nam
e
,
const
char
*
branch
);
/**
* Set the URL for the submodule
.
* Set the URL for the submodule
in the configuration
*
* This sets the URL in memory for the submodule. This will be used for
* any following submodule actions while this submodule data is in memory.
*
* After calling this, you may wish to call `git_submodule_save()` to write
* the changes back to the ".gitmodules" file and `git_submodule_sync()` to
* After calling this, you may wish to call `git_submodule_sync()` to
* write the changes to the checked out submodule repository.
*
* @param submodule Pointer to the submodule object
* @param repo the repository to affect
* @param name the name of the submodule to configure
* @param url URL that should be used for the submodule
* @return 0 on success, <0 on failure
*/
GIT_EXTERN
(
int
)
git_submodule_set_url
(
git_
submodule
*
submodul
e
,
const
char
*
url
);
GIT_EXTERN
(
int
)
git_submodule_set_url
(
git_
repository
*
repo
,
const
char
*
nam
e
,
const
char
*
url
);
/**
* Get the OID for the submodule in the index.
...
...
@@ -452,9 +433,6 @@ GIT_EXTERN(const git_oid *) git_submodule_wd_id(git_submodule *submodule);
* The working directory will be consider clean so long as there is a
* checked out version present.
*
* plus the special **GIT_SUBMODULE_IGNORE_RESET** which can be used with
* `git_submodule_set_ignore()` to revert to the on-disk setting.
*
* @param submodule The submodule to check
* @return The current git_submodule_ignore_t valyue what will be used for
* this submodule.
...
...
@@ -463,32 +441,25 @@ GIT_EXTERN(git_submodule_ignore_t) git_submodule_ignore(
git_submodule
*
submodule
);
/**
* Set the ignore rule for the submodule.
*
* This sets the in-memory ignore rule for the submodule which will
* control the behavior of `git_submodule_status()`.
* Set the ignore rule for the submodule in the configuration
*
* To make changes persistent, call `git_submodule_save()` to write the
* value to disk (in the ".gitmodules" and ".git/config" files).
* This does not affect any currently-loaded instances.
*
* Call with `GIT_SUBMODULE_IGNORE_RESET` or call `git_submodule_reload()`
* to revert the in-memory rule to the value that is on disk.
*
* @param submodule The submodule to update
* @param repo the repository to affect
* @param name the name of the submdule
* @param ignore The new value for the ignore rule
* @return
old value for ignor
e
* @return
0 or an error cod
e
*/
GIT_EXTERN
(
git_submodule_ignore_t
)
git_submodule_set_ignore
(
git_submodule
*
submodule
,
GIT_EXTERN
(
int
)
git_submodule_set_ignore
(
git_repository
*
repo
,
const
char
*
name
,
git_submodule_ignore_t
ignore
);
/**
* Get the update rule that will be used for the submodule.
*
* This value controls the behavior of the `git submodule update` command.
* There are four useful values documented with `git_submodule_update_t`
* plus the `GIT_SUBMODULE_UPDATE_RESET` which can be used to revert to
* the on-disk setting.
* There are four useful values documented with `git_submodule_update_t`.
*
* @param submodule The submodule to check
* @return The current git_submodule_update_t value that will be used
...
...
@@ -498,23 +469,18 @@ GIT_EXTERN(git_submodule_update_t) git_submodule_update_strategy(
git_submodule
*
submodule
);
/**
* Set the update rule for the submodule.
*
* The initial value comes from the ".git/config" setting of
* `submodule.$name.update` for this submodule (which is initialized from
* the ".gitmodules" file). Using this function sets the update rule in
* memory for the submodule. Call `git_submodule_save()` to write out the
* new update rule.
* Set the update rule for the submodule in the configuration
*
* Calling this again with GIT_SUBMODULE_UPDATE_RESET or calling
* `git_submodule_reload()` will revert the rule to the on disk value.
* This setting won't affect any existing instances.
*
* @param submodule The submodule to update
* @param repo the repository to affect
* @param name the name of the submodule to configure
* @param update The new value to use
* @return
old value for updat
e
* @return
0 or an error cod
e
*/
GIT_EXTERN
(
git_submodule_update_t
)
git_submodule_set_update
(
git_submodule
*
submodule
,
GIT_EXTERN
(
int
)
git_submodule_set_update
(
git_repository
*
repo
,
const
char
*
name
,
git_submodule_update_t
update
);
/**
...
...
@@ -532,18 +498,18 @@ GIT_EXTERN(git_submodule_recurse_t) git_submodule_fetch_recurse_submodules(
git_submodule
*
submodule
);
/**
* Set the fetchRecurseSubmodules rule for a submodule
.
* Set the fetchRecurseSubmodules rule for a submodule
in the configuration
*
* This sets the submodule.<name>.fetchRecurseSubmodules value for
* the submodule. You should call `git_submodule_save()` if you want
* to persist the new value.
* This setting won't affect any existing instances.
*
* @param submodule The submodule to modify
* @param repo the repository to affect
* @param name the submodule to configure
* @param fetch_recurse_submodules Boolean value
* @return old value for fetchRecurseSubmodules
*/
GIT_EXTERN
(
git_submodule_recurse_t
)
git_submodule_set_fetch_recurse_submodules
(
git_submodule
*
submodule
,
GIT_EXTERN
(
int
)
git_submodule_set_fetch_recurse_submodules
(
git_repository
*
repo
,
const
char
*
name
,
git_submodule_recurse_t
fetch_recurse_submodules
);
/**
...
...
@@ -634,16 +600,19 @@ GIT_EXTERN(int) git_submodule_reload_all(git_repository *repo, int force);
* This looks at a submodule and tries to determine the status. It
* will return a combination of the `GIT_SUBMODULE_STATUS` values above.
* How deeply it examines the working directory to do this will depend
* on the `git_submodule_ignore_t` value for the submodule - which can be
* set either temporarily or permanently with `git_submodule_set_ignore()`.
* on the `git_submodule_ignore_t` value for the submodule.
*
* @param status Combination of `GIT_SUBMODULE_STATUS` flags
* @param submodule Submodule for which to get status
* @param repo the repository in which to look
* @param name name of the submodule
* @param ignore the ignore rules to follow
* @return 0 on success, <0 on error
*/
GIT_EXTERN
(
int
)
git_submodule_status
(
unsigned
int
*
status
,
git_submodule
*
submodule
);
git_repository
*
repo
,
const
char
*
name
,
git_submodule_ignore_t
ignore
);
/**
* Get the locations of submodule information.
...
...
include/git2/types.h
View file @
daacf96d
...
...
@@ -349,7 +349,6 @@ typedef struct git_submodule git_submodule;
*
* The values are:
*
* - GIT_SUBMODULE_UPDATE_RESET: reset to the on-disk value.
* - GIT_SUBMODULE_UPDATE_CHECKOUT: the default; when a submodule is
* updated, checkout the new detached HEAD to the submodule directory.
* - GIT_SUBMODULE_UPDATE_REBASE: update by rebasing the current checked
...
...
@@ -362,8 +361,6 @@ typedef struct git_submodule git_submodule;
* when we don't want any particular update rule to be specified.
*/
typedef
enum
{
GIT_SUBMODULE_UPDATE_RESET
=
-
1
,
GIT_SUBMODULE_UPDATE_CHECKOUT
=
1
,
GIT_SUBMODULE_UPDATE_REBASE
=
2
,
GIT_SUBMODULE_UPDATE_MERGE
=
3
,
...
...
@@ -386,7 +383,7 @@ typedef enum {
*
* The values are:
*
* - GIT_SUBMODULE_IGNORE_
RESET: reset to the on-disk value.
* - GIT_SUBMODULE_IGNORE_
FALLBACK: use the submodule's configuration
* - GIT_SUBMODULE_IGNORE_NONE: don't ignore any change - i.e. even an
* untracked file, will mark the submodule as dirty. Ignored files are
* still ignored, of course.
...
...
@@ -400,14 +397,12 @@ typedef enum {
* when we don't want any particular ignore rule to be specified.
*/
typedef
enum
{
GIT_SUBMODULE_IGNORE_
RESET
=
-
1
,
/**< reset to on-disk value
*/
GIT_SUBMODULE_IGNORE_
FALLBACK
=
-
1
,
/**< use the submodule's configuration
*/
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_DEFAULT
=
0
}
git_submodule_ignore_t
;
/**
...
...
@@ -415,15 +410,12 @@ typedef enum {
*
* Represent the value of `submodule.$name.fetchRecurseSubmodules`
*
* * GIT_SUBMODULE_RECURSE_RESET - reset to the on-disk value
* * GIT_SUBMODULE_RECURSE_NO - do no recurse into submodules
* * GIT_SUBMODULE_RECURSE_YES - recurse into submodules
* * GIT_SUBMODULE_RECURSE_ONDEMAND - recurse into submodules only when
* commit not already in local clone
*/
typedef
enum
{
GIT_SUBMODULE_RECURSE_RESET
=
-
1
,
GIT_SUBMODULE_RECURSE_NO
=
0
,
GIT_SUBMODULE_RECURSE_YES
=
1
,
GIT_SUBMODULE_RECURSE_ONDEMAND
=
2
,
...
...
src/checkout.c
View file @
daacf96d
...
...
@@ -180,7 +180,7 @@ static bool checkout_is_workdir_modified(
return
true
;
}
if
(
git_submodule_status
(
&
sm_status
,
sm
)
<
0
||
if
(
git_submodule_status
(
&
sm_status
,
data
->
repo
,
wditem
->
path
,
GIT_SUBMODULE_IGNORE_FALLBACK
)
<
0
||
GIT_SUBMODULE_STATUS_IS_WD_DIRTY
(
sm_status
))
rval
=
true
;
else
if
((
sm_oid
=
git_submodule_wd_id
(
sm
))
==
NULL
)
...
...
@@ -1860,11 +1860,6 @@ static int checkout_create_submodules(
git_diff_delta
*
delta
;
size_t
i
;
/* initial reload of submodules if .gitmodules was changed */
if
(
data
->
reload_submodules
&&
(
error
=
git_submodule_reload_all
(
data
->
repo
,
1
))
<
0
)
return
error
;
git_vector_foreach
(
&
data
->
diff
->
deltas
,
i
,
delta
)
{
if
(
actions
[
i
]
&
CHECKOUT_ACTION__DEFER_REMOVE
)
{
/* this has a blocker directory that should only be removed iff
...
...
@@ -1885,8 +1880,7 @@ static int checkout_create_submodules(
}
}
/* final reload once submodules have been updated */
return
git_submodule_reload_all
(
data
->
repo
,
1
);
return
0
;
}
static
int
checkout_lookup_head_tree
(
git_tree
**
out
,
git_repository
*
repo
)
...
...
src/config.c
View file @
daacf96d
...
...
@@ -1194,6 +1194,26 @@ fail_parse:
return
-
1
;
}
int
git_config_lookup_map_enum
(
git_cvar_t
*
type_out
,
const
char
**
str_out
,
const
git_cvar_map
*
maps
,
size_t
map_n
,
int
enum_val
)
{
size_t
i
;
for
(
i
=
0
;
i
<
map_n
;
i
++
)
{
const
git_cvar_map
*
m
=
&
maps
[
i
];
if
(
m
->
map_value
!=
enum_val
)
continue
;
*
type_out
=
m
->
cvar_type
;
*
str_out
=
m
->
str_match
;
return
0
;
}
giterr_set
(
GITERR_CONFIG
,
"invalid enum value"
);
return
GIT_ENOTFOUND
;
}
int
git_config_parse_bool
(
int
*
out
,
const
char
*
value
)
{
if
(
git__parse_bool
(
out
,
value
)
==
0
)
...
...
src/config.h
View file @
daacf96d
...
...
@@ -82,4 +82,10 @@ extern int git_config__get_int_force(
extern
int
git_config__cvar
(
int
*
out
,
git_config
*
config
,
git_cvar_cached
cvar
);
/**
* The opposite of git_config_lookup_map_value, we take an enum value
* and map it to the string or bool value on the config.
*/
int
git_config_lookup_map_enum
(
git_cvar_t
*
type_out
,
const
char
**
str_out
,
const
git_cvar_map
*
maps
,
size_t
map_n
,
int
enum_val
);
#endif
src/diff_file.c
View file @
daacf96d
...
...
@@ -186,7 +186,7 @@ static int diff_file_content_commit_to_str(
return
error
;
}
if
((
error
=
git_submodule_status
(
&
sm_status
,
sm
))
<
0
)
{
if
((
error
=
git_submodule_status
(
&
sm_status
,
fc
->
repo
,
fc
->
file
->
path
,
GIT_SUBMODULE_IGNORE_FALLBACK
))
<
0
)
{
git_submodule_free
(
sm
);
return
error
;
}
...
...
src/repository.c
View file @
daacf96d
...
...
@@ -111,7 +111,6 @@ void git_repository__cleanup(git_repository *repo)
git_cache_clear
(
&
repo
->
objects
);
git_attr_cache_flush
(
repo
);
git_submodule_cache_free
(
repo
);
set_config
(
repo
,
NULL
);
set_index
(
repo
,
NULL
);
...
...
src/repository.h
View file @
daacf96d
...
...
@@ -121,7 +121,6 @@ struct git_repository {
git_refdb
*
_refdb
;
git_config
*
_config
;
git_index
*
_index
;
git_submodule_cache
*
_submodules
;
git_cache
objects
;
git_attr_cache
*
attrcache
;
...
...
src/submodule.c
View file @
daacf96d
...
...
@@ -87,17 +87,16 @@ __KHASH_IMPL(
str
,
static
kh_inline
,
const
char
*
,
void
*
,
1
,
str_hash_no_trailing_slash
,
str_equal_no_trailing_slash
)
static
int
submodule_cache_init
(
git_repository
*
repo
,
int
refresh
);
static
void
submodule_cache_free
(
git_submodule_cache
*
cache
);
static
git_config_backend
*
open_gitmodules
(
git_submodule_cache
*
,
int
gitmod
);
static
int
submodule_alloc
(
git_submodule
**
out
,
git_repository
*
repo
,
const
char
*
name
);
static
git_config_backend
*
open_gitmodules
(
git_repository
*
repo
,
int
gitmod
);
static
int
get_url_base
(
git_buf
*
url
,
git_repository
*
repo
);
static
int
lookup_head_remote_key
(
git_buf
*
remote_key
,
git_repository
*
repo
);
static
int
submodule_get
(
git_submodule
**
,
git_submodule_cache
*
,
const
char
*
,
const
char
*
);
static
int
submodule_load_from_config
(
const
git_config_entry
*
,
void
*
);
static
int
submodule_load_from_wd_lite
(
git_submodule
*
);
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
void
submodule_update_from_index_entry
(
git_submodule
*
sm
,
const
git_index_entry
*
ie
);
static
void
submodule_update_from_head_data
(
git_submodule
*
sm
,
mode_t
mode
,
const
git_oid
*
id
);
static
int
submodule_cmp
(
const
void
*
a
,
const
void
*
b
)
{
...
...
@@ -111,69 +110,10 @@ static int submodule_config_key_trunc_puts(git_buf *key, const char *suffix)
return
git_buf_puts
(
key
,
suffix
);
}
/* lookup submodule or return ENOTFOUND if it doesn't exist */
static
int
submodule_lookup
(
git_submodule
**
out
,
git_submodule_cache
*
cache
,
const
char
*
name
,
const
char
*
alternate
)
{
khiter_t
pos
;
/* lock cache */
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
name
);
if
(
!
git_strmap_valid_index
(
cache
->
submodules
,
pos
)
&&
alternate
)
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
alternate
);
if
(
!
git_strmap_valid_index
(
cache
->
submodules
,
pos
))
{
/* unlock cache */
return
GIT_ENOTFOUND
;
/* don't set error - caller will cope */
}
if
(
out
!=
NULL
)
{
git_submodule
*
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
GIT_REFCOUNT_INC
(
sm
);
*
out
=
sm
;
}
/* unlock cache */
return
0
;
}
/* clear a set of flags on all submodules */
static
void
submodule_cache_clear_flags
(
git_submodule_cache
*
cache
,
uint32_t
mask
)
{
git_submodule
*
sm
;
uint32_t
inverted_mask
=
~
mask
;
git_strmap_foreach_value
(
cache
->
submodules
,
sm
,
{
sm
->
flags
&=
inverted_mask
;
});
}
/*
* PUBLIC APIS
*/
bool
git_submodule__is_submodule
(
git_repository
*
repo
,
const
char
*
name
)
{
git_strmap
*
map
;
if
(
submodule_cache_init
(
repo
,
CACHE_OK
)
<
0
)
{
giterr_clear
();
return
false
;
}
if
(
!
repo
->
_submodules
||
!
(
map
=
repo
->
_submodules
->
submodules
))
return
false
;
return
git_strmap_valid_index
(
map
,
git_strmap_lookup_index
(
map
,
name
));
}
static
void
submodule_set_lookup_error
(
int
error
,
const
char
*
name
)
{
if
(
!
error
)
...
...
@@ -184,22 +124,24 @@ static void submodule_set_lookup_error(int error, const char *name)
"Submodule '%s' has not been added yet"
,
name
);
}
int
git_submodule__lookup
(
git_submodule
**
out
,
/* NULL if user only wants to test existence */
git_repository
*
repo
,
const
char
*
name
)
/* trailing slash is allowed */
{
int
error
;
assert
(
repo
&&
name
);
typedef
struct
{
const
char
*
path
;
char
*
name
;
}
fbp_data
;
if
((
error
=
submodule_cache_init
(
repo
,
CACHE_OK
))
<
0
)
return
error
;
static
int
find_by_path
(
const
git_config_entry
*
entry
,
void
*
payload
)
{
fbp_data
*
data
=
payload
;
if
((
error
=
submodule_lookup
(
out
,
repo
->
_submodules
,
name
,
NULL
))
<
0
)
submodule_set_lookup_error
(
error
,
name
);
if
(
!
strcmp
(
entry
->
value
,
data
->
path
))
{
const
char
*
fdot
,
*
ldot
;
fdot
=
strchr
(
entry
->
name
,
'.'
);
ldot
=
strrchr
(
entry
->
name
,
'.'
);
data
->
name
=
git__strndup
(
fdot
+
1
,
ldot
-
fdot
-
1
);
GITERR_CHECK_ALLOC
(
data
->
name
);
}
return
error
;
return
0
;
}
int
git_submodule_lookup
(
...
...
@@ -208,20 +150,71 @@ int git_submodule_lookup(
const
char
*
name
)
/* trailing slash is allowed */
{
int
error
;
unsigned
int
location
;
git_submodule
*
sm
;
assert
(
repo
&&
name
);
if
((
error
=
submodule_
cache_init
(
repo
,
CACHE_REFRESH
))
<
0
)
if
((
error
=
submodule_
alloc
(
&
sm
,
repo
,
name
))
<
0
)
return
error
;
if
((
error
=
submodule_lookup
(
out
,
repo
->
_submodules
,
name
,
NULL
))
<
0
)
{
if
((
error
=
git_submodule_reload
(
sm
,
false
))
<
0
)
{
git_submodule_free
(
sm
);
return
error
;
}
if
((
error
=
git_submodule_location
(
&
location
,
sm
))
<
0
)
{
git_submodule_free
(
sm
);
return
error
;
}
/* If it's not configured, we need to check for the path */
if
(
location
==
0
||
location
==
GIT_SUBMODULE_STATUS_IN_WD
)
{
git_config_backend
*
mods
;
const
char
*
pattern
=
"submodule
\\
..*
\\
.path"
;
fbp_data
data
=
{
name
,
NULL
};
mods
=
open_gitmodules
(
repo
,
GITMODULES_EXISTING
);
if
(
mods
)
error
=
git_config_file_foreach_match
(
mods
,
pattern
,
find_by_path
,
&
data
);
/* check if a plausible submodule exists at path */
git_config_file_free
(
mods
);
if
(
error
<
0
)
{
git_submodule_free
(
sm
);
return
error
;
}
if
(
data
.
name
)
{
git__free
(
sm
->
name
);
sm
->
name
=
data
.
name
;
sm
->
path
=
git__strdup
(
name
);
GITERR_CHECK_ALLOC
(
sm
->
path
);
/* Try to load again with the right name */
if
((
error
=
git_submodule_reload
(
sm
,
false
))
<
0
)
{
git_submodule_free
(
sm
);
return
error
;
}
}
}
if
((
error
=
git_submodule_location
(
&
location
,
sm
))
<
0
)
{
git_submodule_free
(
sm
);
return
error
;
}
/* If we still haven't found it, do the WD check */
if
(
location
==
0
||
location
==
GIT_SUBMODULE_STATUS_IN_WD
)
{
git_submodule_free
(
sm
);
error
=
GIT_ENOTFOUND
;
/* If it's not configured, we still check if there's a repo at the path */
if
(
git_repository_workdir
(
repo
))
{
git_buf
path
=
GIT_BUF_INIT
;
if
(
git_buf_join3
(
&
path
,
'/'
,
git_repository_workdir
(
repo
),
name
,
DOT_GIT
)
<
0
)
'/'
,
git_repository_workdir
(
repo
),
name
,
DOT_GIT
)
<
0
)
return
-
1
;
if
(
git_path_exists
(
path
.
ptr
))
...
...
@@ -231,9 +224,15 @@ int git_submodule_lookup(
}
submodule_set_lookup_error
(
error
,
name
);
return
error
;
}
return
error
;
if
(
out
)
*
out
=
sm
;
else
git_submodule_free
(
sm
);
return
0
;
}
static
void
submodule_free_dup
(
void
*
sm
)
...
...
@@ -241,41 +240,221 @@ static void submodule_free_dup(void *sm)
git_submodule_free
(
sm
);
}
static
int
submodule_get_or_create
(
git_submodule
**
out
,
git_repository
*
repo
,
git_strmap
*
map
,
const
char
*
name
)
{
int
error
=
0
;
khiter_t
pos
;
git_submodule
*
sm
=
NULL
;
pos
=
git_strmap_lookup_index
(
map
,
name
);
if
(
git_strmap_valid_index
(
map
,
pos
))
{
sm
=
git_strmap_value_at
(
map
,
pos
);
goto
done
;
}
/* if the submodule doesn't exist yet in the map, create it */
if
((
error
=
submodule_alloc
(
&
sm
,
repo
,
name
))
<
0
)
return
error
;
pos
=
kh_put
(
str
,
map
,
sm
->
name
,
&
error
);
/* nobody can beat us to adding it */
assert
(
error
!=
0
);
if
(
error
<
0
)
{
git_submodule_free
(
sm
);
return
error
;
}
git_strmap_set_value_at
(
map
,
pos
,
sm
);
done:
GIT_REFCOUNT_INC
(
sm
);
*
out
=
sm
;
return
0
;
}
static
int
submodules_from_index
(
git_strmap
*
map
,
git_index
*
idx
)
{
int
error
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
if
((
error
=
git_iterator_for_index
(
&
i
,
idx
,
0
,
NULL
,
NULL
))
<
0
)
return
error
;
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
khiter_t
pos
=
git_strmap_lookup_index
(
map
,
entry
->
path
);
git_submodule
*
sm
;
if
(
git_strmap_valid_index
(
map
,
pos
))
{
sm
=
git_strmap_value_at
(
map
,
pos
);
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_or_create
(
&
sm
,
git_index_owner
(
idx
),
map
,
entry
->
path
))
{
submodule_update_from_index_entry
(
sm
,
entry
);
git_submodule_free
(
sm
);
}
}
}
if
(
error
==
GIT_ITEROVER
)
error
=
0
;
git_iterator_free
(
i
);
return
error
;
}
static
int
submodules_from_head
(
git_strmap
*
map
,
git_tree
*
head
)
{
int
error
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
if
((
error
=
git_iterator_for_tree
(
&
i
,
head
,
0
,
NULL
,
NULL
))
<
0
)
return
error
;
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
khiter_t
pos
=
git_strmap_lookup_index
(
map
,
entry
->
path
);
git_submodule
*
sm
;
if
(
git_strmap_valid_index
(
map
,
pos
))
{
sm
=
git_strmap_value_at
(
map
,
pos
);
if
(
S_ISGITLINK
(
entry
->
mode
))
submodule_update_from_head_data
(
sm
,
entry
->
mode
,
&
entry
->
id
);
else
sm
->
flags
|=
GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
}
else
if
(
S_ISGITLINK
(
entry
->
mode
))
{
if
(
!
submodule_get_or_create
(
&
sm
,
git_tree_owner
(
head
),
map
,
entry
->
path
))
{
submodule_update_from_head_data
(
sm
,
entry
->
mode
,
&
entry
->
id
);
git_submodule_free
(
sm
);
}
}
}
if
(
error
==
GIT_ITEROVER
)
error
=
0
;
git_iterator_free
(
i
);
return
error
;
}
/* If have_sm is true, sm is populated, otherwise map an repo are. */
typedef
struct
{
int
have_sm
;
git_submodule
*
sm
;
git_strmap
*
map
;
git_repository
*
repo
;
}
lfc_data
;
static
int
all_submodules
(
git_repository
*
repo
,
git_strmap
*
map
)
{
int
error
=
0
;
git_index
*
idx
=
NULL
;
git_tree
*
head
=
NULL
;
const
char
*
wd
=
NULL
;
git_buf
path
=
GIT_BUF_INIT
;
git_submodule
*
sm
;
git_config_backend
*
mods
=
NULL
;
uint32_t
mask
;
assert
(
repo
&&
map
);
/* get sources that we will need to check */
if
(
git_repository_index
(
&
idx
,
repo
)
<
0
)
giterr_clear
();
if
(
git_repository_head_tree
(
&
head
,
repo
)
<
0
)
giterr_clear
();
wd
=
git_repository_workdir
(
repo
);
if
(
wd
&&
(
error
=
git_buf_joinpath
(
&
path
,
wd
,
GIT_MODULES_FILE
))
<
0
)
goto
cleanup
;
/* clear submodule flags that are to be refreshed */
mask
=
0
;
mask
|=
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS__INDEX_FLAGS
|
GIT_SUBMODULE_STATUS__INDEX_OID_VALID
|
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
mask
|=
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
mask
|=
GIT_SUBMODULE_STATUS_IN_CONFIG
;
if
(
mask
!=
0
)
mask
|=
GIT_SUBMODULE_STATUS_IN_WD
|
GIT_SUBMODULE_STATUS__WD_SCANNED
|
GIT_SUBMODULE_STATUS__WD_FLAGS
|
GIT_SUBMODULE_STATUS__WD_OID_VALID
;
/* add back submodule information from index */
if
(
idx
)
{
if
((
error
=
submodules_from_index
(
map
,
idx
))
<
0
)
goto
cleanup
;
}
/* add submodule information from HEAD */
if
(
head
)
{
if
((
error
=
submodules_from_head
(
map
,
head
))
<
0
)
goto
cleanup
;
}
/* add submodule information from .gitmodules */
if
(
wd
)
{
lfc_data
data
=
{
0
};
data
.
map
=
map
;
data
.
repo
=
repo
;
if
((
mods
=
open_gitmodules
(
repo
,
false
))
!=
NULL
&&
(
error
=
git_config_file_foreach
(
mods
,
submodule_load_from_config
,
&
data
))
<
0
)
goto
cleanup
;
}
/* shallow scan submodules in work tree as needed */
if
(
wd
&&
mask
!=
0
)
{
git_strmap_foreach_value
(
map
,
sm
,
{
submodule_load_from_wd_lite
(
sm
);
});
}
cleanup:
git_config_file_free
(
mods
);
/* TODO: if we got an error, mark submodule config as invalid? */
git_index_free
(
idx
);
git_tree_free
(
head
);
git_buf_free
(
&
path
);
return
error
;
}
int
git_submodule_foreach
(
git_repository
*
repo
,
int
(
*
callback
)(
git_submodule
*
sm
,
const
char
*
name
,
void
*
payload
),
void
*
payload
)
{
git_vector
snapshot
=
GIT_VECTOR_INIT
;
git_strmap
*
submodules
;
git_submodule
*
sm
;
int
error
;
size_t
i
;
git_submodule
*
sm
;
git_submodule_cache
*
cache
;
git_vector
snapshot
=
GIT_VECTOR_INIT
;
assert
(
repo
&&
callback
);
if
((
error
=
submodule_cache_init
(
repo
,
CACHE_REFRESH
))
<
0
)
if
((
error
=
git_strmap_alloc
(
&
submodules
))
<
0
)
return
error
;
cache
=
repo
->
_submodules
;
if
(
git_mutex_lock
(
&
cache
->
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Unable to acquire lock on submodule cache"
);
return
-
1
;
}
if
((
error
=
all_submodules
(
repo
,
submodules
))
<
0
)
goto
done
;
if
(
!
(
error
=
git_vector_init
(
&
snapshot
,
kh_size
(
cache
->
submodules
),
submodule_cmp
)))
{
&
snapshot
,
kh_size
(
submodules
),
submodule_cmp
)))
{
git_strmap_foreach_value
(
cache
->
submodules
,
sm
,
{
git_strmap_foreach_value
(
submodules
,
sm
,
{
if
((
error
=
git_vector_insert
(
&
snapshot
,
sm
))
<
0
)
break
;
GIT_REFCOUNT_INC
(
sm
);
});
}
git_mutex_unlock
(
&
cache
->
lock
);
if
(
error
<
0
)
goto
done
;
...
...
@@ -293,17 +472,12 @@ done:
git_submodule_free
(
sm
);
git_vector_free
(
&
snapshot
);
return
error
;
}
void
git_submodule_cache_free
(
git_repository
*
repo
)
{
git_submodule_cache
*
cache
;
assert
(
repo
);
git_strmap_foreach_value
(
submodules
,
sm
,
{
git_submodule_free
(
sm
);
});
git_strmap_free
(
submodules
);
if
((
cache
=
git__swap
(
repo
->
_submodules
,
NULL
))
!=
NULL
)
submodule_cache_free
(
cache
);
return
error
;
}
static
int
submodule_repo_init
(
...
...
@@ -394,7 +568,7 @@ int git_submodule_add_setup(
/* update .gitmodules */
if
(
!
(
mods
=
open_gitmodules
(
repo
->
_submodules
,
GITMODULES_CREATE
)))
{
if
(
!
(
mods
=
open_gitmodules
(
repo
,
GITMODULES_CREATE
)))
{
giterr_set
(
GITERR_SUBMODULE
,
"Adding submodules to a bare repository is not supported"
);
return
-
1
;
...
...
@@ -430,19 +604,10 @@ int git_submodule_add_setup(
goto
cleanup
;
}
/* add submodule to hash and "reload" it */
if
(
git_mutex_lock
(
&
repo
->
_submodules
->
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Unable to acquire lock on submodule cache"
);
error
=
-
1
;
if
((
error
=
git_submodule_lookup
(
&
sm
,
repo
,
path
))
<
0
)
goto
cleanup
;
}
if
(
!
(
error
=
submodule_get
(
&
sm
,
repo
->
_submodules
,
path
,
NULL
))
&&
!
(
error
=
git_submodule_reload
(
sm
,
false
)))
error
=
git_submodule_init
(
sm
,
false
);
git_mutex_unlock
(
&
repo
->
_submodules
->
lock
);
error
=
git_submodule_init
(
sm
,
false
);
cleanup:
if
(
error
&&
sm
)
{
...
...
@@ -572,15 +737,6 @@ 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
;
...
...
@@ -590,132 +746,90 @@ const char *git_submodule_update_to_str(git_submodule_update_t update)
return
NULL
;
}
const
char
*
git_submodule_recurse_to_str
(
git_submodule_recurse_t
recurs
e
)
git_repository
*
git_submodule_owner
(
git_submodule
*
submodul
e
)
{
int
i
;
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
_sm_recurse_map
);
++
i
)
if
(
_sm_recurse_map
[
i
].
map_value
==
recurse
)
return
_sm_recurse_map
[
i
].
str_match
;
return
NULL
;
assert
(
submodule
);
return
submodule
->
repo
;
}
int
git_submodule_sav
e
(
git_submodule
*
submodule
)
const
char
*
git_submodule_nam
e
(
git_submodule
*
submodule
)
{
int
error
=
0
;
git_config_backend
*
mods
;
git_buf
key
=
GIT_BUF_INIT
;
const
char
*
val
;
assert
(
submodule
);
return
submodule
->
name
;
}
mods
=
open_gitmodules
(
submodule
->
repo
->
_submodules
,
GITMODULES_CREATE
);
if
(
!
mods
)
{
giterr_set
(
GITERR_SUBMODULE
,
"Adding submodules to a bare repository is not supported"
);
return
-
1
;
}
const
char
*
git_submodule_path
(
git_submodule
*
submodule
)
{
assert
(
submodule
);
return
submodule
->
path
;
}
if
((
error
=
git_buf_printf
(
&
key
,
"submodule.%s."
,
submodule
->
name
))
<
0
)
goto
cleanup
;
const
char
*
git_submodule_url
(
git_submodule
*
submodule
)
{
assert
(
submodule
);
return
submodule
->
url
;
}
/* save values for path, url, update, ignore, fetchRecurseSubmodules */
int
git_submodule_resolve_url
(
git_buf
*
out
,
git_repository
*
repo
,
const
char
*
url
)
{
int
error
=
0
;
if
((
error
=
submodule_config_key_trunc_puts
(
&
key
,
"path"
))
<
0
||
(
error
=
git_config_file_set_string
(
mods
,
key
.
ptr
,
submodule
->
path
))
<
0
)
goto
cleanup
;
assert
(
out
&&
repo
&&
url
);
if
((
error
=
submodule_config_key_trunc_puts
(
&
key
,
"url"
))
<
0
||
(
error
=
git_config_file_set_string
(
mods
,
key
.
ptr
,
submodule
->
url
))
<
0
)
goto
cleanup
;
git_buf_sanitize
(
out
);
if
((
error
=
submodule_config_key_trunc_puts
(
&
key
,
"branch"
))
<
0
)
goto
cleanup
;
if
(
submodule
->
branch
==
NULL
)
error
=
git_config_file_delete
(
mods
,
key
.
ptr
);
else
error
=
git_config_file_set_string
(
mods
,
key
.
ptr
,
submodule
->
branch
);
if
(
error
==
GIT_ENOTFOUND
)
{
error
=
0
;
giterr_clear
();
if
(
git_path_is_relative
(
url
))
{
if
(
!
(
error
=
get_url_base
(
out
,
repo
)))
error
=
git_path_apply_relative
(
out
,
url
);
}
else
if
(
strchr
(
url
,
':'
)
!=
NULL
||
url
[
0
]
==
'/'
)
{
error
=
git_buf_sets
(
out
,
url
);
}
else
{
giterr_set
(
GITERR_SUBMODULE
,
"Invalid format for submodule URL"
);
error
=
-
1
;
}
if
(
error
<
0
)
goto
cleanup
;
if
(
!
(
error
=
submodule_config_key_trunc_puts
(
&
key
,
"update"
))
&&
(
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"
))
&&
(
val
=
git_submodule_ignore_to_str
(
submodule
->
ignore
))
!=
NULL
)
error
=
git_config_file_set_string
(
mods
,
key
.
ptr
,
val
);
if
(
error
<
0
)
goto
cleanup
;
if
(
!
(
error
=
submodule_config_key_trunc_puts
(
&
key
,
"fetchRecurseSubmodules"
))
&&
(
val
=
git_submodule_recurse_to_str
(
submodule
->
fetch_recurse
))
!=
NULL
)
error
=
git_config_file_set_string
(
mods
,
key
.
ptr
,
val
);
if
(
error
<
0
)
goto
cleanup
;
/* update internal defaults */
submodule
->
ignore_default
=
submodule
->
ignore
;
submodule
->
update_default
=
submodule
->
update
;
submodule
->
fetch_recurse_default
=
submodule
->
fetch_recurse
;
submodule
->
flags
|=
GIT_SUBMODULE_STATUS_IN_CONFIG
;
cleanup:
git_config_file_free
(
mods
);
git_buf_free
(
&
key
);
return
error
;
}
git_repository
*
git_submodule_owner
(
git_submodule
*
submodule
)
static
int
write_var
(
git_repository
*
repo
,
const
char
*
name
,
const
char
*
var
,
const
char
*
val
)
{
assert
(
submodule
)
;
return
submodule
->
repo
;
}
git_buf
key
=
GIT_BUF_INIT
;
git_config_backend
*
mods
;
int
error
;
const
char
*
git_submodule_name
(
git_submodule
*
submodule
)
{
assert
(
submodule
);
return
submodule
->
name
;
}
mods
=
open_gitmodules
(
repo
,
GITMODULES_CREATE
);
if
(
!
mods
)
return
-
1
;
const
char
*
git_submodule_path
(
git_submodule
*
submodule
)
{
assert
(
submodule
);
return
submodule
->
path
;
}
if
((
error
=
git_buf_printf
(
&
key
,
"submodule.%s.%s"
,
name
,
var
))
<
0
)
goto
cleanup
;
if
(
val
)
error
=
git_config_file_set_string
(
mods
,
key
.
ptr
,
val
);
else
error
=
git_config_file_delete
(
mods
,
key
.
ptr
);
git_buf_free
(
&
key
);
const
char
*
git_submodule_url
(
git_submodule
*
submodule
)
{
assert
(
submodule
);
return
submodule
->
url
;
cleanup:
git_config_file_free
(
mods
);
return
error
;
}
int
git_submodule_resolve_url
(
git_buf
*
out
,
git_repository
*
repo
,
const
char
*
ur
l
)
static
int
write_mapped_var
(
git_repository
*
repo
,
const
char
*
name
,
git_cvar_map
*
maps
,
size_t
nmaps
,
const
char
*
var
,
int
iva
l
)
{
int
error
=
0
;
assert
(
out
&&
repo
&&
url
);
git_buf_sanitize
(
out
);
git_cvar_t
type
;
const
char
*
val
;
if
(
git_path_is_relative
(
url
))
{
if
(
!
(
error
=
get_url_base
(
out
,
repo
)))
error
=
git_path_apply_relative
(
out
,
url
);
}
else
if
(
strchr
(
url
,
':'
)
!=
NULL
||
url
[
0
]
==
'/'
)
{
error
=
git_buf_sets
(
out
,
url
);
}
else
{
giterr_set
(
GITERR_SUBMODULE
,
"Invalid format for submodule URL"
);
error
=
-
1
;
if
(
git_config_lookup_map_enum
(
&
type
,
&
val
,
maps
,
nmaps
,
ival
)
<
0
)
{
giterr_set
(
GITERR_SUBMODULE
,
"invalid value for %s"
,
var
);
return
-
1
;
}
return
error
;
if
(
type
==
GIT_CVAR_TRUE
)
val
=
"true"
;
return
write_var
(
repo
,
name
,
var
,
val
);
}
const
char
*
git_submodule_branch
(
git_submodule
*
submodule
)
...
...
@@ -724,31 +838,19 @@ const char *git_submodule_branch(git_submodule *submodule)
return
submodule
->
branch
;
}
int
git_submodule_set_branch
(
git_
submodule
*
submodul
e
,
const
char
*
branch
)
int
git_submodule_set_branch
(
git_
repository
*
repo
,
const
char
*
nam
e
,
const
char
*
branch
)
{
assert
(
submodule
);
git__free
(
submodule
->
branch
);
submodule
->
branch
=
NULL
;
if
(
branch
!=
NULL
)
{
submodule
->
branch
=
git__strdup
(
branch
);
GITERR_CHECK_ALLOC
(
submodule
->
branch
);
}
assert
(
repo
&&
name
);
return
0
;
return
write_var
(
repo
,
name
,
"branch"
,
branch
)
;
}
int
git_submodule_set_url
(
git_
submodule
*
submodul
e
,
const
char
*
url
)
int
git_submodule_set_url
(
git_
repository
*
repo
,
const
char
*
nam
e
,
const
char
*
url
)
{
assert
(
submodule
&&
url
);
git__free
(
submodule
->
url
);
submodule
->
url
=
git__strdup
(
url
);
GITERR_CHECK_ALLOC
(
submodule
->
url
);
assert
(
repo
&&
name
&&
url
);
return
0
;
return
write_var
(
repo
,
name
,
"url"
,
url
)
;
}
const
git_oid
*
git_submodule_index_id
(
git_submodule
*
submodule
)
...
...
@@ -799,19 +901,11 @@ git_submodule_ignore_t git_submodule_ignore(git_submodule *submodule)
GIT_SUBMODULE_IGNORE_NONE
:
submodule
->
ignore
;
}
git_submodule_ignore_t
git_submodule_set_ignore
(
git_submodule
*
submodule
,
git_submodule_ignore_t
ignore
)
int
git_submodule_set_ignore
(
git_repository
*
repo
,
const
char
*
name
,
git_submodule_ignore_t
ignore
)
{
git_submodule_ignore_t
old
;
assert
(
submodule
);
if
(
ignore
==
GIT_SUBMODULE_IGNORE_RESET
)
ignore
=
submodule
->
ignore_default
;
assert
(
repo
&&
name
);
old
=
submodule
->
ignore
;
submodule
->
ignore
=
ignore
;
return
old
;
return
write_mapped_var
(
repo
,
name
,
_sm_ignore_map
,
ARRAY_SIZE
(
_sm_ignore_map
),
"ignore"
,
ignore
);
}
git_submodule_update_t
git_submodule_update_strategy
(
git_submodule
*
submodule
)
...
...
@@ -821,19 +915,11 @@ git_submodule_update_t git_submodule_update_strategy(git_submodule *submodule)
GIT_SUBMODULE_UPDATE_CHECKOUT
:
submodule
->
update
;
}
git_submodule_update_t
git_submodule_set_update
(
git_submodule
*
submodule
,
git_submodule_update_t
update
)
int
git_submodule_set_update
(
git_repository
*
repo
,
const
char
*
name
,
git_submodule_update_t
update
)
{
git_submodule_update_t
old
;
assert
(
submodule
);
if
(
update
==
GIT_SUBMODULE_UPDATE_RESET
)
update
=
submodule
->
update_default
;
assert
(
repo
&&
name
);
old
=
submodule
->
update
;
submodule
->
update
=
update
;
return
old
;
return
write_mapped_var
(
repo
,
name
,
_sm_update_map
,
ARRAY_SIZE
(
_sm_update_map
),
"update"
,
update
);
}
git_submodule_recurse_t
git_submodule_fetch_recurse_submodules
(
...
...
@@ -843,20 +929,11 @@ git_submodule_recurse_t git_submodule_fetch_recurse_submodules(
return
submodule
->
fetch_recurse
;
}
git_submodule_recurse_t
git_submodule_set_fetch_recurse_submodules
(
git_submodule
*
submodule
,
git_submodule_recurse_t
fetch_recurse_submodules
)
int
git_submodule_set_fetch_recurse_submodules
(
git_repository
*
repo
,
const
char
*
name
,
git_submodule_recurse_t
recurse
)
{
git_submodule_recurse_t
old
;
assert
(
submodule
);
if
(
fetch_recurse_submodules
==
GIT_SUBMODULE_RECURSE_RESET
)
fetch_recurse_submodules
=
submodule
->
fetch_recurse_default
;
assert
(
repo
&&
name
);
old
=
submodule
->
fetch_recurse
;
submodule
->
fetch_recurse
=
fetch_recurse_submodules
;
return
old
;
return
write_mapped_var
(
repo
,
name
,
_sm_recurse_map
,
ARRAY_SIZE
(
_sm_recurse_map
),
"fetchRecurseSubmodules"
,
recurse
);
}
static
int
submodule_repo_create
(
...
...
@@ -953,7 +1030,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
memcpy
(
&
clone_options
.
fetch_opts
,
&
update_options
.
fetch_opts
,
sizeof
(
git_fetch_options
));
/* Get the status of the submodule to determine if it is already initialized */
if
((
error
=
git_submodule_status
(
&
submodule_status
,
sm
))
<
0
)
if
((
error
=
git_submodule_status
(
&
submodule_status
,
sm
->
repo
,
sm
->
name
,
GIT_SUBMODULE_IGNORE_FALLBACK
))
<
0
)
goto
done
;
/*
...
...
@@ -1197,11 +1274,6 @@ 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
,
int
force
)
{
return
submodule_cache_init
(
repo
,
force
?
CACHE_FLUSH
:
CACHE_REFRESH
);
}
static
void
submodule_update_from_index_entry
(
git_submodule
*
sm
,
const
git_index_entry
*
ie
)
{
...
...
@@ -1280,14 +1352,12 @@ int git_submodule_reload(git_submodule *sm, int force)
{
int
error
=
0
;
git_config_backend
*
mods
;
git_submodule_cache
*
cache
;
lfc_data
data
=
{
0
}
;
GIT_UNUSED
(
force
);
assert
(
sm
);
cache
=
sm
->
repo
->
_submodules
;
/* refresh index data */
if
((
error
=
submodule_update_index
(
sm
))
<
0
)
return
error
;
...
...
@@ -1301,7 +1371,7 @@ int git_submodule_reload(git_submodule *sm, int force)
return
error
;
/* refresh config data */
mods
=
open_gitmodules
(
cache
,
GITMODULES_EXISTING
);
mods
=
open_gitmodules
(
sm
->
repo
,
GITMODULES_EXISTING
);
if
(
mods
!=
NULL
)
{
git_buf
path
=
GIT_BUF_INIT
;
...
...
@@ -1309,11 +1379,14 @@ int git_submodule_reload(git_submodule *sm, int force)
git_buf_text_puts_escape_regex
(
&
path
,
sm
->
name
);
git_buf_puts
(
&
path
,
".*"
);
if
(
git_buf_oom
(
&
path
))
if
(
git_buf_oom
(
&
path
))
{
error
=
-
1
;
else
}
else
{
data
.
have_sm
=
1
;
data
.
sm
=
sm
;
error
=
git_config_file_foreach_match
(
mods
,
path
.
ptr
,
submodule_load_from_config
,
cache
);
mods
,
path
.
ptr
,
submodule_load_from_config
,
&
data
);
}
git_buf_free
(
&
path
);
git_config_file_free
(
mods
);
...
...
@@ -1352,7 +1425,7 @@ int git_submodule__status(
unsigned
int
status
;
git_repository
*
smrepo
=
NULL
;
if
(
ign
<
GIT_SUBMODULE_IGNORE_NONE
)
if
(
ign
==
GIT_SUBMODULE_IGNORE_FALLBACK
)
ign
=
sm
->
ignore
;
/* only return location info if ignore == all */
...
...
@@ -1401,11 +1474,20 @@ int git_submodule__status(
return
0
;
}
int
git_submodule_status
(
unsigned
int
*
status
,
git_
submodule
*
sm
)
int
git_submodule_status
(
unsigned
int
*
status
,
git_
repository
*
repo
,
const
char
*
name
,
git_submodule_ignore_t
ignore
)
{
assert
(
status
&&
sm
);
git_submodule
*
sm
;
int
error
;
assert
(
status
&&
repo
&&
name
);
if
((
error
=
git_submodule_lookup
(
&
sm
,
repo
,
name
))
<
0
)
return
error
;
error
=
git_submodule__status
(
status
,
NULL
,
NULL
,
NULL
,
sm
,
ignore
);
git_submodule_free
(
sm
);
return
git_submodule__status
(
status
,
NULL
,
NULL
,
NULL
,
sm
,
0
)
;
return
error
;
}
int
git_submodule_location
(
unsigned
int
*
location
,
git_submodule
*
sm
)
...
...
@@ -1422,7 +1504,7 @@ int git_submodule_location(unsigned int *location, git_submodule *sm)
*/
static
int
submodule_alloc
(
git_submodule
**
out
,
git_
submodule_cache
*
cache
,
const
char
*
name
)
git_submodule
**
out
,
git_
repository
*
repo
,
const
char
*
name
)
{
size_t
namelen
;
git_submodule
*
sm
;
...
...
@@ -1445,56 +1527,20 @@ static int submodule_alloc(
sm
->
ignore
=
sm
->
ignore_default
=
GIT_SUBMODULE_IGNORE_NONE
;
sm
->
update
=
sm
->
update_default
=
GIT_SUBMODULE_UPDATE_CHECKOUT
;
sm
->
fetch_recurse
=
sm
->
fetch_recurse_default
=
GIT_SUBMODULE_RECURSE_NO
;
sm
->
repo
=
cache
->
repo
;
sm
->
repo
=
repo
;
sm
->
branch
=
NULL
;
*
out
=
sm
;
return
0
;
}
static
void
submodule_cache_remove_item
(
git_submodule_cache
*
cache
,
git_submodule
*
item
,
bool
free_after_remove
)
{
git_strmap
*
map
;
const
char
*
name
,
*
alt
;
if
(
!
cache
||
!
(
map
=
cache
->
submodules
)
||
!
item
)
return
;
name
=
item
->
name
;
alt
=
(
item
->
path
!=
item
->
name
)
?
item
->
path
:
NULL
;
for
(;
name
;
name
=
alt
,
alt
=
NULL
)
{
khiter_t
pos
=
git_strmap_lookup_index
(
map
,
name
);
git_submodule
*
found
;
if
(
!
git_strmap_valid_index
(
map
,
pos
))
continue
;
found
=
git_strmap_value_at
(
map
,
pos
);
if
(
found
!=
item
)
continue
;
git_strmap_set_value_at
(
map
,
pos
,
NULL
);
git_strmap_delete_at
(
map
,
pos
);
if
(
free_after_remove
)
git_submodule_free
(
found
);
}
}
static
void
submodule_release
(
git_submodule
*
sm
)
{
if
(
!
sm
)
return
;
if
(
sm
->
repo
)
{
git_submodule_cache
*
cache
=
sm
->
repo
->
_submodules
;
sm
->
repo
=
NULL
;
submodule_cache_remove_item
(
cache
,
sm
,
false
);
}
if
(
sm
->
path
!=
sm
->
name
)
...
...
@@ -1513,54 +1559,6 @@ void git_submodule_free(git_submodule *sm)
GIT_REFCOUNT_DEC
(
sm
,
submodule_release
);
}
static
int
submodule_get
(
git_submodule
**
out
,
git_submodule_cache
*
cache
,
const
char
*
name
,
const
char
*
alternate
)
{
int
error
=
0
;
khiter_t
pos
;
git_submodule
*
sm
;
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
name
);
if
(
!
git_strmap_valid_index
(
cache
->
submodules
,
pos
)
&&
alternate
)
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
alternate
);
if
(
!
git_strmap_valid_index
(
cache
->
submodules
,
pos
))
{
if
((
error
=
submodule_alloc
(
&
sm
,
cache
,
name
))
<
0
)
return
error
;
/* insert value at name - if another thread beats us to it, then use
* their record and release our own.
*/
pos
=
kh_put
(
str
,
cache
->
submodules
,
sm
->
name
,
&
error
);
if
(
error
<
0
)
goto
done
;
else
if
(
error
==
0
)
{
git_submodule_free
(
sm
);
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
}
else
{
error
=
0
;
git_strmap_set_value_at
(
cache
->
submodules
,
pos
,
sm
);
}
}
else
{
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
}
done:
if
(
error
<
0
)
git_submodule_free
(
sm
);
else
if
(
out
)
{
GIT_REFCOUNT_INC
(
sm
);
*
out
=
sm
;
}
return
error
;
}
static
int
submodule_config_error
(
const
char
*
property
,
const
char
*
value
)
{
giterr_set
(
GITERR_INVALID
,
...
...
@@ -1613,12 +1611,12 @@ int git_submodule_parse_recurse(git_submodule_recurse_t *out, const char *value)
static
int
submodule_load_from_config
(
const
git_config_entry
*
entry
,
void
*
payload
)
{
git_submodule_cache
*
cache
=
payload
;
const
char
*
namestart
,
*
property
;
const
char
*
key
=
entry
->
name
,
*
value
=
entry
->
value
,
*
path
;
char
*
alternate
=
NULL
,
*
replaced
=
NULL
;
git_buf
name
=
GIT_BUF_INIT
;
git_submodule
*
sm
=
NULL
;
lfc_data
*
data
=
payload
;
git_submodule
*
sm
;
int
error
=
0
;
if
(
git__prefixcmp
(
key
,
"submodule."
)
!=
0
)
...
...
@@ -1633,10 +1631,29 @@ static int submodule_load_from_config(
property
++
;
path
=
!
strcasecmp
(
property
,
"path"
)
?
value
:
NULL
;
if
((
error
=
git_buf_set
(
&
name
,
namestart
,
property
-
namestart
-
1
))
<
0
||
(
error
=
submodule_get
(
&
sm
,
cache
,
name
.
ptr
,
path
))
<
0
)
if
((
error
=
git_buf_set
(
&
name
,
namestart
,
property
-
namestart
-
1
))
<
0
)
goto
done
;
if
(
data
->
have_sm
)
{
sm
=
data
->
sm
;
}
else
{
khiter_t
pos
;
git_strmap
*
map
=
data
->
map
;
pos
=
git_strmap_lookup_index
(
map
,
name
.
ptr
);
if
(
git_strmap_valid_index
(
map
,
pos
))
{
sm
=
git_strmap_value_at
(
map
,
pos
);
}
else
{
if
((
error
=
submodule_alloc
(
&
sm
,
data
->
repo
,
name
.
ptr
))
<
0
)
goto
done
;
git_strmap_insert
(
map
,
sm
->
name
,
sm
,
error
);
assert
(
error
!=
0
);
if
(
error
<
0
)
goto
done
;
error
=
0
;
}
}
sm
->
flags
|=
GIT_SUBMODULE_STATUS_IN_CONFIG
;
/* Only from config might we get differing names & paths. If so, then
...
...
@@ -1648,7 +1665,7 @@ static int submodule_load_from_config(
*/
if
(
strcmp
(
sm
->
name
,
name
.
ptr
)
!=
0
)
{
/* name changed */
if
(
!
strcmp
(
sm
->
path
,
name
.
ptr
))
{
/* already set as path */
if
(
sm
->
path
&&
!
strcmp
(
sm
->
path
,
name
.
ptr
))
{
/* already set as path */
replaced
=
sm
->
name
;
sm
->
name
=
sm
->
path
;
}
else
{
...
...
@@ -1674,7 +1691,6 @@ static int submodule_load_from_config(
/* Deregister under name being replaced */
if
(
replaced
)
{
git_strmap_delete
(
cache
->
submodules
,
replaced
);
git_submodule_free
(
sm
);
git__free
(
replaced
);
}
...
...
@@ -1682,7 +1698,6 @@ static int submodule_load_from_config(
/* Insert under alternate key */
if
(
alternate
)
{
void
*
old_sm
=
NULL
;
git_strmap_insert2
(
cache
->
submodules
,
alternate
,
sm
,
old_sm
,
error
);
if
(
error
<
0
)
goto
done
;
...
...
@@ -1742,7 +1757,6 @@ static int submodule_load_from_config(
/* ignore other unknown submodule properties */
done:
git_submodule_free
(
sm
);
/* offset refcount inc from submodule_get() */
git_buf_free
(
&
name
);
return
error
;
}
...
...
@@ -1764,86 +1778,11 @@ static int submodule_load_from_wd_lite(git_submodule *sm)
return
0
;
}
static
int
submodule_cache_refresh_from_index
(
git_submodule_cache
*
cache
,
git_index
*
idx
)
{
int
error
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
if
((
error
=
git_iterator_for_index
(
&
i
,
idx
,
0
,
NULL
,
NULL
))
<
0
)
return
error
;
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
khiter_t
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
entry
->
path
);
git_submodule
*
sm
;
if
(
git_strmap_valid_index
(
cache
->
submodules
,
pos
))
{
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
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
,
cache
,
entry
->
path
,
NULL
))
{
submodule_update_from_index_entry
(
sm
,
entry
);
git_submodule_free
(
sm
);
}
}
}
if
(
error
==
GIT_ITEROVER
)
error
=
0
;
git_iterator_free
(
i
);
return
error
;
}
static
int
submodule_cache_refresh_from_head
(
git_submodule_cache
*
cache
,
git_tree
*
head
)
{
int
error
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
if
((
error
=
git_iterator_for_tree
(
&
i
,
head
,
0
,
NULL
,
NULL
))
<
0
)
return
error
;
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
khiter_t
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
entry
->
path
);
git_submodule
*
sm
;
if
(
git_strmap_valid_index
(
cache
->
submodules
,
pos
))
{
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
if
(
S_ISGITLINK
(
entry
->
mode
))
submodule_update_from_head_data
(
sm
,
entry
->
mode
,
&
entry
->
id
);
else
sm
->
flags
|=
GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
}
else
if
(
S_ISGITLINK
(
entry
->
mode
))
{
if
(
!
submodule_get
(
&
sm
,
cache
,
entry
->
path
,
NULL
))
{
submodule_update_from_head_data
(
sm
,
entry
->
mode
,
&
entry
->
id
);
git_submodule_free
(
sm
);
}
}
}
if
(
error
==
GIT_ITEROVER
)
error
=
0
;
git_iterator_free
(
i
);
return
error
;
}
static
git_config_backend
*
open_gitmodules
(
git_
submodule_cache
*
cache
,
git_
repository
*
repo
,
int
okay_to_create
)
{
const
char
*
workdir
=
git_repository_workdir
(
cache
->
repo
);
const
char
*
workdir
=
git_repository_workdir
(
repo
);
git_buf
path
=
GIT_BUF_INIT
;
git_config_backend
*
mods
=
NULL
;
...
...
@@ -1868,198 +1807,6 @@ static git_config_backend *open_gitmodules(
return
mods
;
}
static
void
submodule_cache_free
(
git_submodule_cache
*
cache
)
{
git_submodule
*
sm
;
if
(
!
cache
)
return
;
git_strmap_foreach_value
(
cache
->
submodules
,
sm
,
{
sm
->
repo
=
NULL
;
/* disconnect from repo */
git_submodule_free
(
sm
);
});
git_strmap_free
(
cache
->
submodules
);
git_buf_free
(
&
cache
->
gitmodules_path
);
git_mutex_free
(
&
cache
->
lock
);
git__free
(
cache
);
}
static
int
submodule_cache_alloc
(
git_submodule_cache
**
out
,
git_repository
*
repo
)
{
git_submodule_cache
*
cache
=
git__calloc
(
1
,
sizeof
(
git_submodule_cache
));
GITERR_CHECK_ALLOC
(
cache
);
if
(
git_mutex_init
(
&
cache
->
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Unable to initialize submodule cache lock"
);
git__free
(
cache
);
return
-
1
;
}
if
(
git_strmap_alloc
(
&
cache
->
submodules
)
<
0
)
{
submodule_cache_free
(
cache
);
return
-
1
;
}
cache
->
repo
=
repo
;
git_buf_init
(
&
cache
->
gitmodules_path
,
0
);
*
out
=
cache
;
return
0
;
}
static
int
submodule_cache_refresh
(
git_submodule_cache
*
cache
,
int
refresh
)
{
int
error
=
0
,
update_index
,
update_head
,
update_gitmod
;
git_index
*
idx
=
NULL
;
git_tree
*
head
=
NULL
;
const
char
*
wd
=
NULL
;
git_buf
path
=
GIT_BUF_INIT
;
git_submodule
*
sm
;
git_config_backend
*
mods
=
NULL
;
uint32_t
mask
;
if
(
!
cache
||
!
cache
->
repo
||
!
refresh
)
return
0
;
if
(
git_mutex_lock
(
&
cache
->
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Unable to acquire lock on submodule cache"
);
return
-
1
;
}
/* get sources that we will need to check */
if
(
git_repository_index
(
&
idx
,
cache
->
repo
)
<
0
)
giterr_clear
();
if
(
git_repository_head_tree
(
&
head
,
cache
->
repo
)
<
0
)
giterr_clear
();
wd
=
git_repository_workdir
(
cache
->
repo
);
if
(
wd
&&
(
error
=
git_buf_joinpath
(
&
path
,
wd
,
GIT_MODULES_FILE
))
<
0
)
goto
cleanup
;
/* check for invalidation */
if
(
refresh
==
CACHE_FLUSH
)
update_index
=
update_head
=
update_gitmod
=
true
;
else
{
update_index
=
!
idx
||
git_index__changed_relative_to
(
idx
,
&
cache
->
index_checksum
);
update_head
=
!
head
||
!
git_oid_equal
(
&
cache
->
head_id
,
git_tree_id
(
head
));
update_gitmod
=
(
wd
!=
NULL
)
?
git_futils_filestamp_check
(
&
cache
->
gitmodules_stamp
,
path
.
ptr
)
:
(
cache
->
gitmodules_stamp
.
mtime
!=
0
);
}
/* clear submodule flags that are to be refreshed */
mask
=
0
;
if
(
!
idx
||
update_index
)
mask
|=
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS__INDEX_FLAGS
|
GIT_SUBMODULE_STATUS__INDEX_OID_VALID
|
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
;
if
(
!
head
||
update_head
)
mask
|=
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS__HEAD_OID_VALID
;
if
(
update_gitmod
)
mask
|=
GIT_SUBMODULE_STATUS_IN_CONFIG
;
if
(
mask
!=
0
)
mask
|=
GIT_SUBMODULE_STATUS_IN_WD
|
GIT_SUBMODULE_STATUS__WD_SCANNED
|
GIT_SUBMODULE_STATUS__WD_FLAGS
|
GIT_SUBMODULE_STATUS__WD_OID_VALID
;
else
goto
cleanup
;
/* nothing to do */
submodule_cache_clear_flags
(
cache
,
mask
);
/* add back submodule information from index */
if
(
idx
&&
update_index
)
{
if
((
error
=
submodule_cache_refresh_from_index
(
cache
,
idx
))
<
0
)
goto
cleanup
;
git_oid_cpy
(
&
cache
->
index_checksum
,
git_index_checksum
(
idx
));
}
/* add submodule information from HEAD */
if
(
head
&&
update_head
)
{
if
((
error
=
submodule_cache_refresh_from_head
(
cache
,
head
))
<
0
)
goto
cleanup
;
git_oid_cpy
(
&
cache
->
head_id
,
git_tree_id
(
head
));
}
/* add submodule information from .gitmodules */
if
(
wd
&&
update_gitmod
>
0
)
{
if
((
mods
=
open_gitmodules
(
cache
,
false
))
!=
NULL
&&
(
error
=
git_config_file_foreach
(
mods
,
submodule_load_from_config
,
cache
))
<
0
)
goto
cleanup
;
}
/* shallow scan submodules in work tree as needed */
if
(
wd
&&
mask
!=
0
)
{
git_strmap_foreach_value
(
cache
->
submodules
,
sm
,
{
submodule_load_from_wd_lite
(
sm
);
});
}
/* remove submodules that no longer exist */
git_strmap_foreach_value
(
cache
->
submodules
,
sm
,
{
/* purge unless in HEAD, index, or .gitmodules; no sm for wd only */
if
(
sm
!=
NULL
&&
!
(
sm
->
flags
&
(
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
)))
submodule_cache_remove_item
(
cache
,
sm
,
true
);
});
cleanup:
git_config_file_free
(
mods
);
/* TODO: if we got an error, mark submodule config as invalid? */
git_mutex_unlock
(
&
cache
->
lock
);
git_index_free
(
idx
);
git_tree_free
(
head
);
git_buf_free
(
&
path
);
return
error
;
}
static
int
submodule_cache_init
(
git_repository
*
repo
,
int
cache_refresh
)
{
int
error
=
0
;
git_submodule_cache
*
cache
=
NULL
;
/* if submodules already exist, just refresh as requested */
if
(
repo
->
_submodules
)
return
submodule_cache_refresh
(
repo
->
_submodules
,
cache_refresh
);
/* otherwise create a new cache, load it, and atomically swap it in */
if
(
!
(
error
=
submodule_cache_alloc
(
&
cache
,
repo
))
&&
!
(
error
=
submodule_cache_refresh
(
cache
,
CACHE_FLUSH
)))
cache
=
git__compare_and_swap
(
&
repo
->
_submodules
,
NULL
,
cache
);
/* might have raced with another thread to set cache, so free if needed */
if
(
cache
)
submodule_cache_free
(
cache
);
return
error
;
}
/* Lookup name of remote of the local tracking branch HEAD points to */
static
int
lookup_head_remote_key
(
git_buf
*
remote_name
,
git_repository
*
repo
)
{
...
...
src/submodule.h
View file @
daacf96d
...
...
@@ -99,23 +99,6 @@ struct git_submodule {
git_oid
wd_oid
;
};
/**
* The git_submodule_cache stores known submodules along with timestamps,
* etc. about when they were loaded
*/
typedef
struct
{
git_repository
*
repo
;
git_strmap
*
submodules
;
git_mutex
lock
;
/* cache invalidation data */
git_oid
head_id
;
git_oid
index_checksum
;
git_buf
gitmodules_path
;
git_futils_filestamp
gitmodules_stamp
;
git_futils_filestamp
config_stamp
;
}
git_submodule_cache
;
/* Force revalidation of submodule data cache (alloc as needed) */
extern
int
git_submodule_cache_refresh
(
git_repository
*
repo
);
...
...
@@ -137,9 +120,6 @@ enum {
#define GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(S) \
((S) & ~(0xFFFFFFFFu << 20))
/* Internal submodule check does not attempt to refresh cached data */
extern
bool
git_submodule__is_submodule
(
git_repository
*
repo
,
const
char
*
name
);
/* Internal lookup does not attempt to refresh cached data */
extern
int
git_submodule__lookup
(
git_submodule
**
out
,
git_repository
*
repo
,
const
char
*
path
);
...
...
@@ -163,8 +143,4 @@ extern int git_submodule_parse_ignore(
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
);
extern
const
char
*
git_submodule_recurse_to_str
(
git_submodule_recurse_t
);
#endif
tests/diff/submodules.c
View file @
daacf96d
...
...
@@ -273,13 +273,13 @@ void test_diff_submodules__invalid_cache(void)
/* 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
);
git_submodule_set_ignore
(
g_repo
,
git_submodule_name
(
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_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_UNTRACKED
);
git_submodule_set_ignore
(
g_repo
,
git_submodule_name
(
sm
)
,
GIT_SUBMODULE_IGNORE_UNTRACKED
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_unchanged
);
...
...
@@ -301,7 +301,7 @@ void test_diff_submodules__invalid_cache(void)
check_diff_patches
(
diff
,
expected_dirty
);
git_diff_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_DIRTY
);
git_submodule_set_ignore
(
g_repo
,
git_submodule_name
(
sm
)
,
GIT_SUBMODULE_IGNORE_DIRTY
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_unchanged
);
...
...
@@ -312,13 +312,13 @@ void test_diff_submodules__invalid_cache(void)
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
);
git_submodule_set_ignore
(
g_repo
,
git_submodule_name
(
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_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_DIRTY
);
git_submodule_set_ignore
(
g_repo
,
git_submodule_name
(
sm
)
,
GIT_SUBMODULE_IGNORE_DIRTY
);
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_unchanged
);
...
...
@@ -327,19 +327,19 @@ void test_diff_submodules__invalid_cache(void)
/* commit changed index of submodule */
cl_repo_commit_from_index
(
NULL
,
smrepo
,
NULL
,
1372350000
,
"Move it"
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_DIRTY
);
git_submodule_set_ignore
(
g_repo
,
git_submodule_name
(
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_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_ALL
);
git_submodule_set_ignore
(
g_repo
,
git_submodule_name
(
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_free
(
diff
);
git_submodule_set_ignore
(
sm
,
GIT_SUBMODULE_IGNORE_NONE
);
git_submodule_set_ignore
(
g_repo
,
git_submodule_name
(
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
);
...
...
tests/diff/tree.c
View file @
daacf96d
...
...
@@ -89,7 +89,7 @@ void test_diff_tree__0(void)
}
#define DIFF_OPTS(FLAGS, CTXT) \
{GIT_DIFF_OPTIONS_VERSION, (FLAGS), GIT_SUBMODULE_IGNORE_
DEFAULT
, \
{GIT_DIFF_OPTIONS_VERSION, (FLAGS), GIT_SUBMODULE_IGNORE_
FALLBACK
, \
{NULL,0}, NULL, NULL, (CTXT), 1}
void
test_diff_tree__options
(
void
)
...
...
tests/submodule/init.c
View file @
daacf96d
...
...
@@ -23,10 +23,10 @@ void test_submodule_init__absolute_url(void)
cl_assert
(
git_path_dirname_r
(
&
absolute_url
,
git_repository_workdir
(
g_repo
))
>
0
);
cl_git_pass
(
git_buf_joinpath
(
&
absolute_url
,
absolute_url
.
ptr
,
"testrepo.git"
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
/* write the absolute url to the .gitmodules file*/
cl_git_pass
(
git_submodule_set_url
(
sm
,
absolute_url
.
ptr
));
cl_git_pass
(
git_submodule_set_url
(
g_repo
,
"testrepo"
,
absolute_url
.
ptr
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
/* verify that the .gitmodules is set with an absolute path*/
cl_assert_equal_s
(
absolute_url
.
ptr
,
git_submodule_url
(
sm
));
...
...
tests/submodule/modify.c
View file @
daacf96d
...
...
@@ -41,17 +41,15 @@ void test_submodule_modify__init(void)
git_config_free
(
cfg
);
/* confirm no submodule data in config */
cl_git_pass
(
git_repository_config
(
&
cfg
,
g_repo
));
cl_git_fail
(
git_config_get_string
(
&
str
,
cfg
,
"submodule.sm_unchanged.url"
));
cl_git_fail
(
git_config_get_string
(
&
str
,
cfg
,
"submodule.sm_changed_head.url"
));
cl_git_fail
(
git_config_get_string
(
&
str
,
cfg
,
"submodule.sm_added_and_uncommited.url"
));
cl_git_pass
(
git_repository_config
_snapshot
(
&
cfg
,
g_repo
));
cl_git_fail
_with
(
GIT_ENOTFOUND
,
git_config_get_string
(
&
str
,
cfg
,
"submodule.sm_unchanged.url"
));
cl_git_fail
_with
(
GIT_ENOTFOUND
,
git_config_get_string
(
&
str
,
cfg
,
"submodule.sm_changed_head.url"
));
cl_git_fail
_with
(
GIT_ENOTFOUND
,
git_config_get_string
(
&
str
,
cfg
,
"submodule.sm_added_and_uncommited.url"
));
git_config_free
(
cfg
);
/* call init and see that settings are copied */
cl_git_pass
(
git_submodule_foreach
(
g_repo
,
init_one_submodule
,
NULL
));
git_submodule_reload_all
(
g_repo
,
1
);
/* confirm submodule data in config */
cl_git_pass
(
git_repository_config_snapshot
(
&
cfg
,
g_repo
));
cl_git_pass
(
git_config_get_string
(
&
str
,
cfg
,
"submodule.sm_unchanged.url"
));
...
...
@@ -130,132 +128,85 @@ void test_submodule_modify__sync(void)
git_submodule_free
(
sm3
);
}
void
test_submodule_modify__edit_and_save
(
void
)
void
assert_ignore_change
(
git_submodule_ignore_t
ignore
)
{
git_submodule
*
sm1
,
*
sm2
;
char
*
old_url
,
*
old_branch
;
git_submodule_ignore_t
old_ignore
;
git_submodule_update_t
old_update
;
git_repository
*
r2
;
git_submodule_recurse_t
old_fetchrecurse
;
cl_git_pass
(
git_submodule_lookup
(
&
sm1
,
g_repo
,
"sm_changed_head"
));
old_url
=
git__strdup
(
git_submodule_url
(
sm1
));
old_branch
=
NULL
;
/* modify properties of submodule */
cl_git_pass
(
git_submodule_set_url
(
sm1
,
SM_LIBGIT2_URL
));
cl_git_pass
(
git_submodule_set_branch
(
sm1
,
SM_LIBGIT2_BRANCH
));
old_ignore
=
git_submodule_set_ignore
(
sm1
,
GIT_SUBMODULE_IGNORE_UNTRACKED
);
old_update
=
git_submodule_set_update
(
sm1
,
GIT_SUBMODULE_UPDATE_REBASE
);
old_fetchrecurse
=
git_submodule_set_fetch_recurse_submodules
(
sm1
,
GIT_SUBMODULE_RECURSE_YES
);
cl_assert_equal_s
(
SM_LIBGIT2_URL
,
git_submodule_url
(
sm1
));
cl_assert_equal_s
(
SM_LIBGIT2_BRANCH
,
git_submodule_branch
(
sm1
));
cl_assert_equal_i
(
GIT_SUBMODULE_IGNORE_UNTRACKED
,
git_submodule_ignore
(
sm1
));
cl_assert_equal_i
(
GIT_SUBMODULE_UPDATE_REBASE
,
git_submodule_update_strategy
(
sm1
));
cl_assert_equal_i
(
GIT_SUBMODULE_RECURSE_YES
,
git_submodule_fetch_recurse_submodules
(
sm1
));
/* revert without saving (and confirm setters return old value) */
cl_git_pass
(
git_submodule_set_url
(
sm1
,
old_url
));
cl_git_pass
(
git_submodule_set_branch
(
sm1
,
old_branch
));
cl_assert_equal_i
(
GIT_SUBMODULE_IGNORE_UNTRACKED
,
git_submodule_set_ignore
(
sm1
,
GIT_SUBMODULE_IGNORE_RESET
));
cl_assert_equal_i
(
GIT_SUBMODULE_UPDATE_REBASE
,
git_submodule_set_update
(
sm1
,
GIT_SUBMODULE_UPDATE_RESET
));
cl_assert_equal_i
(
GIT_SUBMODULE_RECURSE_YES
,
git_submodule_set_fetch_recurse_submodules
(
sm1
,
GIT_SUBMODULE_RECURSE_RESET
));
/* check that revert was successful */
cl_assert_equal_s
(
old_url
,
git_submodule_url
(
sm1
));
cl_assert_equal_s
(
old_branch
,
git_submodule_branch
(
sm1
));
cl_assert_equal_i
((
int
)
old_ignore
,
(
int
)
git_submodule_ignore
(
sm1
));
cl_assert_equal_i
((
int
)
old_update
,
(
int
)
git_submodule_update_strategy
(
sm1
));
cl_assert_equal_i
(
old_fetchrecurse
,
git_submodule_fetch_recurse_submodules
(
sm1
));
/* modify properties of submodule (again) */
cl_git_pass
(
git_submodule_set_url
(
sm1
,
SM_LIBGIT2_URL
));
cl_git_pass
(
git_submodule_set_branch
(
sm1
,
SM_LIBGIT2_BRANCH
));
git_submodule_set_ignore
(
sm1
,
GIT_SUBMODULE_IGNORE_UNTRACKED
);
git_submodule_set_update
(
sm1
,
GIT_SUBMODULE_UPDATE_REBASE
);
git_submodule_set_fetch_recurse_submodules
(
sm1
,
GIT_SUBMODULE_RECURSE_YES
);
/* call save */
cl_git_pass
(
git_submodule_save
(
sm1
));
/* attempt to "revert" values */
git_submodule_set_ignore
(
sm1
,
GIT_SUBMODULE_IGNORE_RESET
);
git_submodule_set_update
(
sm1
,
GIT_SUBMODULE_UPDATE_RESET
);
/* but ignore and update should NOT revert because the RESET
* should now be the newly saved value...
*/
cl_assert_equal_i
(
(
int
)
GIT_SUBMODULE_IGNORE_UNTRACKED
,
(
int
)
git_submodule_ignore
(
sm1
));
cl_assert_equal_i
(
(
int
)
GIT_SUBMODULE_UPDATE_REBASE
,
(
int
)
git_submodule_update_strategy
(
sm1
));
cl_assert_equal_i
(
GIT_SUBMODULE_RECURSE_YES
,
git_submodule_fetch_recurse_submodules
(
sm1
));
/* call reload and check that the new values are loaded */
cl_git_pass
(
git_submodule_reload
(
sm1
,
0
));
cl_assert_equal_s
(
SM_LIBGIT2_URL
,
git_submodule_url
(
sm1
));
cl_assert_equal_s
(
SM_LIBGIT2_BRANCH
,
git_submodule_branch
(
sm1
));
cl_assert_equal_i
(
(
int
)
GIT_SUBMODULE_IGNORE_UNTRACKED
,
(
int
)
git_submodule_ignore
(
sm1
));
cl_assert_equal_i
(
(
int
)
GIT_SUBMODULE_UPDATE_REBASE
,
(
int
)
git_submodule_update_strategy
(
sm1
));
cl_assert_equal_i
(
GIT_SUBMODULE_RECURSE_YES
,
git_submodule_fetch_recurse_submodules
(
sm1
));
/* unset branch again and verify that the property is deleted in config */
cl_git_pass
(
git_submodule_set_branch
(
sm1
,
NULL
));
cl_git_pass
(
git_submodule_save
(
sm1
));
cl_git_pass
(
git_submodule_reload
(
sm1
,
0
));
cl_assert_equal_s
(
NULL
,
git_submodule_branch
(
sm1
));
/* open a second copy of the repo and compare submodule */
cl_git_pass
(
git_repository_open
(
&
r2
,
"submod2"
));
cl_git_pass
(
git_submodule_lookup
(
&
sm2
,
r2
,
"sm_changed_head"
));
cl_assert_equal_s
(
SM_LIBGIT2_URL
,
git_submodule_url
(
sm2
));
cl_assert_equal_i
(
GIT_SUBMODULE_IGNORE_UNTRACKED
,
git_submodule_ignore
(
sm2
));
cl_assert_equal_i
(
GIT_SUBMODULE_UPDATE_REBASE
,
git_submodule_update_strategy
(
sm2
));
cl_assert_equal_i
(
GIT_SUBMODULE_RECURSE_NO
,
git_submodule_fetch_recurse_submodules
(
sm2
));
/* set fetchRecurseSubmodules on-demand */
cl_git_pass
(
git_submodule_reload
(
sm1
,
0
));
git_submodule_set_fetch_recurse_submodules
(
sm1
,
GIT_SUBMODULE_RECURSE_ONDEMAND
);
cl_assert_equal_i
(
GIT_SUBMODULE_RECURSE_ONDEMAND
,
git_submodule_fetch_recurse_submodules
(
sm1
));
/* call save */
cl_git_pass
(
git_submodule_save
(
sm1
));
cl_git_pass
(
git_submodule_reload
(
sm1
,
0
));
cl_assert_equal_i
(
GIT_SUBMODULE_RECURSE_ONDEMAND
,
git_submodule_fetch_recurse_submodules
(
sm1
));
git_submodule
*
sm
;
git_submodule_free
(
sm1
);
git_submodule_free
(
sm2
);
git_repository_free
(
r2
);
git__free
(
old_url
);
cl_git_pass
(
git_submodule_set_ignore
(
g_repo
,
"sm_changed_head"
,
ignore
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"sm_changed_head"
));
cl_assert_equal_i
(
ignore
,
git_submodule_ignore
(
sm
));
git_submodule_free
(
sm
);
}
void
test_submodule_modify__set_ignore
(
void
)
{
assert_ignore_change
(
GIT_SUBMODULE_IGNORE_UNTRACKED
);
assert_ignore_change
(
GIT_SUBMODULE_IGNORE_NONE
);
assert_ignore_change
(
GIT_SUBMODULE_IGNORE_ALL
);
}
void
assert_update_change
(
git_submodule_update_t
update
)
{
git_submodule
*
sm
;
cl_git_pass
(
git_submodule_set_update
(
g_repo
,
"sm_changed_head"
,
update
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"sm_changed_head"
));
cl_assert_equal_i
(
update
,
git_submodule_update_strategy
(
sm
));
git_submodule_free
(
sm
);
}
void
test_submodule_modify__set_update
(
void
)
{
assert_update_change
(
GIT_SUBMODULE_UPDATE_REBASE
);
assert_update_change
(
GIT_SUBMODULE_UPDATE_NONE
);
assert_update_change
(
GIT_SUBMODULE_UPDATE_CHECKOUT
);
}
void
assert_recurse_change
(
git_submodule_recurse_t
recurse
)
{
git_submodule
*
sm
;
cl_git_pass
(
git_submodule_set_fetch_recurse_submodules
(
g_repo
,
"sm_changed_head"
,
recurse
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"sm_changed_head"
));
cl_assert_equal_i
(
recurse
,
git_submodule_fetch_recurse_submodules
(
sm
));
git_submodule_free
(
sm
);
}
void
test_submodule_modify__set_fetch_recurse_submodules
(
void
)
{
assert_recurse_change
(
GIT_SUBMODULE_RECURSE_YES
);
assert_recurse_change
(
GIT_SUBMODULE_RECURSE_NO
);
assert_recurse_change
(
GIT_SUBMODULE_RECURSE_ONDEMAND
);
}
void
test_submodule_modify__set_branch
(
void
)
{
git_submodule
*
sm
;
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"sm_changed_head"
));
cl_assert
(
git_submodule_branch
(
sm
)
==
NULL
);
git_submodule_free
(
sm
);
cl_git_pass
(
git_submodule_set_branch
(
g_repo
,
"sm_changed_head"
,
SM_LIBGIT2_BRANCH
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"sm_changed_head"
));
cl_assert_equal_s
(
SM_LIBGIT2_BRANCH
,
git_submodule_branch
(
sm
));
git_submodule_free
(
sm
);
cl_git_pass
(
git_submodule_set_branch
(
g_repo
,
"sm_changed_head"
,
NULL
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"sm_changed_head"
));
cl_assert
(
git_submodule_branch
(
sm
)
==
NULL
);
git_submodule_free
(
sm
);
}
void
test_submodule_modify__s
ave_last
(
void
)
void
test_submodule_modify__s
et_url
(
void
)
{
git_submodule
*
sm
;
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"sm_gitmodules_only"
));
cl_git_pass
(
git_submodule_save
(
sm
));
cl_git_pass
(
git_submodule_set_url
(
g_repo
,
"sm_changed_head"
,
SM_LIBGIT2_URL
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"sm_changed_head"
));
cl_assert_equal_s
(
SM_LIBGIT2_URL
,
git_submodule_url
(
sm
));
git_submodule_free
(
sm
);
}
tests/submodule/nosubs.c
View file @
daacf96d
...
...
@@ -21,19 +21,11 @@ void test_submodule_nosubs__lookup(void)
cl_assert_equal_i
(
GIT_EEXISTS
,
git_submodule_lookup
(
&
sm
,
repo
,
"subrepo"
));
cl_git_pass
(
git_submodule_reload_all
(
repo
,
0
));
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_submodule_lookup
(
&
sm
,
repo
,
"subdir"
));
cl_assert_equal_i
(
GIT_EEXISTS
,
git_submodule_lookup
(
&
sm
,
repo
,
"subrepo"
));
}
void
test_submodule_nosubs__immediate_reload
(
void
)
{
git_repository
*
repo
=
cl_git_sandbox_init
(
"status"
);
cl_git_pass
(
git_submodule_reload_all
(
repo
,
0
));
}
static
int
fake_submod_cb
(
git_submodule
*
sm
,
const
char
*
n
,
void
*
p
)
{
GIT_UNUSED
(
sm
);
GIT_UNUSED
(
n
);
GIT_UNUSED
(
p
);
...
...
@@ -57,41 +49,7 @@ void test_submodule_nosubs__add(void)
git_submodule_free
(
sm2
);
cl_git_pass
(
git_submodule_foreach
(
repo
,
fake_submod_cb
,
NULL
));
cl_git_pass
(
git_submodule_reload_all
(
repo
,
0
));
git_submodule_free
(
sm
);
}
void
test_submodule_nosubs__reload_add_reload
(
void
)
{
git_repository
*
repo
=
cl_git_sandbox_init
(
"status"
);
git_submodule
*
sm
;
cl_git_pass
(
git_submodule_reload_all
(
repo
,
0
));
/* try one add with a reload (to make sure no errors happen) */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
repo
,
"https://github.com/libgit2/libgit2.git"
,
"submodules/libgit2"
,
1
));
cl_git_pass
(
git_submodule_reload_all
(
repo
,
0
));
cl_assert_equal_s
(
"submodules/libgit2"
,
git_submodule_name
(
sm
));
git_submodule_free
(
sm
);
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
"submodules/libgit2"
));
cl_assert_equal_s
(
"submodules/libgit2"
,
git_submodule_name
(
sm
));
git_submodule_free
(
sm
);
/* try one add without a reload (to make sure cache inval works, too) */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
repo
,
"https://github.com/libgit2/libgit2.git"
,
"libgit2-again"
,
1
));
cl_assert_equal_s
(
"libgit2-again"
,
git_submodule_name
(
sm
));
git_submodule_free
(
sm
);
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
"libgit2-again"
));
cl_assert_equal_s
(
"libgit2-again"
,
git_submodule_name
(
sm
));
git_submodule_free
(
sm
);
}
...
...
@@ -100,10 +58,8 @@ void test_submodule_nosubs__bad_gitmodules(void)
git_repository
*
repo
=
cl_git_sandbox_init
(
"status"
);
cl_git_mkfile
(
"status/.gitmodules"
,
"[submodule
\"
foobar
\"
]
\t
path=blargle
\n\t
url=
\n\t
branch=
\n\t
update=flooble
\n\n
"
);
cl_git_fail
(
git_submodule_reload_all
(
repo
,
0
));
cl_git_rewritefile
(
"status/.gitmodules"
,
"[submodule
\"
foobar
\"
]
\t
path=blargle
\n\t
url=
\n\t
branch=
\n\t
update=rebase
\n\n
"
);
cl_git_pass
(
git_submodule_reload_all
(
repo
,
0
));
cl_git_pass
(
git_submodule_lookup
(
NULL
,
repo
,
"foobar"
));
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_submodule_lookup
(
NULL
,
repo
,
"subdir"
));
...
...
tests/submodule/status.c
View file @
daacf96d
...
...
@@ -107,56 +107,47 @@ void test_submodule_status__ignore_none(void)
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_INDEX_DELETED
)
!=
0
);
}
static
int
set_sm_ignore
(
git_submodule
*
sm
,
const
char
*
name
,
void
*
payload
)
{
git_submodule_ignore_t
ignore
=
*
(
git_submodule_ignore_t
*
)
payload
;
GIT_UNUSED
(
name
);
git_submodule_set_ignore
(
sm
,
ignore
);
return
0
;
}
void
test_submodule_status__ignore_untracked
(
void
)
{
unsigned
int
status
;
git_submodule_ignore_t
ign
=
GIT_SUBMODULE_IGNORE_UNTRACKED
;
rm_submodule
(
"sm_unchanged"
);
cl_git_pass
(
git_submodule_foreach
(
g_repo
,
set_sm_ignore
,
&
ign
));
refute_submodule_exists
(
g_repo
,
"just_a_dir"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"not-submodule"
,
GIT_EEXISTS
);
refute_submodule_exists
(
g_repo
,
"not"
,
GIT_EEXISTS
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_index"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_index"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED
)
!=
0
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_head"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_head"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_MODIFIED
)
!=
0
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_file"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_file"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_WD_MODIFIED
)
!=
0
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_untracked_file"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_untracked_file"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
status
=
get_submodule_status
(
g_repo
,
"sm_missing_commits"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_missing_commits"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_MODIFIED
)
!=
0
);
status
=
get_submodule_status
(
g_repo
,
"sm_added_and_uncommited"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_added_and_uncommited"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_INDEX_ADDED
)
!=
0
);
/* removed sm_unchanged for deleted workdir */
status
=
get_submodule_status
(
g_repo
,
"sm_unchanged"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_unchanged"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_DELETED
)
!=
0
);
/* now mkdir sm_unchanged to test uninitialized */
cl_git_pass
(
git_futils_mkdir
(
"sm_unchanged"
,
"submod2"
,
0755
,
0
));
status
=
get_submodule_status
(
g_repo
,
"sm_unchanged"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_unchanged"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
)
!=
0
);
/* update sm_changed_head in index */
add_submodule_to_index
(
"sm_changed_head"
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_head"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_head"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_INDEX_MODIFIED
)
!=
0
);
}
...
...
@@ -166,42 +157,41 @@ void test_submodule_status__ignore_dirty(void)
git_submodule_ignore_t
ign
=
GIT_SUBMODULE_IGNORE_DIRTY
;
rm_submodule
(
"sm_unchanged"
);
cl_git_pass
(
git_submodule_foreach
(
g_repo
,
set_sm_ignore
,
&
ign
));
refute_submodule_exists
(
g_repo
,
"just_a_dir"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"not-submodule"
,
GIT_EEXISTS
);
refute_submodule_exists
(
g_repo
,
"not"
,
GIT_EEXISTS
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_index"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_index"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
status
=
get_submodule_status
(
g_repo
,
"sm_changed_head"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_head"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_MODIFIED
)
!=
0
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_file"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_file"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
status
=
get_submodule_status
(
g_repo
,
"sm_changed_untracked_file"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_untracked_file"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
status
=
get_submodule_status
(
g_repo
,
"sm_missing_commits"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_missing_commits"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_MODIFIED
)
!=
0
);
status
=
get_submodule_status
(
g_repo
,
"sm_added_and_uncommited"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_added_and_uncommited"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_INDEX_ADDED
)
!=
0
);
/* removed sm_unchanged for deleted workdir */
status
=
get_submodule_status
(
g_repo
,
"sm_unchanged"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_unchanged"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_DELETED
)
!=
0
);
/* now mkdir sm_unchanged to test uninitialized */
cl_git_pass
(
git_futils_mkdir
(
"sm_unchanged"
,
"submod2"
,
0755
,
0
));
status
=
get_submodule_status
(
g_repo
,
"sm_unchanged"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_unchanged"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_WD_UNINITIALIZED
)
!=
0
);
/* update sm_changed_head in index */
add_submodule_to_index
(
"sm_changed_head"
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_head"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_head"
,
ign
)
);
cl_assert
((
status
&
GIT_SUBMODULE_STATUS_INDEX_MODIFIED
)
!=
0
);
}
...
...
@@ -211,42 +201,41 @@ void test_submodule_status__ignore_all(void)
git_submodule_ignore_t
ign
=
GIT_SUBMODULE_IGNORE_ALL
;
rm_submodule
(
"sm_unchanged"
);
cl_git_pass
(
git_submodule_foreach
(
g_repo
,
set_sm_ignore
,
&
ign
));
refute_submodule_exists
(
g_repo
,
"just_a_dir"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"not-submodule"
,
GIT_EEXISTS
);
refute_submodule_exists
(
g_repo
,
"not"
,
GIT_EEXISTS
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_index"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_index"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
status
=
get_submodule_status
(
g_repo
,
"sm_changed_head"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_head"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
status
=
get_submodule_status
(
g_repo
,
"sm_changed_file"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_file"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
status
=
get_submodule_status
(
g_repo
,
"sm_changed_untracked_file"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_untracked_file"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
status
=
get_submodule_status
(
g_repo
,
"sm_missing_commits"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_missing_commits"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
status
=
get_submodule_status
(
g_repo
,
"sm_added_and_uncommited"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_added_and_uncommited"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
/* removed sm_unchanged for deleted workdir */
status
=
get_submodule_status
(
g_repo
,
"sm_unchanged"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_unchanged"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
/* now mkdir sm_unchanged to test uninitialized */
cl_git_pass
(
git_futils_mkdir
(
"sm_unchanged"
,
"submod2"
,
0755
,
0
));
status
=
get_submodule_status
(
g_repo
,
"sm_unchanged"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_unchanged"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
/* update sm_changed_head in index */
add_submodule_to_index
(
"sm_changed_head"
);
status
=
get_submodule_status
(
g_repo
,
"sm_changed_head"
);
cl_git_pass
(
git_submodule_status
(
&
status
,
g_repo
,
"sm_changed_head"
,
ign
)
);
cl_assert
(
GIT_SUBMODULE_STATUS_IS_UNMODIFIED
(
status
));
}
...
...
tests/submodule/submodule_helpers.c
View file @
daacf96d
...
...
@@ -156,21 +156,18 @@ void refute__submodule_exists(
git_repository
*
repo
,
const
char
*
name
,
int
expected_error
,
const
char
*
msg
,
const
char
*
file
,
int
line
)
{
git_submodule
*
sm
;
clar__assert_equal
(
file
,
line
,
msg
,
1
,
"%i"
,
expected_error
,
(
int
)(
git_submodule_lookup
(
&
sm
,
repo
,
name
)));
expected_error
,
(
int
)(
git_submodule_lookup
(
NULL
,
repo
,
name
)));
}
unsigned
int
get_submodule_status
(
git_repository
*
repo
,
const
char
*
name
)
{
git_submodule
*
sm
=
NULL
;
unsigned
int
status
=
0
;
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
name
));
cl_assert
(
sm
);
cl_git_pass
(
git_submodule_status
(
&
status
,
sm
));
git_submodule_free
(
sm
);
assert
(
repo
&&
name
);
cl_git_pass
(
git_submodule_status
(
&
status
,
repo
,
name
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
return
status
;
}
...
...
tests/submodule/update.c
View file @
daacf96d
...
...
@@ -103,7 +103,7 @@ void test_submodule_update__update_submodule(void)
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
/* verify the initial state of the submodule */
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
sm
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
g_repo
,
"testrepo"
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
cl_assert_equal_i
(
submodule_status
,
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
...
...
@@ -114,7 +114,7 @@ void test_submodule_update__update_submodule(void)
cl_git_pass
(
git_submodule_update
(
sm
,
0
,
&
update_options
));
/* verify state */
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
sm
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
g_repo
,
"testrepo"
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
cl_assert_equal_i
(
submodule_status
,
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
...
...
@@ -142,7 +142,7 @@ void test_submodule_update__update_and_init_submodule(void)
/* get the submodule */
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
sm
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
g_repo
,
"testrepo"
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
cl_assert_equal_i
(
submodule_status
,
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
...
...
@@ -177,7 +177,7 @@ void test_submodule_update__update_already_checked_out_submodule(void)
/* Initialize and update the sub repository */
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
sm
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
g_repo
,
"testrepo"
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
cl_assert_equal_i
(
submodule_status
,
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
...
...
@@ -203,7 +203,11 @@ void test_submodule_update__update_already_checked_out_submodule(void)
* HEAD commit and index should be updated, but not the workdir.
*/
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
sm
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
g_repo
,
"testrepo"
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
git_submodule_free
(
sm
);
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
cl_assert_equal_i
(
submodule_status
,
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
...
...
@@ -251,7 +255,7 @@ void test_submodule_update__update_blocks_on_dirty_wd(void)
/* Initialize and update the sub repository */
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
sm
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
g_repo
,
"testrepo"
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
cl_assert_equal_i
(
submodule_status
,
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
...
...
@@ -277,7 +281,11 @@ void test_submodule_update__update_blocks_on_dirty_wd(void)
* HEAD commit and index should be updated, but not the workdir.
*/
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
sm
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
g_repo
,
"testrepo"
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
git_submodule_free
(
sm
);
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
cl_assert_equal_i
(
submodule_status
,
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
...
...
@@ -324,7 +332,7 @@ void test_submodule_update__can_force_update(void)
/* Initialize and update the sub repository */
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
sm
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
g_repo
,
"testrepo"
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
cl_assert_equal_i
(
submodule_status
,
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
...
...
@@ -349,7 +357,11 @@ void test_submodule_update__can_force_update(void)
* Verify state after checkout of parent repository. The submodule ID in the
* HEAD commit and index should be updated, but not the workdir.
*/
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
sm
));
cl_git_pass
(
git_submodule_status
(
&
submodule_status
,
g_repo
,
"testrepo"
,
GIT_SUBMODULE_IGNORE_FALLBACK
));
git_submodule_free
(
sm
);
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
"testrepo"
));
cl_assert_equal_i
(
submodule_status
,
GIT_SUBMODULE_STATUS_IN_HEAD
|
GIT_SUBMODULE_STATUS_IN_INDEX
|
GIT_SUBMODULE_STATUS_IN_CONFIG
|
...
...
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