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
923c8400
Commit
923c8400
authored
Apr 04, 2014
by
Vicent Marti
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2215 from libgit2/rb/submodule-cache-fixes
Improve submodule cache management
parents
f34408a7
eedeeb9e
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
1203 additions
and
517 deletions
+1203
-517
examples/status.c
+50
-9
src/buffer.c
+53
-0
src/buffer.h
+4
-0
src/config.c
+30
-0
src/config.h
+8
-0
src/config_file.h
+2
-1
src/index.c
+12
-0
src/index.h
+7
-0
src/path.h
+8
-0
src/refdb_fs.c
+1
-1
src/remote.c
+35
-51
src/repository.c
+1
-1
src/repository.h
+2
-7
src/submodule.c
+541
-343
src/submodule.h
+28
-5
src/vector.c
+1
-1
tests/core/buffer.c
+32
-0
tests/diff/submodules.c
+0
-5
tests/submodule/add.c
+117
-0
tests/submodule/lookup.c
+121
-26
tests/submodule/modify.c
+26
-57
tests/submodule/nosubs.c
+82
-1
tests/submodule/submodule_helpers.c
+29
-7
tests/submodule/submodule_helpers.h
+13
-2
No files found.
examples/status.c
View file @
923c8400
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
*/
*/
#include "common.h"
#include "common.h"
#include <unistd.h>
/**
/**
* This example demonstrates the use of the libgit2 status APIs,
* This example demonstrates the use of the libgit2 status APIs,
...
@@ -44,19 +45,22 @@ enum {
...
@@ -44,19 +45,22 @@ enum {
#define MAX_PATHSPEC 8
#define MAX_PATHSPEC 8
struct
opts
{
struct
opts
{
git_status_options
statusopt
;
git_status_options
statusopt
;
char
*
repodir
;
char
*
repodir
;
char
*
pathspec
[
MAX_PATHSPEC
];
char
*
pathspec
[
MAX_PATHSPEC
];
int
npaths
;
int
npaths
;
int
format
;
int
format
;
int
zterm
;
int
zterm
;
int
showbranch
;
int
showbranch
;
int
showsubmod
;
int
repeat
;
};
};
static
void
parse_opts
(
struct
opts
*
o
,
int
argc
,
char
*
argv
[]);
static
void
parse_opts
(
struct
opts
*
o
,
int
argc
,
char
*
argv
[]);
static
void
show_branch
(
git_repository
*
repo
,
int
format
);
static
void
show_branch
(
git_repository
*
repo
,
int
format
);
static
void
print_long
(
git_status_list
*
status
);
static
void
print_long
(
git_status_list
*
status
);
static
void
print_short
(
git_repository
*
repo
,
git_status_list
*
status
);
static
void
print_short
(
git_repository
*
repo
,
git_status_list
*
status
);
static
int
print_submod
(
git_submodule
*
sm
,
const
char
*
name
,
void
*
payload
);
int
main
(
int
argc
,
char
*
argv
[])
int
main
(
int
argc
,
char
*
argv
[])
{
{
...
@@ -84,6 +88,10 @@ int main(int argc, char *argv[])
...
@@ -84,6 +88,10 @@ int main(int argc, char *argv[])
fatal
(
"Cannot report status on bare repository"
,
fatal
(
"Cannot report status on bare repository"
,
git_repository_path
(
repo
));
git_repository_path
(
repo
));
show_status:
if
(
o
.
repeat
)
printf
(
"
\033
[H
\033
[2J"
);
/**
/**
* Run status on the repository
* Run status on the repository
*
*
...
@@ -98,17 +106,29 @@ int main(int argc, char *argv[])
...
@@ -98,17 +106,29 @@ int main(int argc, char *argv[])
* about what results are presented.
* about what results are presented.
*/
*/
check_lg2
(
git_status_list_new
(
&
status
,
repo
,
&
o
.
statusopt
),
check_lg2
(
git_status_list_new
(
&
status
,
repo
,
&
o
.
statusopt
),
"Could not get status"
,
NULL
);
"Could not get status"
,
NULL
);
if
(
o
.
showbranch
)
if
(
o
.
showbranch
)
show_branch
(
repo
,
o
.
format
);
show_branch
(
repo
,
o
.
format
);
if
(
o
.
showsubmod
)
{
int
submod_count
=
0
;
check_lg2
(
git_submodule_foreach
(
repo
,
print_submod
,
&
submod_count
),
"Cannot iterate submodules"
,
o
.
repodir
);
}
if
(
o
.
format
==
FORMAT_LONG
)
if
(
o
.
format
==
FORMAT_LONG
)
print_long
(
status
);
print_long
(
status
);
else
else
print_short
(
repo
,
status
);
print_short
(
repo
,
status
);
git_status_list_free
(
status
);
git_status_list_free
(
status
);
if
(
o
.
repeat
)
{
sleep
(
o
.
repeat
);
goto
show_status
;
}
git_repository_free
(
repo
);
git_repository_free
(
repo
);
git_threads_shutdown
();
git_threads_shutdown
();
...
@@ -381,7 +401,7 @@ static void print_short(git_repository *repo, git_status_list *status)
...
@@ -381,7 +401,7 @@ static void print_short(git_repository *repo, git_status_list *status)
}
}
/**
/**
* Now that we have all the information,
it's time to
format the output.
* Now that we have all the information, format the output.
*/
*/
if
(
s
->
head_to_index
)
{
if
(
s
->
head_to_index
)
{
...
@@ -417,6 +437,21 @@ static void print_short(git_repository *repo, git_status_list *status)
...
@@ -417,6 +437,21 @@ static void print_short(git_repository *repo, git_status_list *status)
}
}
}
}
static
int
print_submod
(
git_submodule
*
sm
,
const
char
*
name
,
void
*
payload
)
{
int
*
count
=
payload
;
(
void
)
name
;
if
(
*
count
==
0
)
printf
(
"# Submodules
\n
"
);
(
*
count
)
++
;
printf
(
"# - submodule '%s' at %s
\n
"
,
git_submodule_name
(
sm
),
git_submodule_path
(
sm
));
return
0
;
}
/**
/**
* Parse options that git's status command supports.
* Parse options that git's status command supports.
*/
*/
...
@@ -462,6 +497,12 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
...
@@ -462,6 +497,12 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
o
->
statusopt
.
flags
|=
GIT_STATUS_OPT_EXCLUDE_SUBMODULES
;
o
->
statusopt
.
flags
|=
GIT_STATUS_OPT_EXCLUDE_SUBMODULES
;
else
if
(
!
strncmp
(
a
,
"--git-dir="
,
strlen
(
"--git-dir="
)))
else
if
(
!
strncmp
(
a
,
"--git-dir="
,
strlen
(
"--git-dir="
)))
o
->
repodir
=
a
+
strlen
(
"--git-dir="
);
o
->
repodir
=
a
+
strlen
(
"--git-dir="
);
else
if
(
!
strcmp
(
a
,
"--repeat"
))
o
->
repeat
=
10
;
else
if
(
match_int_arg
(
&
o
->
repeat
,
&
args
,
"--repeat"
,
0
))
/* okay */
;
else
if
(
!
strcmp
(
a
,
"--list-submodules"
))
o
->
showsubmod
=
1
;
else
else
check_lg2
(
-
1
,
"Unsupported option"
,
a
);
check_lg2
(
-
1
,
"Unsupported option"
,
a
);
}
}
...
...
src/buffer.c
View file @
923c8400
...
@@ -467,6 +467,59 @@ int git_buf_join(
...
@@ -467,6 +467,59 @@ int git_buf_join(
return
0
;
return
0
;
}
}
int
git_buf_join3
(
git_buf
*
buf
,
char
separator
,
const
char
*
str_a
,
const
char
*
str_b
,
const
char
*
str_c
)
{
size_t
len_a
=
strlen
(
str_a
),
len_b
=
strlen
(
str_b
),
len_c
=
strlen
(
str_c
);
int
sep_a
=
0
,
sep_b
=
0
;
char
*
tgt
;
/* for this function, disallow pointers into the existing buffer */
assert
(
str_a
<
buf
->
ptr
||
str_a
>=
buf
->
ptr
+
buf
->
size
);
assert
(
str_b
<
buf
->
ptr
||
str_b
>=
buf
->
ptr
+
buf
->
size
);
assert
(
str_c
<
buf
->
ptr
||
str_c
>=
buf
->
ptr
+
buf
->
size
);
if
(
separator
)
{
if
(
len_a
>
0
)
{
while
(
*
str_b
==
separator
)
{
str_b
++
;
len_b
--
;
}
sep_a
=
(
str_a
[
len_a
-
1
]
!=
separator
);
}
if
(
len_a
>
0
||
len_b
>
0
)
while
(
*
str_c
==
separator
)
{
str_c
++
;
len_c
--
;
}
if
(
len_b
>
0
)
sep_b
=
(
str_b
[
len_b
-
1
]
!=
separator
);
}
if
(
git_buf_grow
(
buf
,
len_a
+
sep_a
+
len_b
+
sep_b
+
len_c
+
1
)
<
0
)
return
-
1
;
tgt
=
buf
->
ptr
;
if
(
len_a
)
{
memcpy
(
tgt
,
str_a
,
len_a
);
tgt
+=
len_a
;
}
if
(
sep_a
)
*
tgt
++
=
separator
;
if
(
len_b
)
{
memcpy
(
tgt
,
str_b
,
len_b
);
tgt
+=
len_b
;
}
if
(
sep_b
)
*
tgt
++
=
separator
;
if
(
len_c
)
memcpy
(
tgt
,
str_c
,
len_c
);
buf
->
size
=
len_a
+
sep_a
+
len_b
+
sep_b
+
len_c
;
buf
->
ptr
[
buf
->
size
]
=
'\0'
;
return
0
;
}
void
git_buf_rtrim
(
git_buf
*
buf
)
void
git_buf_rtrim
(
git_buf
*
buf
)
{
{
while
(
buf
->
size
>
0
)
{
while
(
buf
->
size
>
0
)
{
...
...
src/buffer.h
View file @
923c8400
...
@@ -98,8 +98,12 @@ void git_buf_truncate(git_buf *buf, size_t len);
...
@@ -98,8 +98,12 @@ void git_buf_truncate(git_buf *buf, size_t len);
void
git_buf_shorten
(
git_buf
*
buf
,
size_t
amount
);
void
git_buf_shorten
(
git_buf
*
buf
,
size_t
amount
);
void
git_buf_rtruncate_at_char
(
git_buf
*
path
,
char
separator
);
void
git_buf_rtruncate_at_char
(
git_buf
*
path
,
char
separator
);
/** General join with separator */
int
git_buf_join_n
(
git_buf
*
buf
,
char
separator
,
int
nbuf
,
...);
int
git_buf_join_n
(
git_buf
*
buf
,
char
separator
,
int
nbuf
,
...);
/** Fast join of two strings - first may legally point into `buf` data */
int
git_buf_join
(
git_buf
*
buf
,
char
separator
,
const
char
*
str_a
,
const
char
*
str_b
);
int
git_buf_join
(
git_buf
*
buf
,
char
separator
,
const
char
*
str_a
,
const
char
*
str_b
);
/** Fast join of three strings - cannot reference `buf` data */
int
git_buf_join3
(
git_buf
*
buf
,
char
separator
,
const
char
*
str_a
,
const
char
*
str_b
,
const
char
*
str_c
);
/**
/**
* Join two strings as paths, inserting a slash between as needed.
* Join two strings as paths, inserting a slash between as needed.
...
...
src/config.c
View file @
923c8400
...
@@ -615,6 +615,36 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
...
@@ -615,6 +615,36 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
return
error
;
return
error
;
}
}
int
git_config__update_entry
(
git_config
*
config
,
const
char
*
key
,
const
char
*
value
,
bool
overwrite_existing
,
bool
only_if_existing
)
{
int
error
=
0
;
const
git_config_entry
*
ce
=
NULL
;
if
((
error
=
git_config__lookup_entry
(
&
ce
,
config
,
key
,
false
))
<
0
)
return
error
;
if
(
!
ce
&&
only_if_existing
)
/* entry doesn't exist */
return
0
;
if
(
ce
&&
!
overwrite_existing
)
/* entry would be overwritten */
return
0
;
if
(
value
&&
ce
&&
ce
->
value
&&
!
strcmp
(
ce
->
value
,
value
))
/* no change */
return
0
;
if
(
!
value
&&
(
!
ce
||
!
ce
->
value
))
/* asked to delete absent entry */
return
0
;
if
(
!
value
)
error
=
git_config_delete_entry
(
config
,
key
);
else
error
=
git_config_set_string
(
config
,
key
,
value
);
return
error
;
}
/***********
/***********
* Getters
* Getters
***********/
***********/
...
...
src/config.h
View file @
923c8400
...
@@ -53,6 +53,14 @@ extern int git_config__lookup_entry(
...
@@ -53,6 +53,14 @@ extern int git_config__lookup_entry(
const
char
*
key
,
const
char
*
key
,
bool
no_errors
);
bool
no_errors
);
/* internal only: update and/or delete entry string with constraints */
extern
int
git_config__update_entry
(
git_config
*
cfg
,
const
char
*
key
,
const
char
*
value
,
bool
overwrite_existing
,
bool
only_if_existing
);
/*
/*
* Lookup functions that cannot fail. These functions look up a config
* Lookup functions that cannot fail. These functions look up a config
* value and return a fallback value if the value is missing or if any
* value and return a fallback value if the value is missing or if any
...
...
src/config_file.h
View file @
923c8400
...
@@ -16,7 +16,8 @@ GIT_INLINE(int) git_config_file_open(git_config_backend *cfg, unsigned int level
...
@@ -16,7 +16,8 @@ GIT_INLINE(int) git_config_file_open(git_config_backend *cfg, unsigned int level
GIT_INLINE
(
void
)
git_config_file_free
(
git_config_backend
*
cfg
)
GIT_INLINE
(
void
)
git_config_file_free
(
git_config_backend
*
cfg
)
{
{
cfg
->
free
(
cfg
);
if
(
cfg
)
cfg
->
free
(
cfg
);
}
}
GIT_INLINE
(
int
)
git_config_file_get_string
(
GIT_INLINE
(
int
)
git_config_file_get_string
(
...
...
src/index.c
View file @
923c8400
...
@@ -517,6 +517,18 @@ int git_index_read(git_index *index, int force)
...
@@ -517,6 +517,18 @@ int git_index_read(git_index *index, int force)
return
error
;
return
error
;
}
}
int
git_index__changed_relative_to
(
git_index
*
index
,
const
git_futils_filestamp
*
fs
)
{
/* attempt to update index (ignoring errors) */
if
(
git_index_read
(
index
,
false
)
<
0
)
giterr_clear
();
return
(
index
->
stamp
.
mtime
!=
fs
->
mtime
||
index
->
stamp
.
size
!=
fs
->
size
||
index
->
stamp
.
ino
!=
fs
->
ino
);
}
int
git_index_write
(
git_index
*
index
)
int
git_index_write
(
git_index
*
index
)
{
{
git_filebuf
file
=
GIT_FILEBUF_INIT
;
git_filebuf
file
=
GIT_FILEBUF_INIT
;
...
...
src/index.h
View file @
923c8400
...
@@ -62,4 +62,11 @@ extern void git_index__set_ignore_case(git_index *index, bool ignore_case);
...
@@ -62,4 +62,11 @@ extern void git_index__set_ignore_case(git_index *index, bool ignore_case);
extern
unsigned
int
git_index__create_mode
(
unsigned
int
mode
);
extern
unsigned
int
git_index__create_mode
(
unsigned
int
mode
);
GIT_INLINE
(
const
git_futils_filestamp
*
)
git_index__filestamp
(
git_index
*
index
)
{
return
&
index
->
stamp
;
}
extern
int
git_index__changed_relative_to
(
git_index
*
index
,
const
git_futils_filestamp
*
fs
);
#endif
#endif
src/path.h
View file @
923c8400
...
@@ -119,6 +119,14 @@ GIT_INLINE(void) git_path_mkposix(char *path)
...
@@ -119,6 +119,14 @@ GIT_INLINE(void) git_path_mkposix(char *path)
# define git_path_mkposix(p)
/* blank */
# define git_path_mkposix(p)
/* blank */
#endif
#endif
/**
* Check if string is a relative path (i.e. starts with "./" or "../")
*/
GIT_INLINE
(
int
)
git_path_is_relative
(
const
char
*
p
)
{
return
(
p
[
0
]
==
'.'
&&
(
p
[
1
]
==
'/'
||
(
p
[
1
]
==
'.'
&&
p
[
2
]
==
'/'
)));
}
extern
int
git__percent_decode
(
git_buf
*
decoded_out
,
const
char
*
input
);
extern
int
git__percent_decode
(
git_buf
*
decoded_out
,
const
char
*
input
);
/**
/**
...
...
src/refdb_fs.c
View file @
923c8400
...
@@ -1432,7 +1432,7 @@ static int create_new_reflog_file(const char *filepath)
...
@@ -1432,7 +1432,7 @@ static int create_new_reflog_file(const char *filepath)
GIT_INLINE
(
int
)
retrieve_reflog_path
(
git_buf
*
path
,
git_repository
*
repo
,
const
char
*
name
)
GIT_INLINE
(
int
)
retrieve_reflog_path
(
git_buf
*
path
,
git_repository
*
repo
,
const
char
*
name
)
{
{
return
git_buf_join
_n
(
path
,
'/'
,
3
,
repo
->
path_repository
,
GIT_REFLOG_DIR
,
name
);
return
git_buf_join
3
(
path
,
'/'
,
repo
->
path_repository
,
GIT_REFLOG_DIR
,
name
);
}
}
static
int
refdb_reflog_fs__ensure_log
(
git_refdb_backend
*
_backend
,
const
char
*
name
)
static
int
refdb_reflog_fs__ensure_log
(
git_refdb_backend
*
_backend
,
const
char
*
name
)
...
...
src/remote.c
View file @
923c8400
...
@@ -495,9 +495,10 @@ cleanup:
...
@@ -495,9 +495,10 @@ cleanup:
int
git_remote_save
(
const
git_remote
*
remote
)
int
git_remote_save
(
const
git_remote
*
remote
)
{
{
int
error
;
int
error
;
git_config
*
c
onfi
g
;
git_config
*
c
f
g
;
const
char
*
tagopt
=
NULL
;
const
char
*
tagopt
=
NULL
;
git_buf
buf
=
GIT_BUF_INIT
;
git_buf
buf
=
GIT_BUF_INIT
;
const
git_config_entry
*
existing
;
assert
(
remote
);
assert
(
remote
);
...
@@ -509,43 +510,31 @@ int git_remote_save(const git_remote *remote)
...
@@ -509,43 +510,31 @@ int git_remote_save(const git_remote *remote)
if
((
error
=
ensure_remote_name_is_valid
(
remote
->
name
))
<
0
)
if
((
error
=
ensure_remote_name_is_valid
(
remote
->
name
))
<
0
)
return
error
;
return
error
;
if
(
git_repository_config__weakptr
(
&
config
,
remote
->
repo
)
<
0
)
if
(
(
error
=
git_repository_config__weakptr
(
&
cfg
,
remote
->
repo
)
)
<
0
)
return
-
1
;
return
error
;
if
(
git_buf_printf
(
&
buf
,
"remote.%s.url"
,
remote
->
name
)
<
0
)
if
(
(
error
=
git_buf_printf
(
&
buf
,
"remote.%s.url"
,
remote
->
name
)
)
<
0
)
return
-
1
;
return
error
;
if
(
git_config_set_string
(
config
,
git_buf_cstr
(
&
buf
),
remote
->
url
)
<
0
)
{
/* after this point, buffer is allocated so end with cleanup */
git_buf_free
(
&
buf
);
return
-
1
;
if
((
error
=
git_config_set_string
(
}
cfg
,
git_buf_cstr
(
&
buf
),
remote
->
url
))
<
0
)
goto
cleanup
;
git_buf_clear
(
&
buf
);
git_buf_clear
(
&
buf
);
if
(
git_buf_printf
(
&
buf
,
"remote.%s.pushurl"
,
remote
->
name
)
<
0
)
if
(
(
error
=
git_buf_printf
(
&
buf
,
"remote.%s.pushurl"
,
remote
->
name
)
)
<
0
)
return
-
1
;
goto
cleanup
;
if
(
remote
->
pushurl
)
{
if
((
error
=
git_config__update_entry
(
if
(
git_config_set_string
(
config
,
git_buf_cstr
(
&
buf
),
remote
->
pushurl
)
<
0
)
{
cfg
,
git_buf_cstr
(
&
buf
),
remote
->
pushurl
,
true
,
false
))
<
0
)
git_buf_free
(
&
buf
);
goto
cleanup
;
return
-
1
;
}
}
else
{
int
error
=
git_config_delete_entry
(
config
,
git_buf_cstr
(
&
buf
));
if
(
error
==
GIT_ENOTFOUND
)
{
error
=
0
;
giterr_clear
();
}
if
(
error
<
0
)
{
git_buf_free
(
&
buf
);
return
error
;
}
}
if
(
update_config_refspec
(
remote
,
config
,
GIT_DIRECTION_FETCH
)
<
0
)
if
(
(
error
=
update_config_refspec
(
remote
,
cfg
,
GIT_DIRECTION_FETCH
)
)
<
0
)
goto
on_error
;
goto
cleanup
;
if
(
update_config_refspec
(
remote
,
config
,
GIT_DIRECTION_PUSH
)
<
0
)
if
(
(
error
=
update_config_refspec
(
remote
,
cfg
,
GIT_DIRECTION_PUSH
)
)
<
0
)
goto
on_error
;
goto
cleanup
;
/*
/*
* What action to take depends on the old and new values. This
* What action to take depends on the old and new values. This
...
@@ -561,31 +550,26 @@ int git_remote_save(const git_remote *remote)
...
@@ -561,31 +550,26 @@ int git_remote_save(const git_remote *remote)
*/
*/
git_buf_clear
(
&
buf
);
git_buf_clear
(
&
buf
);
if
(
git_buf_printf
(
&
buf
,
"remote.%s.tagopt"
,
remote
->
name
)
<
0
)
if
((
error
=
git_buf_printf
(
&
buf
,
"remote.%s.tagopt"
,
remote
->
name
))
<
0
)
goto
on_error
;
goto
cleanup
;
error
=
git_config_get_string
(
&
tagopt
,
config
,
git_buf_cstr
(
&
buf
));
if
(
error
<
0
&&
error
!=
GIT_ENOTFOUND
)
goto
on_error
;
if
(
remote
->
download_tags
==
GIT_REMOTE_DOWNLOAD_TAGS_ALL
)
{
if
((
error
=
git_config__lookup_entry
(
if
(
git_config_set_string
(
config
,
git_buf_cstr
(
&
buf
),
"--tags"
)
<
0
)
&
existing
,
cfg
,
git_buf_cstr
(
&
buf
),
false
))
<
0
)
goto
on_error
;
goto
cleanup
;
}
else
if
(
remote
->
download_tags
==
GIT_REMOTE_DOWNLOAD_TAGS_NONE
)
{
if
(
git_config_set_string
(
config
,
git_buf_cstr
(
&
buf
),
"--no-tags"
)
<
0
)
goto
on_error
;
}
else
if
(
tagopt
)
{
if
(
git_config_delete_entry
(
config
,
git_buf_cstr
(
&
buf
))
<
0
)
goto
on_error
;
}
git_buf_free
(
&
buf
);
if
(
remote
->
download_tags
==
GIT_REMOTE_DOWNLOAD_TAGS_ALL
)
tagopt
=
"--tags"
;
else
if
(
remote
->
download_tags
==
GIT_REMOTE_DOWNLOAD_TAGS_NONE
)
tagopt
=
"--no-tags"
;
else
if
(
existing
!=
NULL
)
tagopt
=
NULL
;
return
0
;
error
=
git_config__update_entry
(
cfg
,
git_buf_cstr
(
&
buf
),
tagopt
,
true
,
false
);
on_error
:
cleanup
:
git_buf_free
(
&
buf
);
git_buf_free
(
&
buf
);
return
-
1
;
return
error
;
}
}
const
char
*
git_remote_name
(
const
git_remote
*
remote
)
const
char
*
git_remote_name
(
const
git_remote
*
remote
)
...
...
src/repository.c
View file @
923c8400
...
@@ -93,6 +93,7 @@ void git_repository__cleanup(git_repository *repo)
...
@@ -93,6 +93,7 @@ void git_repository__cleanup(git_repository *repo)
git_cache_clear
(
&
repo
->
objects
);
git_cache_clear
(
&
repo
->
objects
);
git_attr_cache_flush
(
repo
);
git_attr_cache_flush
(
repo
);
git_submodule_cache_free
(
repo
);
set_config
(
repo
,
NULL
);
set_config
(
repo
,
NULL
);
set_index
(
repo
,
NULL
);
set_index
(
repo
,
NULL
);
...
@@ -108,7 +109,6 @@ void git_repository_free(git_repository *repo)
...
@@ -108,7 +109,6 @@ void git_repository_free(git_repository *repo)
git_repository__cleanup
(
repo
);
git_repository__cleanup
(
repo
);
git_cache_free
(
&
repo
->
objects
);
git_cache_free
(
&
repo
->
objects
);
git_submodule_config_free
(
repo
);
git_diff_driver_registry_free
(
repo
->
diff_drivers
);
git_diff_driver_registry_free
(
repo
->
diff_drivers
);
repo
->
diff_drivers
=
NULL
;
repo
->
diff_drivers
=
NULL
;
...
...
src/repository.h
View file @
923c8400
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
#include "buffer.h"
#include "buffer.h"
#include "object.h"
#include "object.h"
#include "attrcache.h"
#include "attrcache.h"
#include "s
trmap
.h"
#include "s
ubmodule
.h"
#include "diff_driver.h"
#include "diff_driver.h"
#define DOT_GIT ".git"
#define DOT_GIT ".git"
...
@@ -105,10 +105,10 @@ struct git_repository {
...
@@ -105,10 +105,10 @@ struct git_repository {
git_refdb
*
_refdb
;
git_refdb
*
_refdb
;
git_config
*
_config
;
git_config
*
_config
;
git_index
*
_index
;
git_index
*
_index
;
git_submodule_cache
*
_submodules
;
git_cache
objects
;
git_cache
objects
;
git_attr_cache
attrcache
;
git_attr_cache
attrcache
;
git_strmap
*
submodules
;
git_diff_driver_registry
*
diff_drivers
;
git_diff_driver_registry
*
diff_drivers
;
char
*
path_repository
;
char
*
path_repository
;
...
@@ -149,11 +149,6 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo);
...
@@ -149,11 +149,6 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo);
int
git_repository__cvar
(
int
*
out
,
git_repository
*
repo
,
git_cvar_cached
cvar
);
int
git_repository__cvar
(
int
*
out
,
git_repository
*
repo
,
git_cvar_cached
cvar
);
void
git_repository__cvar_cache_clear
(
git_repository
*
repo
);
void
git_repository__cvar_cache_clear
(
git_repository
*
repo
);
/*
* Submodule cache
*/
extern
void
git_submodule_config_free
(
git_repository
*
repo
);
GIT_INLINE
(
int
)
git_repository__ensure_not_bare
(
GIT_INLINE
(
int
)
git_repository__ensure_not_bare
(
git_repository
*
repo
,
git_repository
*
repo
,
const
char
*
operation_name
)
const
char
*
operation_name
)
...
...
src/submodule.c
View file @
923c8400
...
@@ -49,6 +49,16 @@ static git_cvar_map _sm_recurse_map[] = {
...
@@ -49,6 +49,16 @@ static git_cvar_map _sm_recurse_map[] = {
{
GIT_CVAR_TRUE
,
NULL
,
GIT_SUBMODULE_RECURSE_YES
},
{
GIT_CVAR_TRUE
,
NULL
,
GIT_SUBMODULE_RECURSE_YES
},
};
};
enum
{
CACHE_OK
=
0
,
CACHE_REFRESH
=
1
,
CACHE_FLUSH
=
2
};
enum
{
GITMODULES_EXISTING
=
0
,
GITMODULES_CREATE
=
1
,
};
static
kh_inline
khint_t
str_hash_no_trailing_slash
(
const
char
*
s
)
static
kh_inline
khint_t
str_hash_no_trailing_slash
(
const
char
*
s
)
{
{
khint_t
h
;
khint_t
h
;
...
@@ -77,13 +87,15 @@ __KHASH_IMPL(
...
@@ -77,13 +87,15 @@ __KHASH_IMPL(
str
,
static
kh_inline
,
const
char
*
,
void
*
,
1
,
str
,
static
kh_inline
,
const
char
*
,
void
*
,
1
,
str_hash_no_trailing_slash
,
str_equal_no_trailing_slash
);
str_hash_no_trailing_slash
,
str_equal_no_trailing_slash
);
static
int
load_submodule_config
(
git_repository
*
repo
,
bool
reload
);
static
int
submodule_cache_init
(
git_repository
*
repo
,
int
refresh
);
static
git_config_backend
*
open_gitmodules
(
git_repository
*
,
bool
,
const
git_oid
*
);
static
void
submodule_cache_free
(
git_submodule_cache
*
cache
);
static
int
lookup_head_remote
(
git_buf
*
url
,
git_repository
*
repo
);
static
int
submodule_get
(
git_submodule
**
,
git_repository
*
,
const
char
*
,
const
char
*
);
static
git_config_backend
*
open_gitmodules
(
git_submodule_cache
*
,
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_config
(
const
git_config_entry
*
,
void
*
);
static
int
submodule_load_from_wd_lite
(
git_submodule
*
);
static
int
submodule_load_from_wd_lite
(
git_submodule
*
);
static
int
submodule_update_config
(
git_submodule
*
,
const
char
*
,
const
char
*
,
bool
,
bool
);
static
void
submodule_get_index_status
(
unsigned
int
*
,
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_get_wd_status
(
unsigned
int
*
,
git_submodule
*
,
git_repository
*
,
git_submodule_ignore_t
);
...
@@ -102,7 +114,7 @@ static int submodule_config_key_trunc_puts(git_buf *key, const char *suffix)
...
@@ -102,7 +114,7 @@ static int submodule_config_key_trunc_puts(git_buf *key, const char *suffix)
/* lookup submodule or return ENOTFOUND if it doesn't exist */
/* lookup submodule or return ENOTFOUND if it doesn't exist */
static
int
submodule_lookup
(
static
int
submodule_lookup
(
git_submodule
**
out
,
git_submodule
**
out
,
git_s
trmap
*
cache
,
git_s
ubmodule_cache
*
cache
,
const
char
*
name
,
const
char
*
name
,
const
char
*
alternate
)
const
char
*
alternate
)
{
{
...
@@ -110,18 +122,18 @@ static int submodule_lookup(
...
@@ -110,18 +122,18 @@ static int submodule_lookup(
/* lock cache */
/* lock cache */
pos
=
git_strmap_lookup_index
(
cache
,
name
);
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
name
);
if
(
!
git_strmap_valid_index
(
cache
,
pos
)
&&
alternate
)
if
(
!
git_strmap_valid_index
(
cache
->
submodules
,
pos
)
&&
alternate
)
pos
=
git_strmap_lookup_index
(
cache
,
alternate
);
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
alternate
);
if
(
!
git_strmap_valid_index
(
cache
,
pos
))
{
if
(
!
git_strmap_valid_index
(
cache
->
submodules
,
pos
))
{
/* unlock cache */
/* unlock cache */
return
GIT_ENOTFOUND
;
/* don't set error - caller will cope */
return
GIT_ENOTFOUND
;
/* don't set error - caller will cope */
}
}
if
(
out
!=
NULL
)
{
if
(
out
!=
NULL
)
{
git_submodule
*
sm
=
git_strmap_value_at
(
cache
,
pos
);
git_submodule
*
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
GIT_REFCOUNT_INC
(
sm
);
GIT_REFCOUNT_INC
(
sm
);
*
out
=
sm
;
*
out
=
sm
;
}
}
...
@@ -131,6 +143,18 @@ static int submodule_lookup(
...
@@ -131,6 +143,18 @@ static int submodule_lookup(
return
0
;
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
* PUBLIC APIS
*/
*/
...
@@ -139,17 +163,45 @@ bool git_submodule__is_submodule(git_repository *repo, const char *name)
...
@@ -139,17 +163,45 @@ bool git_submodule__is_submodule(git_repository *repo, const char *name)
{
{
git_strmap
*
map
;
git_strmap
*
map
;
if
(
load_submodule_config
(
repo
,
false
)
<
0
)
{
if
(
submodule_cache_init
(
repo
,
CACHE_OK
)
<
0
)
{
giterr_clear
();
giterr_clear
();
return
false
;
return
false
;
}
}
if
(
!
(
map
=
repo
->
submodules
))
if
(
!
repo
->
_submodules
||
!
(
map
=
repo
->
_submodules
->
submodules
))
return
false
;
return
false
;
return
git_strmap_valid_index
(
map
,
git_strmap_lookup_index
(
map
,
name
));
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
)
return
;
giterr_set
(
GITERR_SUBMODULE
,
(
error
==
GIT_ENOTFOUND
)
?
"No submodule named '%s'"
:
"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
);
if
((
error
=
submodule_cache_init
(
repo
,
CACHE_OK
))
<
0
)
return
error
;
if
((
error
=
submodule_lookup
(
out
,
repo
->
_submodules
,
name
,
NULL
))
<
0
)
submodule_set_lookup_error
(
error
,
name
);
return
error
;
}
int
git_submodule_lookup
(
int
git_submodule_lookup
(
git_submodule
**
out
,
/* NULL if user only wants to test existence */
git_submodule
**
out
,
/* NULL if user only wants to test existence */
git_repository
*
repo
,
git_repository
*
repo
,
...
@@ -159,88 +211,99 @@ int git_submodule_lookup(
...
@@ -159,88 +211,99 @@ int git_submodule_lookup(
assert
(
repo
&&
name
);
assert
(
repo
&&
name
);
if
((
error
=
load_submodule_config
(
repo
,
false
))
<
0
)
if
((
error
=
submodule_cache_init
(
repo
,
CACHE_REFRESH
))
<
0
)
return
error
;
return
error
;
if
((
error
=
submodule_lookup
(
out
,
repo
->
submodules
,
name
,
NULL
))
<
0
)
{
if
((
error
=
submodule_lookup
(
out
,
repo
->
_
submodules
,
name
,
NULL
))
<
0
)
{
/* check if a plausible submodule exists at path */
/* check if a plausible submodule exists at path */
if
(
git_repository_workdir
(
repo
))
{
if
(
git_repository_workdir
(
repo
))
{
git_buf
path
=
GIT_BUF_INIT
;
git_buf
path
=
GIT_BUF_INIT
;
if
(
git_buf_joinpath
(
&
path
,
git_repository_workdir
(
repo
),
name
)
<
0
)
if
(
git_buf_join3
(
&
path
,
'/'
,
git_repository_workdir
(
repo
),
name
,
DOT_GIT
)
<
0
)
return
-
1
;
return
-
1
;
if
(
git_path_
contains
(
&
path
,
DOT_GIT
))
if
(
git_path_
exists
(
path
.
ptr
))
error
=
GIT_EEXISTS
;
error
=
GIT_EEXISTS
;
git_buf_free
(
&
path
);
git_buf_free
(
&
path
);
}
}
giterr_set
(
GITERR_SUBMODULE
,
(
error
==
GIT_ENOTFOUND
)
?
submodule_set_lookup_error
(
error
,
name
);
"No submodule named '%s'"
:
"Submodule '%s' has not been added yet"
,
name
);
}
}
return
error
;
return
error
;
}
}
static
void
submodule_free_dup
(
void
*
sm
)
{
git_submodule_free
(
sm
);
}
int
git_submodule_foreach
(
int
git_submodule_foreach
(
git_repository
*
repo
,
git_repository
*
repo
,
int
(
*
callback
)(
git_submodule
*
sm
,
const
char
*
name
,
void
*
payload
),
int
(
*
callback
)(
git_submodule
*
sm
,
const
char
*
name
,
void
*
payload
),
void
*
payload
)
void
*
payload
)
{
{
int
error
;
int
error
;
size_t
i
;
git_submodule
*
sm
;
git_submodule
*
sm
;
git_
vector
seen
=
GIT_VECTOR_INIT
;
git_
submodule_cache
*
cache
;
git_vector
_set_cmp
(
&
seen
,
submodule_cmp
)
;
git_vector
snapshot
=
GIT_VECTOR_INIT
;
assert
(
repo
&&
callback
);
assert
(
repo
&&
callback
);
if
((
error
=
load_submodule_config
(
repo
,
true
))
<
0
)
if
((
error
=
submodule_cache_init
(
repo
,
CACHE_REFRESH
))
<
0
)
return
error
;
return
error
;
git_strmap_foreach_value
(
repo
->
submodules
,
sm
,
{
cache
=
repo
->
_submodules
;
/* Usually the following will not come into play - it just prevents
* us from issuing a callback twice for a submodule where the name
if
(
git_mutex_lock
(
&
cache
->
lock
)
<
0
)
{
* and path are not the same.
giterr_set
(
GITERR_OS
,
"Unable to acquire lock on submodule cache"
);
*/
return
-
1
;
if
(
GIT_REFCOUNT_VAL
(
sm
)
>
1
)
{
}
if
(
git_vector_bsearch
(
NULL
,
&
seen
,
sm
)
!=
GIT_ENOTFOUND
)
continue
;
if
(
!
(
error
=
git_vector_init
(
if
((
error
=
git_vector_insert
(
&
seen
,
sm
))
<
0
)
&
snapshot
,
kh_size
(
cache
->
submodules
),
submodule_cmp
)))
{
git_strmap_foreach_value
(
cache
->
submodules
,
sm
,
{
if
((
error
=
git_vector_insert
(
&
snapshot
,
sm
))
<
0
)
break
;
break
;
}
GIT_REFCOUNT_INC
(
sm
);
});
}
git_mutex_unlock
(
&
cache
->
lock
);
if
(
error
<
0
)
goto
done
;
git_vector_uniq
(
&
snapshot
,
submodule_free_dup
);
git_vector_foreach
(
&
snapshot
,
i
,
sm
)
{
if
((
error
=
callback
(
sm
,
sm
->
name
,
payload
))
!=
0
)
{
if
((
error
=
callback
(
sm
,
sm
->
name
,
payload
))
!=
0
)
{
giterr_set_after_callback
(
error
);
giterr_set_after_callback
(
error
);
break
;
break
;
}
}
}
);
}
git_vector_free
(
&
seen
);
done:
git_vector_foreach
(
&
snapshot
,
i
,
sm
)
git_submodule_free
(
sm
);
git_vector_free
(
&
snapshot
);
return
error
;
return
error
;
}
}
void
git_submodule_c
onfig
_free
(
git_repository
*
repo
)
void
git_submodule_c
ache
_free
(
git_repository
*
repo
)
{
{
git_strmap
*
smcfg
;
git_submodule_cache
*
cache
;
git_submodule
*
sm
;
assert
(
repo
);
assert
(
repo
);
smcfg
=
repo
->
submodules
;
if
((
cache
=
git__swap
(
repo
->
_submodules
,
NULL
))
!=
NULL
)
repo
->
submodules
=
NULL
;
submodule_cache_free
(
cache
);
if
(
smcfg
==
NULL
)
return
;
git_strmap_foreach_value
(
smcfg
,
sm
,
{
sm
->
repo
=
NULL
;
/* disconnect from repo */
;
git_submodule_free
(
sm
);
});
git_strmap_free
(
smcfg
);
}
}
int
git_submodule_add_setup
(
int
git_submodule_add_setup
(
...
@@ -261,18 +324,16 @@ int git_submodule_add_setup(
...
@@ -261,18 +324,16 @@ int git_submodule_add_setup(
/* see if there is already an entry for this submodule */
/* see if there is already an entry for this submodule */
if
(
git_submodule_lookup
(
&
sm
,
repo
,
path
)
<
0
)
if
(
git_submodule_lookup
(
NULL
,
repo
,
path
)
<
0
)
giterr_clear
();
giterr_clear
();
else
{
else
{
git_submodule_free
(
sm
);
giterr_set
(
GITERR_SUBMODULE
,
giterr_set
(
GITERR_SUBMODULE
,
"Attempt to add
a submodule that already exists"
);
"Attempt to add
submodule '%s' that already exists"
,
path
);
return
GIT_EEXISTS
;
return
GIT_EEXISTS
;
}
}
/* resolve parameters */
/* resolve parameters */
error
=
git_submodule_resolve_url
(
&
real_url
,
repo
,
url
);
if
((
error
=
git_submodule_resolve_url
(
&
real_url
,
repo
,
url
))
<
0
)
if
(
error
)
goto
cleanup
;
goto
cleanup
;
/* validate and normalize path */
/* validate and normalize path */
...
@@ -288,9 +349,9 @@ int git_submodule_add_setup(
...
@@ -288,9 +349,9 @@ int git_submodule_add_setup(
/* update .gitmodules */
/* update .gitmodules */
if
(
(
mods
=
open_gitmodules
(
repo
,
true
,
NULL
))
==
NULL
)
{
if
(
!
(
mods
=
open_gitmodules
(
repo
->
_submodules
,
GITMODULES_CREATE
))
)
{
giterr_set
(
GITERR_SUBMODULE
,
giterr_set
(
GITERR_SUBMODULE
,
"Adding submodules to a bare repository is not supported
(for now)
"
);
"Adding submodules to a bare repository is not supported"
);
return
-
1
;
return
-
1
;
}
}
...
@@ -328,8 +389,8 @@ int git_submodule_add_setup(
...
@@ -328,8 +389,8 @@ int git_submodule_add_setup(
else
if
(
use_gitlink
)
{
else
if
(
use_gitlink
)
{
git_buf
repodir
=
GIT_BUF_INIT
;
git_buf
repodir
=
GIT_BUF_INIT
;
error
=
git_buf_join
_n
(
error
=
git_buf_join
3
(
&
repodir
,
'/'
,
3
,
git_repository_path
(
repo
),
"modules"
,
path
);
&
repodir
,
'/'
,
git_repository_path
(
repo
),
"modules"
,
path
);
if
(
error
<
0
)
if
(
error
<
0
)
goto
cleanup
;
goto
cleanup
;
...
@@ -348,10 +409,18 @@ int git_submodule_add_setup(
...
@@ -348,10 +409,18 @@ int git_submodule_add_setup(
/* add submodule to hash and "reload" it */
/* add submodule to hash and "reload" it */
if
(
!
(
error
=
submodule_get
(
&
sm
,
repo
,
path
,
NULL
))
&&
if
(
git_mutex_lock
(
&
repo
->
_submodules
->
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Unable to acquire lock on submodule cache"
);
error
=
-
1
;
goto
cleanup
;
}
if
(
!
(
error
=
submodule_get
(
&
sm
,
repo
->
_submodules
,
path
,
NULL
))
&&
!
(
error
=
git_submodule_reload
(
sm
,
false
)))
!
(
error
=
git_submodule_reload
(
sm
,
false
)))
error
=
git_submodule_init
(
sm
,
false
);
error
=
git_submodule_init
(
sm
,
false
);
git_mutex_unlock
(
&
repo
->
_submodules
->
lock
);
cleanup:
cleanup:
if
(
error
&&
sm
)
{
if
(
error
&&
sm
)
{
git_submodule_free
(
sm
);
git_submodule_free
(
sm
);
...
@@ -360,8 +429,7 @@ cleanup:
...
@@ -360,8 +429,7 @@ cleanup:
if
(
out
!=
NULL
)
if
(
out
!=
NULL
)
*
out
=
sm
;
*
out
=
sm
;
if
(
mods
!=
NULL
)
git_config_file_free
(
mods
);
git_config_file_free
(
mods
);
git_repository_free
(
subrepo
);
git_repository_free
(
subrepo
);
git_buf_free
(
&
real_url
);
git_buf_free
(
&
real_url
);
git_buf_free
(
&
name
);
git_buf_free
(
&
name
);
...
@@ -489,10 +557,10 @@ int git_submodule_save(git_submodule *submodule)
...
@@ -489,10 +557,10 @@ int git_submodule_save(git_submodule *submodule)
assert
(
submodule
);
assert
(
submodule
);
mods
=
open_gitmodules
(
submodule
->
repo
,
true
,
NULL
);
mods
=
open_gitmodules
(
submodule
->
repo
->
_submodules
,
GITMODULES_CREATE
);
if
(
!
mods
)
{
if
(
!
mods
)
{
giterr_set
(
GITERR_SUBMODULE
,
giterr_set
(
GITERR_SUBMODULE
,
"Adding submodules to a bare repository is not supported
(for now)
"
);
"Adding submodules to a bare repository is not supported"
);
return
-
1
;
return
-
1
;
}
}
...
@@ -539,8 +607,7 @@ int git_submodule_save(git_submodule *submodule)
...
@@ -539,8 +607,7 @@ int git_submodule_save(git_submodule *submodule)
submodule
->
flags
|=
GIT_SUBMODULE_STATUS_IN_CONFIG
;
submodule
->
flags
|=
GIT_SUBMODULE_STATUS_IN_CONFIG
;
cleanup:
cleanup:
if
(
mods
!=
NULL
)
git_config_file_free
(
mods
);
git_config_file_free
(
mods
);
git_buf_free
(
&
key
);
git_buf_free
(
&
key
);
return
error
;
return
error
;
...
@@ -576,8 +643,8 @@ int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *ur
...
@@ -576,8 +643,8 @@ int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *ur
assert
(
url
);
assert
(
url
);
if
(
url
[
0
]
==
'.'
&&
(
url
[
1
]
==
'/'
||
(
url
[
1
]
==
'.'
&&
url
[
2
]
==
'/'
)
))
{
if
(
git_path_is_relative
(
url
))
{
if
(
!
(
error
=
lookup_head_remot
e
(
out
,
repo
)))
if
(
!
(
error
=
get_url_bas
e
(
out
,
repo
)))
error
=
git_path_apply_relative
(
out
,
url
);
error
=
git_path_apply_relative
(
out
,
url
);
}
else
if
(
strchr
(
url
,
':'
)
!=
NULL
||
url
[
0
]
==
'/'
)
{
}
else
if
(
strchr
(
url
,
':'
)
!=
NULL
||
url
[
0
]
==
'/'
)
{
error
=
git_buf_sets
(
out
,
url
);
error
=
git_buf_sets
(
out
,
url
);
...
@@ -715,46 +782,95 @@ git_submodule_recurse_t git_submodule_set_fetch_recurse_submodules(
...
@@ -715,46 +782,95 @@ git_submodule_recurse_t git_submodule_set_fetch_recurse_submodules(
return
old
;
return
old
;
}
}
int
git_submodule_init
(
git_submodule
*
s
ubmodule
,
int
overwrite
)
int
git_submodule_init
(
git_submodule
*
s
m
,
int
overwrite
)
{
{
int
error
;
int
error
;
const
char
*
val
;
const
char
*
val
;
git_buf
key
=
GIT_BUF_INIT
;
git_config
*
cfg
=
NULL
;
/* write "submodule.NAME.url" */
if
(
!
sm
->
url
)
{
if
(
!
submodule
->
url
)
{
giterr_set
(
GITERR_SUBMODULE
,
giterr_set
(
GITERR_SUBMODULE
,
"No URL configured for submodule '%s'"
,
s
ubmodule
->
name
);
"No URL configured for submodule '%s'"
,
s
m
->
name
);
return
-
1
;
return
-
1
;
}
}
error
=
submodule_update_config
(
if
((
error
=
git_repository_config
(
&
cfg
,
sm
->
repo
))
<
0
)
submodule
,
"url"
,
submodule
->
url
,
overwrite
!=
0
,
false
);
if
(
error
<
0
)
return
error
;
return
error
;
/* write "submodule.NAME.url" */
if
((
error
=
git_buf_printf
(
&
key
,
"submodule.%s.url"
,
sm
->
name
))
<
0
||
(
error
=
git_config__update_entry
(
cfg
,
key
.
ptr
,
sm
->
url
,
overwrite
!=
0
,
false
))
<
0
)
goto
cleanup
;
/* write "submodule.NAME.update" if not default */
/* write "submodule.NAME.update" if not default */
val
=
(
submodule
->
update
==
GIT_SUBMODULE_UPDATE_CHECKOUT
)
?
val
=
(
sm
->
update
==
GIT_SUBMODULE_UPDATE_CHECKOUT
)
?
NULL
:
git_submodule_update_to_str
(
submodule
->
update
);
NULL
:
git_submodule_update_to_str
(
sm
->
update
);
error
=
submodule_update_config
(
submodule
,
"update"
,
val
,
(
overwrite
!=
0
),
false
);
if
((
error
=
git_buf_printf
(
&
key
,
"submodule.%s.update"
,
sm
->
name
))
<
0
||
(
error
=
git_config__update_entry
(
cfg
,
key
.
ptr
,
val
,
overwrite
!=
0
,
false
))
<
0
)
goto
cleanup
;
/* success */
cleanup:
git_config_free
(
cfg
);
git_buf_free
(
&
key
);
return
error
;
return
error
;
}
}
int
git_submodule_sync
(
git_submodule
*
s
ubmodule
)
int
git_submodule_sync
(
git_submodule
*
s
m
)
{
{
if
(
!
submodule
->
url
)
{
int
error
=
0
;
git_config
*
cfg
=
NULL
;
git_buf
key
=
GIT_BUF_INIT
;
git_repository
*
smrepo
=
NULL
;
if
(
!
sm
->
url
)
{
giterr_set
(
GITERR_SUBMODULE
,
giterr_set
(
GITERR_SUBMODULE
,
"No URL configured for submodule '%s'"
,
s
ubmodule
->
name
);
"No URL configured for submodule '%s'"
,
s
m
->
name
);
return
-
1
;
return
-
1
;
}
}
/* copy URL over to config only if it already exists */
/* copy URL over to config only if it already exists */
return
submodule_update_config
(
if
(
!
(
error
=
git_repository_config__weakptr
(
&
cfg
,
sm
->
repo
))
&&
submodule
,
"url"
,
submodule
->
url
,
true
,
true
);
!
(
error
=
git_buf_printf
(
&
key
,
"submodule.%s.url"
,
sm
->
name
)))
error
=
git_config__update_entry
(
cfg
,
key
.
ptr
,
sm
->
url
,
true
,
true
);
/* if submodule exists in the working directory, update remote url */
if
(
!
error
&&
(
sm
->
flags
&
GIT_SUBMODULE_STATUS_IN_WD
)
!=
0
&&
!
(
error
=
git_submodule_open
(
&
smrepo
,
sm
)))
{
git_buf
remote_name
=
GIT_BUF_INIT
;
if
((
error
=
git_repository_config__weakptr
(
&
cfg
,
smrepo
))
<
0
)
/* return error from reading submodule config */
;
else
if
((
error
=
lookup_head_remote_key
(
&
remote_name
,
smrepo
))
<
0
)
{
giterr_clear
();
error
=
git_buf_sets
(
&
key
,
"branch.origin.remote"
);
}
else
{
error
=
git_buf_join3
(
&
key
,
'.'
,
"branch"
,
remote_name
.
ptr
,
"remote"
);
git_buf_free
(
&
remote_name
);
}
if
(
!
error
)
error
=
git_config__update_entry
(
cfg
,
key
.
ptr
,
sm
->
url
,
true
,
false
);
git_repository_free
(
smrepo
);
}
git_buf_free
(
&
key
);
return
error
;
}
}
static
int
git_submodule__open
(
static
int
git_submodule__open
(
...
@@ -821,64 +937,9 @@ int git_submodule_open(git_repository **subrepo, git_submodule *sm)
...
@@ -821,64 +937,9 @@ int git_submodule_open(git_repository **subrepo, git_submodule *sm)
return
git_submodule__open
(
subrepo
,
sm
,
false
);
return
git_submodule__open
(
subrepo
,
sm
,
false
);
}
}
static
void
submodule_cache_remove_item
(
git_strmap
*
cache
,
const
char
*
name
,
git_submodule
*
expected
,
bool
free_after_remove
)
{
khiter_t
pos
;
git_submodule
*
found
;
if
(
!
cache
)
return
;
pos
=
git_strmap_lookup_index
(
cache
,
name
);
if
(
!
git_strmap_valid_index
(
cache
,
pos
))
return
;
found
=
git_strmap_value_at
(
cache
,
pos
);
if
(
expected
&&
found
!=
expected
)
return
;
git_strmap_set_value_at
(
cache
,
pos
,
NULL
);
git_strmap_delete_at
(
cache
,
pos
);
if
(
free_after_remove
)
git_submodule_free
(
found
);
}
int
git_submodule_reload_all
(
git_repository
*
repo
,
int
force
)
int
git_submodule_reload_all
(
git_repository
*
repo
,
int
force
)
{
{
int
error
=
0
;
return
submodule_cache_init
(
repo
,
force
?
CACHE_FLUSH
:
CACHE_REFRESH
);
git_submodule
*
sm
;
GIT_UNUSED
(
force
);
assert
(
repo
);
if
(
repo
->
submodules
)
git_strmap_foreach_value
(
repo
->
submodules
,
sm
,
{
sm
->
flags
=
0
;
});
if
((
error
=
load_submodule_config
(
repo
,
true
))
<
0
)
return
error
;
git_strmap_foreach_value
(
repo
->
submodules
,
sm
,
{
git_strmap
*
cache
=
repo
->
submodules
;
if
(
sm
&&
(
sm
->
flags
&
GIT_SUBMODULE_STATUS__IN_FLAGS
)
==
0
)
{
/* we must check path != name before first remove, in case
* that call frees the submodule */
bool
free_as_path
=
(
sm
->
path
!=
sm
->
name
);
submodule_cache_remove_item
(
cache
,
sm
->
name
,
sm
,
true
);
if
(
free_as_path
)
submodule_cache_remove_item
(
cache
,
sm
->
path
,
sm
,
true
);
}
});
return
error
;
}
}
static
void
submodule_update_from_index_entry
(
static
void
submodule_update_from_index_entry
(
...
@@ -955,41 +1016,44 @@ static int submodule_update_head(git_submodule *submodule)
...
@@ -955,41 +1016,44 @@ static int submodule_update_head(git_submodule *submodule)
}
}
int
git_submodule_reload
(
git_submodule
*
s
ubmodule
,
int
force
)
int
git_submodule_reload
(
git_submodule
*
s
m
,
int
force
)
{
{
int
error
=
0
;
int
error
=
0
;
git_config_backend
*
mods
;
git_config_backend
*
mods
;
git_submodule_cache
*
cache
;
GIT_UNUSED
(
force
);
GIT_UNUSED
(
force
);
assert
(
submodule
);
assert
(
sm
);
cache
=
sm
->
repo
->
_submodules
;
/* refresh index data */
/* refresh index data */
if
((
error
=
submodule_update_index
(
s
ubmodule
))
<
0
)
if
((
error
=
submodule_update_index
(
s
m
))
<
0
)
return
error
;
return
error
;
/* refresh HEAD tree data */
/* refresh HEAD tree data */
if
((
error
=
submodule_update_head
(
s
ubmodule
))
<
0
)
if
((
error
=
submodule_update_head
(
s
m
))
<
0
)
return
error
;
return
error
;
/* done if bare */
/* done if bare */
if
(
git_repository_is_bare
(
s
ubmodule
->
repo
))
if
(
git_repository_is_bare
(
s
m
->
repo
))
return
error
;
return
error
;
/* refresh config data */
/* refresh config data */
mods
=
open_gitmodules
(
submodule
->
repo
,
false
,
NULL
);
mods
=
open_gitmodules
(
cache
,
GITMODULES_EXISTING
);
if
(
mods
!=
NULL
)
{
if
(
mods
!=
NULL
)
{
git_buf
path
=
GIT_BUF_INIT
;
git_buf
path
=
GIT_BUF_INIT
;
git_buf_sets
(
&
path
,
"submodule
\\
."
);
git_buf_sets
(
&
path
,
"submodule
\\
."
);
git_buf_text_puts_escape_regex
(
&
path
,
s
ubmodule
->
name
);
git_buf_text_puts_escape_regex
(
&
path
,
s
m
->
name
);
git_buf_puts
(
&
path
,
".*"
);
git_buf_puts
(
&
path
,
".*"
);
if
(
git_buf_oom
(
&
path
))
if
(
git_buf_oom
(
&
path
))
error
=
-
1
;
error
=
-
1
;
else
else
error
=
git_config_file_foreach_match
(
error
=
git_config_file_foreach_match
(
mods
,
path
.
ptr
,
submodule_load_from_config
,
submodule
->
repo
);
mods
,
path
.
ptr
,
submodule_load_from_config
,
cache
);
git_buf_free
(
&
path
);
git_buf_free
(
&
path
);
git_config_file_free
(
mods
);
git_config_file_free
(
mods
);
...
@@ -999,9 +1063,11 @@ int git_submodule_reload(git_submodule *submodule, int force)
...
@@ -999,9 +1063,11 @@ int git_submodule_reload(git_submodule *submodule, int force)
}
}
/* refresh wd data */
/* refresh wd data */
submodule
->
flags
&=
~
GIT_SUBMODULE_STATUS__ALL_WD_FLAGS
;
sm
->
flags
&=
~
(
GIT_SUBMODULE_STATUS_IN_WD
|
GIT_SUBMODULE_STATUS__WD_OID_VALID
|
GIT_SUBMODULE_STATUS__WD_FLAGS
);
return
submodule_load_from_wd_lite
(
s
ubmodule
);
return
submodule_load_from_wd_lite
(
s
m
);
}
}
static
void
submodule_copy_oid_maybe
(
static
void
submodule_copy_oid_maybe
(
...
@@ -1095,34 +1161,69 @@ int git_submodule_location(unsigned int *location, git_submodule *sm)
...
@@ -1095,34 +1161,69 @@ int git_submodule_location(unsigned int *location, git_submodule *sm)
* INTERNAL FUNCTIONS
* INTERNAL FUNCTIONS
*/
*/
static
git_submodule
*
submodule_alloc
(
git_repository
*
repo
,
const
char
*
name
)
static
int
submodule_alloc
(
git_submodule
**
out
,
git_submodule_cache
*
cache
,
const
char
*
name
)
{
{
size_t
namelen
;
size_t
namelen
;
git_submodule
*
sm
;
git_submodule
*
sm
;
if
(
!
name
||
!
(
namelen
=
strlen
(
name
)))
{
if
(
!
name
||
!
(
namelen
=
strlen
(
name
)))
{
giterr_set
(
GITERR_SUBMODULE
,
"Invalid submodule name"
);
giterr_set
(
GITERR_SUBMODULE
,
"Invalid submodule name"
);
return
NULL
;
return
-
1
;
}
}
sm
=
git__calloc
(
1
,
sizeof
(
git_submodule
));
sm
=
git__calloc
(
1
,
sizeof
(
git_submodule
));
if
(
sm
==
NULL
)
GITERR_CHECK_ALLOC
(
sm
);
return
NULL
;
sm
->
name
=
sm
->
path
=
git__strdup
(
name
);
sm
->
name
=
sm
->
path
=
git__strdup
(
name
);
if
(
!
sm
->
name
)
{
if
(
!
sm
->
name
)
{
git__free
(
sm
);
git__free
(
sm
);
return
NULL
;
return
-
1
;
}
}
GIT_REFCOUNT_INC
(
sm
);
GIT_REFCOUNT_INC
(
sm
);
sm
->
ignore
=
sm
->
ignore_default
=
GIT_SUBMODULE_IGNORE_NONE
;
sm
->
ignore
=
sm
->
ignore_default
=
GIT_SUBMODULE_IGNORE_NONE
;
sm
->
update
=
sm
->
update_default
=
GIT_SUBMODULE_UPDATE_CHECKOUT
;
sm
->
update
=
sm
->
update_default
=
GIT_SUBMODULE_UPDATE_CHECKOUT
;
sm
->
fetch_recurse
=
sm
->
fetch_recurse_default
=
GIT_SUBMODULE_RECURSE_NO
;
sm
->
fetch_recurse
=
sm
->
fetch_recurse_default
=
GIT_SUBMODULE_RECURSE_NO
;
sm
->
repo
=
repo
;
sm
->
repo
=
cache
->
repo
;
sm
->
branch
=
NULL
;
sm
->
branch
=
NULL
;
return
sm
;
*
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
)
static
void
submodule_release
(
git_submodule
*
sm
)
...
@@ -1131,10 +1232,9 @@ static void submodule_release(git_submodule *sm)
...
@@ -1131,10 +1232,9 @@ static void submodule_release(git_submodule *sm)
return
;
return
;
if
(
sm
->
repo
)
{
if
(
sm
->
repo
)
{
git_strmap
*
cache
=
sm
->
repo
->
submodules
;
git_submodule_cache
*
cache
=
sm
->
repo
->
_submodules
;
submodule_cache_remove_item
(
cache
,
sm
->
name
,
sm
,
false
);
sm
->
repo
=
NULL
;
if
(
sm
->
path
!=
sm
->
name
)
submodule_cache_remove_item
(
cache
,
sm
,
false
);
submodule_cache_remove_item
(
cache
,
sm
->
path
,
sm
,
false
);
}
}
if
(
sm
->
path
!=
sm
->
name
)
if
(
sm
->
path
!=
sm
->
name
)
...
@@ -1155,40 +1255,39 @@ void git_submodule_free(git_submodule *sm)
...
@@ -1155,40 +1255,39 @@ void git_submodule_free(git_submodule *sm)
static
int
submodule_get
(
static
int
submodule_get
(
git_submodule
**
out
,
git_submodule
**
out
,
git_
repository
*
repo
,
git_
submodule_cache
*
cache
,
const
char
*
name
,
const
char
*
name
,
const
char
*
alternate
)
const
char
*
alternate
)
{
{
int
error
=
0
;
int
error
=
0
;
git_strmap
*
smcfg
=
repo
->
submodules
;
khiter_t
pos
;
khiter_t
pos
;
git_submodule
*
sm
;
git_submodule
*
sm
;
pos
=
git_strmap_lookup_index
(
smcfg
,
name
);
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
name
);
if
(
!
git_strmap_valid_index
(
smcfg
,
pos
)
&&
alternate
)
if
(
!
git_strmap_valid_index
(
cache
->
submodules
,
pos
)
&&
alternate
)
pos
=
git_strmap_lookup_index
(
smcfg
,
alternate
);
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
alternate
);
if
(
!
git_strmap_valid_index
(
smcfg
,
pos
))
{
if
(
!
git_strmap_valid_index
(
cache
->
submodules
,
pos
))
{
sm
=
submodule_alloc
(
repo
,
name
);
if
((
error
=
submodule_alloc
(
&
sm
,
cache
,
name
))
<
0
)
GITERR_CHECK_ALLOC
(
sm
)
;
return
error
;
/* insert value at name - if another thread beats us to it, then use
/* insert value at name - if another thread beats us to it, then use
* their record and release our own.
* their record and release our own.
*/
*/
pos
=
kh_put
(
str
,
smcfg
,
sm
->
name
,
&
error
);
pos
=
kh_put
(
str
,
cache
->
submodules
,
sm
->
name
,
&
error
);
if
(
error
<
0
)
if
(
error
<
0
)
goto
done
;
goto
done
;
else
if
(
error
==
0
)
{
else
if
(
error
==
0
)
{
git_submodule_free
(
sm
);
git_submodule_free
(
sm
);
sm
=
git_strmap_value_at
(
smcfg
,
pos
);
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
}
else
{
}
else
{
error
=
0
;
error
=
0
;
git_strmap_set_value_at
(
smcfg
,
pos
,
sm
);
git_strmap_set_value_at
(
cache
->
submodules
,
pos
,
sm
);
}
}
}
else
{
}
else
{
sm
=
git_strmap_value_at
(
smcfg
,
pos
);
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
}
}
done:
done:
...
@@ -1254,10 +1353,10 @@ int git_submodule_parse_recurse(git_submodule_recurse_t *out, const char *value)
...
@@ -1254,10 +1353,10 @@ int git_submodule_parse_recurse(git_submodule_recurse_t *out, const char *value)
static
int
submodule_load_from_config
(
static
int
submodule_load_from_config
(
const
git_config_entry
*
entry
,
void
*
payload
)
const
git_config_entry
*
entry
,
void
*
payload
)
{
{
git_repository
*
repo
=
payload
;
git_submodule_cache
*
cache
=
payload
;
git_strmap
*
smcfg
=
repo
->
submodules
;
const
char
*
namestart
,
*
property
;
const
char
*
namestart
,
*
property
,
*
alternate
=
NULL
;
const
char
*
key
=
entry
->
name
,
*
value
=
entry
->
value
,
*
path
;
const
char
*
key
=
entry
->
name
,
*
value
=
entry
->
value
,
*
path
;
char
*
alternate
=
NULL
,
*
replaced
=
NULL
;
git_buf
name
=
GIT_BUF_INIT
;
git_buf
name
=
GIT_BUF_INIT
;
git_submodule
*
sm
=
NULL
;
git_submodule
*
sm
=
NULL
;
int
error
=
0
;
int
error
=
0
;
...
@@ -1275,7 +1374,7 @@ static int submodule_load_from_config(
...
@@ -1275,7 +1374,7 @@ static int submodule_load_from_config(
path
=
!
strcasecmp
(
property
,
"path"
)
?
value
:
NULL
;
path
=
!
strcasecmp
(
property
,
"path"
)
?
value
:
NULL
;
if
((
error
=
git_buf_set
(
&
name
,
namestart
,
property
-
namestart
-
1
))
<
0
||
if
((
error
=
git_buf_set
(
&
name
,
namestart
,
property
-
namestart
-
1
))
<
0
||
(
error
=
submodule_get
(
&
sm
,
repo
,
name
.
ptr
,
path
))
<
0
)
(
error
=
submodule_get
(
&
sm
,
cache
,
name
.
ptr
,
path
))
<
0
)
goto
done
;
goto
done
;
sm
->
flags
|=
GIT_SUBMODULE_STATUS_IN_CONFIG
;
sm
->
flags
|=
GIT_SUBMODULE_STATUS_IN_CONFIG
;
...
@@ -1288,20 +1387,42 @@ static int submodule_load_from_config(
...
@@ -1288,20 +1387,42 @@ static int submodule_load_from_config(
* should be strcasecmp
* should be strcasecmp
*/
*/
if
(
strcmp
(
sm
->
name
,
name
.
ptr
)
!=
0
)
{
if
(
strcmp
(
sm
->
name
,
name
.
ptr
)
!=
0
)
{
/* name changed */
alternate
=
sm
->
name
=
git_buf_detach
(
&
name
);
if
(
!
strcmp
(
sm
->
path
,
name
.
ptr
))
{
/* already set as path */
}
else
if
(
path
&&
strcmp
(
path
,
sm
->
path
)
!=
0
)
{
replaced
=
sm
->
name
;
alternate
=
sm
->
path
=
git__strdup
(
value
);
sm
->
name
=
sm
->
path
;
if
(
!
sm
->
path
)
{
}
else
{
error
=
-
1
;
if
(
sm
->
name
!=
sm
->
path
)
goto
done
;
replaced
=
sm
->
name
;
alternate
=
sm
->
name
=
git_buf_detach
(
&
name
);
}
}
else
if
(
path
&&
strcmp
(
path
,
sm
->
path
)
!=
0
)
{
/* path changed */
if
(
!
strcmp
(
sm
->
name
,
value
))
{
/* already set as name */
replaced
=
sm
->
path
;
sm
->
path
=
sm
->
name
;
}
else
{
if
(
sm
->
path
!=
sm
->
name
)
replaced
=
sm
->
path
;
if
((
alternate
=
git__strdup
(
value
))
==
NULL
)
{
error
=
-
1
;
goto
done
;
}
sm
->
path
=
alternate
;
}
}
}
}
/* Found a alternate key for the submodule */
/* Deregister under name being replaced */
if
(
replaced
)
{
git_strmap_delete
(
cache
->
submodules
,
replaced
);
git_submodule_free
(
sm
);
git__free
(
replaced
);
}
/* Insert under alternate key */
if
(
alternate
)
{
if
(
alternate
)
{
void
*
old_sm
=
NULL
;
void
*
old_sm
=
NULL
;
git_strmap_insert2
(
smcfg
,
alternate
,
sm
,
old_sm
,
error
);
git_strmap_insert2
(
cache
->
submodules
,
alternate
,
sm
,
old_sm
,
error
);
if
(
error
<
0
)
if
(
error
<
0
)
goto
done
;
goto
done
;
...
@@ -1383,36 +1504,33 @@ static int submodule_load_from_wd_lite(git_submodule *sm)
...
@@ -1383,36 +1504,33 @@ static int submodule_load_from_wd_lite(git_submodule *sm)
return
0
;
return
0
;
}
}
static
int
load_submodule_config
_from_index
(
static
int
submodule_cache_refresh
_from_index
(
git_
repository
*
repo
,
git_oid
*
gitmodules_oid
)
git_
submodule_cache
*
cache
,
git_index
*
idx
)
{
{
int
error
;
int
error
;
git_index
*
index
;
git_iterator
*
i
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
const
git_index_entry
*
entry
;
if
((
error
=
git_repository_index__weakptr
(
&
index
,
repo
))
<
0
||
if
((
error
=
git_iterator_for_index
(
&
i
,
idx
,
0
,
NULL
,
NULL
))
<
0
)
(
error
=
git_iterator_for_index
(
&
i
,
index
,
0
,
NULL
,
NULL
))
<
0
)
return
error
;
return
error
;
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
khiter_t
pos
=
git_strmap_lookup_index
(
repo
->
submodules
,
entry
->
path
);
khiter_t
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
entry
->
path
);
git_submodule
*
sm
;
git_submodule
*
sm
;
if
(
git_strmap_valid_index
(
repo
->
submodules
,
pos
))
{
if
(
git_strmap_valid_index
(
cache
->
submodules
,
pos
))
{
sm
=
git_strmap_value_at
(
repo
->
submodules
,
pos
);
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
if
(
S_ISGITLINK
(
entry
->
mode
))
if
(
S_ISGITLINK
(
entry
->
mode
))
submodule_update_from_index_entry
(
sm
,
entry
);
submodule_update_from_index_entry
(
sm
,
entry
);
else
else
sm
->
flags
|=
GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
sm
->
flags
|=
GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE
;
}
else
if
(
S_ISGITLINK
(
entry
->
mode
))
{
}
else
if
(
S_ISGITLINK
(
entry
->
mode
))
{
if
(
!
submodule_get
(
&
sm
,
repo
,
entry
->
path
,
NULL
))
{
if
(
!
submodule_get
(
&
sm
,
cache
,
entry
->
path
,
NULL
))
{
submodule_update_from_index_entry
(
sm
,
entry
);
submodule_update_from_index_entry
(
sm
,
entry
);
git_submodule_free
(
sm
);
git_submodule_free
(
sm
);
}
}
}
else
if
(
strcmp
(
entry
->
path
,
GIT_MODULES_FILE
)
==
0
)
}
git_oid_cpy
(
gitmodules_oid
,
&
entry
->
id
);
}
}
if
(
error
==
GIT_ITEROVER
)
if
(
error
==
GIT_ITEROVER
)
...
@@ -1423,46 +1541,33 @@ static int load_submodule_config_from_index(
...
@@ -1423,46 +1541,33 @@ static int load_submodule_config_from_index(
return
error
;
return
error
;
}
}
static
int
load_submodule_config
_from_head
(
static
int
submodule_cache_refresh
_from_head
(
git_
repository
*
repo
,
git_oid
*
gitmodules_oi
d
)
git_
submodule_cache
*
cache
,
git_tree
*
hea
d
)
{
{
int
error
;
int
error
;
git_tree
*
head
;
git_iterator
*
i
;
git_iterator
*
i
;
const
git_index_entry
*
entry
;
const
git_index_entry
*
entry
;
/* if we can't look up current head, then there's no submodule in it */
if
((
error
=
git_iterator_for_tree
(
&
i
,
head
,
0
,
NULL
,
NULL
))
<
0
)
if
(
git_repository_head_tree
(
&
head
,
repo
)
<
0
)
{
giterr_clear
();
return
0
;
}
if
((
error
=
git_iterator_for_tree
(
&
i
,
head
,
0
,
NULL
,
NULL
))
<
0
)
{
git_tree_free
(
head
);
return
error
;
return
error
;
}
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
while
(
!
(
error
=
git_iterator_advance
(
&
entry
,
i
)))
{
khiter_t
pos
=
git_strmap_lookup_index
(
repo
->
submodules
,
entry
->
path
);
khiter_t
pos
=
git_strmap_lookup_index
(
cache
->
submodules
,
entry
->
path
);
git_submodule
*
sm
;
git_submodule
*
sm
;
if
(
git_strmap_valid_index
(
repo
->
submodules
,
pos
))
{
if
(
git_strmap_valid_index
(
cache
->
submodules
,
pos
))
{
sm
=
git_strmap_value_at
(
repo
->
submodules
,
pos
);
sm
=
git_strmap_value_at
(
cache
->
submodules
,
pos
);
if
(
S_ISGITLINK
(
entry
->
mode
))
if
(
S_ISGITLINK
(
entry
->
mode
))
submodule_update_from_head_data
(
submodule_update_from_head_data
(
sm
,
entry
->
mode
,
&
entry
->
id
);
sm
,
entry
->
mode
,
&
entry
->
id
);
else
else
sm
->
flags
|=
GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
sm
->
flags
|=
GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE
;
}
else
if
(
S_ISGITLINK
(
entry
->
mode
))
{
}
else
if
(
S_ISGITLINK
(
entry
->
mode
))
{
if
(
!
submodule_get
(
&
sm
,
repo
,
entry
->
path
,
NULL
))
{
if
(
!
submodule_get
(
&
sm
,
cache
,
entry
->
path
,
NULL
))
{
submodule_update_from_head_data
(
submodule_update_from_head_data
(
sm
,
entry
->
mode
,
&
entry
->
id
);
sm
,
entry
->
mode
,
&
entry
->
id
);
git_submodule_free
(
sm
);
git_submodule_free
(
sm
);
}
}
}
else
if
(
strcmp
(
entry
->
path
,
GIT_MODULES_FILE
)
==
0
&&
git_oid_iszero
(
gitmodules_oid
))
{
git_oid_cpy
(
gitmodules_oid
,
&
entry
->
id
);
}
}
}
}
...
@@ -1470,17 +1575,15 @@ static int load_submodule_config_from_head(
...
@@ -1470,17 +1575,15 @@ static int load_submodule_config_from_head(
error
=
0
;
error
=
0
;
git_iterator_free
(
i
);
git_iterator_free
(
i
);
git_tree_free
(
head
);
return
error
;
return
error
;
}
}
static
git_config_backend
*
open_gitmodules
(
static
git_config_backend
*
open_gitmodules
(
git_repository
*
repo
,
git_submodule_cache
*
cache
,
bool
okay_to_create
,
int
okay_to_create
)
const
git_oid
*
gitmodules_oid
)
{
{
const
char
*
workdir
=
git_repository_workdir
(
repo
);
const
char
*
workdir
=
git_repository_workdir
(
cache
->
repo
);
git_buf
path
=
GIT_BUF_INIT
;
git_buf
path
=
GIT_BUF_INIT
;
git_config_backend
*
mods
=
NULL
;
git_config_backend
*
mods
=
NULL
;
...
@@ -1500,186 +1603,281 @@ static git_config_backend *open_gitmodules(
...
@@ -1500,186 +1603,281 @@ static git_config_backend *open_gitmodules(
}
}
}
}
if
(
!
mods
&&
gitmodules_oid
&&
!
git_oid_iszero
(
gitmodules_oid
))
{
git_buf_free
(
&
path
);
/* TODO: Retrieve .gitmodules content from ODB */
/* Should we actually do this? Core git does not, but it means you
return
mods
;
* can't really get much information about submodules on bare repos.
}
*/
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
;
}
}
git_buf_free
(
&
path
);
cache
->
submodules
=
git_strmap_alloc
();
if
(
!
cache
->
submodules
)
{
submodule_cache_free
(
cache
);
return
-
1
;
}
return
mods
;
cache
->
repo
=
repo
;
git_buf_init
(
&
cache
->
gitmodules_path
,
0
);
*
out
=
cache
;
return
0
;
}
}
static
int
load_submodule_config
(
git_repository
*
repo
,
bool
reload
)
static
int
submodule_cache_refresh
(
git_submodule_cache
*
cache
,
int
refresh
)
{
{
int
error
;
int
error
=
0
,
update_index
,
update_head
,
update_gitmod
;
git_oid
gitmodules_oid
;
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
;
git_config_backend
*
mods
=
NULL
;
uint32_t
mask
;
if
(
!
reload
&&
repo
->
submodules
)
if
(
!
cache
||
!
cache
->
repo
||
!
refresh
)
return
0
;
return
0
;
memset
(
&
gitmodules_oid
,
0
,
sizeof
(
gitmodules_oid
));
if
(
git_mutex_lock
(
&
cache
->
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"Unable to acquire lock on submodule cache"
);
/* Submodule data is kept in a hashtable keyed by both name and path.
return
-
1
;
* These are usually the same, but that is not guaranteed.
*/
if
(
!
repo
->
submodules
)
{
repo
->
submodules
=
git_strmap_alloc
();
GITERR_CHECK_ALLOC
(
repo
->
submodules
);
}
}
/*
TODO: only do the following if the sources appear modified
*/
/*
get sources that we will need to check
*/
/* add submodule information from index */
if
(
git_repository_index
(
&
idx
,
cache
->
repo
)
<
0
)
giterr_clear
();
if
(
git_repository_head_tree
(
&
head
,
cache
->
repo
)
<
0
)
giterr_clear
();
if
((
error
=
load_submodule_config_from_index
(
repo
,
&
gitmodules_oid
))
<
0
)
wd
=
git_repository_workdir
(
cache
->
repo
);
if
(
wd
&&
(
error
=
git_buf_joinpath
(
&
path
,
wd
,
GIT_MODULES_FILE
))
<
0
)
goto
cleanup
;
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_stamp
);
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
);
if
(
update_gitmod
<
0
)
giterr_clear
();
}
/* 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_futils_filestamp_set
(
&
cache
->
index_stamp
,
git_index__filestamp
(
idx
));
}
/* add submodule information from HEAD */
/* add submodule information from HEAD */
if
((
error
=
load_submodule_config_from_head
(
repo
,
&
gitmodules_oid
))
<
0
)
if
(
head
&&
update_head
)
{
goto
cleanup
;
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 */
/* add submodule information from .gitmodules */
if
((
mods
=
open_gitmodules
(
repo
,
false
,
&
gitmodules_oid
))
!=
NULL
&&
if
(
wd
&&
update_gitmod
>
0
)
{
(
error
=
git_config_file_foreach
(
if
((
mods
=
open_gitmodules
(
cache
,
false
))
!=
NULL
&&
mods
,
submodule_load_from_config
,
repo
))
<
0
)
(
error
=
git_config_file_foreach
(
goto
cleanup
;
mods
,
submodule_load_from_config
,
cache
))
<
0
)
goto
cleanup
;
}
/* shallow scan submodules in work tree */
/* shallow scan submodules in work tree
as needed
*/
if
(
!
git_repository_is_bare
(
repo
))
{
if
(
wd
&&
mask
!=
0
)
{
git_submodule
*
sm
;
git_strmap_foreach_value
(
cache
->
submodules
,
sm
,
{
git_strmap_foreach_value
(
repo
->
submodules
,
sm
,
{
sm
->
flags
&=
~
GIT_SUBMODULE_STATUS__ALL_WD_FLAGS
;
});
git_strmap_foreach_value
(
repo
->
submodules
,
sm
,
{
submodule_load_from_wd_lite
(
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:
cleanup:
if
(
mods
!=
NULL
)
git_config_file_free
(
mods
);
git_config_file_free
(
mods
);
/* TODO: if we got an error, mark submodule config as invalid? */
if
(
error
)
git_mutex_unlock
(
&
cache
->
lock
);
git_submodule_config_free
(
repo
);
git_index_free
(
idx
);
git_tree_free
(
head
);
git_buf_free
(
&
path
);
return
error
;
return
error
;
}
}
static
int
lookup_head_remote
(
git_buf
*
url
,
git_repository
*
repo
)
static
int
submodule_cache_init
(
git_repository
*
repo
,
int
cache_refresh
)
{
{
int
error
;
int
error
=
0
;
git_config
*
cfg
;
git_submodule_cache
*
cache
=
NULL
;
git_reference
*
head
=
NULL
,
*
remote
=
NULL
;
const
char
*
tgt
,
*
scan
;
git_buf
key
=
GIT_BUF_INIT
;
/* 1. resolve HEAD -> refs/heads/BRANCH
/* if submodules already exist, just refresh as requested */
* 2. lookup config branch.BRANCH.remote -> ORIGIN
if
(
repo
->
_submodules
)
* 3. lookup remote.ORIGIN.url
return
submodule_cache_refresh
(
repo
->
_submodules
,
cache_refresh
);
*/
if
((
error
=
git_repository_config__weakptr
(
&
cfg
,
repo
))
<
0
)
/* otherwise create a new cache, load it, and atomically swap it in */
return
error
;
if
(
!
(
error
=
submodule_cache_alloc
(
&
cache
,
repo
))
&&
!
(
error
=
submodule_cache_refresh
(
cache
,
CACHE_FLUSH
)))
cache
=
git__compare_and_swap
(
&
repo
->
_submodules
,
NULL
,
cache
);
if
(
git_reference_lookup
(
&
head
,
repo
,
GIT_HEAD_FILE
)
<
0
)
{
/* might have raced with another thread to set cache, so free if needed */
giterr_set
(
GITERR_SUBMODULE
,
if
(
cache
)
"Cannot resolve relative URL when HEAD cannot be resolved"
);
submodule_cache_free
(
cache
);
error
=
GIT_ENOTFOUND
;
goto
cleanup
;
}
if
(
git_reference_type
(
head
)
!=
GIT_REF_SYMBOLIC
)
{
return
error
;
giterr_set
(
GITERR_SUBMODULE
,
}
"Cannot resolve relative URL when HEAD is not symbolic"
);
error
=
GIT_ENOTFOUND
;
goto
cleanup
;
}
if
((
error
=
git_branch_upstream
(
&
remote
,
head
))
<
0
)
/* Lookup name of remote of the local tracking branch HEAD points to */
goto
cleanup
;
static
int
lookup_head_remote_key
(
git_buf
*
remote_name
,
git_repository
*
repo
)
{
int
error
;
git_reference
*
head
=
NULL
;
git_buf
upstream_name
=
GIT_BUF_INIT
;
/* remote should refer to something like refs/remotes/ORIGIN/BRANCH */
/* lookup and dereference HEAD */
if
((
error
=
git_repository_head
(
&
head
,
repo
))
<
0
)
return
error
;
if
(
git_reference_type
(
remote
)
!=
GIT_REF_SYMBOLIC
||
/* lookup remote tracking branch of HEAD */
git__prefixcmp
(
git_reference_symbolic_target
(
remote
),
GIT_REFS_REMOTES_DIR
)
!=
0
)
if
(
!
(
error
=
git_branch_upstream_name
(
&
upstream_name
,
repo
,
git_reference_name
(
head
))))
{
{
giterr_set
(
GITERR_SUBMODULE
,
/* lookup remote of remote tracking branch */
"Cannot resolve relative URL when HEAD is not symbolic"
);
error
=
git_branch_remote_name
(
remote_name
,
repo
,
upstream_name
.
ptr
);
error
=
GIT_ENOTFOUND
;
g
oto
cleanup
;
g
it_buf_free
(
&
upstream_name
)
;
}
}
scan
=
tgt
=
git_reference_symbolic_target
(
remote
)
+
strlen
(
GIT_REFS_REMOTES_DIR
);
git_reference_free
(
head
);
while
(
*
scan
&&
(
*
scan
!=
'/'
||
(
scan
>
tgt
&&
scan
[
-
1
]
!=
'\\'
)))
scan
++
;
/* find non-escaped slash to end ORIGIN name */
error
=
git_buf_printf
(
&
key
,
"remote.%.*s.url"
,
(
int
)(
scan
-
tgt
),
tgt
);
return
error
;
if
(
error
<
0
)
}
goto
cleanup
;
if
((
error
=
git_config_get_string
(
&
tgt
,
cfg
,
key
.
ptr
))
<
0
)
/* Lookup the remote of the local tracking branch HEAD points to */
goto
cleanup
;
static
int
lookup_head_remote
(
git_remote
**
remote
,
git_repository
*
repo
)
{
int
error
;
git_buf
remote_name
=
GIT_BUF_INIT
;
error
=
git_buf_sets
(
url
,
tgt
);
/* lookup remote of remote tracking branch name */
if
(
!
(
error
=
lookup_head_remote_key
(
&
remote_name
,
repo
)))
error
=
git_remote_load
(
remote
,
repo
,
remote_name
.
ptr
);
cleanup:
git_buf_free
(
&
remote_name
);
git_buf_free
(
&
key
);
git_reference_free
(
head
);
git_reference_free
(
remote
);
return
error
;
return
error
;
}
}
static
int
submodule_update_config
(
/* Lookup remote, either from HEAD or fall back on origin */
git_submodule
*
submodule
,
static
int
lookup_default_remote
(
git_remote
**
remote
,
git_repository
*
repo
)
const
char
*
attr
,
const
char
*
value
,
bool
overwrite
,
bool
only_existing
)
{
{
int
error
;
int
error
=
lookup_head_remote
(
remote
,
repo
);
git_config
*
config
;
git_buf
key
=
GIT_BUF_INIT
;
const
git_config_entry
*
ce
=
NULL
;
assert
(
submodule
);
/* if that failed, use 'origin' instead */
if
(
error
==
GIT_ENOTFOUND
)
error
=
git_remote_load
(
remote
,
repo
,
"origin"
);
error
=
git_repository_config__weakptr
(
&
config
,
submodule
->
repo
);
if
(
error
==
GIT_ENOTFOUND
)
if
(
error
<
0
)
giterr_set
(
return
error
;
GITERR_SUBMODULE
,
"Cannot get default remote for submodule - no local tracking "
"branch for HEAD and origin does not exist"
);
error
=
git_buf_printf
(
&
key
,
"submodule.%s.%s"
,
submodule
->
name
,
attr
);
return
error
;
if
(
error
<
0
)
}
goto
cleanup
;
if
((
error
=
git_config__lookup_entry
(
&
ce
,
config
,
key
.
ptr
,
false
))
<
0
)
goto
cleanup
;
if
(
!
ce
&&
only_existing
)
static
int
get_url_base
(
git_buf
*
url
,
git_repository
*
repo
)
goto
cleanup
;
{
if
(
ce
&&
!
overwrite
)
int
error
;
goto
cleanup
;
git_remote
*
remote
=
NULL
;
if
(
value
&&
ce
&&
ce
->
value
&&
!
strcmp
(
ce
->
value
,
value
))
goto
cleanup
;
if
(
!
value
&&
(
!
ce
||
!
ce
->
value
))
goto
cleanup
;
if
(
!
value
)
if
(
!
(
error
=
lookup_default_remote
(
&
remote
,
repo
)))
{
error
=
git_config_delete_entry
(
config
,
key
.
ptr
);
error
=
git_buf_sets
(
url
,
git_remote_url
(
remote
));
else
git_remote_free
(
remote
);
error
=
git_config_set_string
(
config
,
key
.
ptr
,
value
);
}
else
if
(
error
==
GIT_ENOTFOUND
)
{
/* if repository does not have a default remote, use workdir instead */
giterr_clear
();
error
=
git_buf_sets
(
url
,
git_repository_workdir
(
repo
));
}
cleanup:
git_buf_free
(
&
key
);
return
error
;
return
error
;
}
}
...
...
src/submodule.h
View file @
923c8400
...
@@ -99,6 +99,29 @@ struct git_submodule {
...
@@ -99,6 +99,29 @@ struct git_submodule {
git_oid
wd_oid
;
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_futils_filestamp
index_stamp
;
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
);
/* Release all submodules */
extern
void
git_submodule_cache_free
(
git_repository
*
repo
);
/* Additional flags on top of public GIT_SUBMODULE_STATUS values */
/* Additional flags on top of public GIT_SUBMODULE_STATUS values */
enum
{
enum
{
GIT_SUBMODULE_STATUS__WD_SCANNED
=
(
1u
<<
20
),
GIT_SUBMODULE_STATUS__WD_SCANNED
=
(
1u
<<
20
),
...
@@ -111,17 +134,16 @@ enum {
...
@@ -111,17 +134,16 @@ enum {
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
=
(
1u
<<
27
),
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES
=
(
1u
<<
27
),
};
};
#define GIT_SUBMODULE_STATUS__ALL_WD_FLAGS \
(GIT_SUBMODULE_STATUS_IN_WD | \
GIT_SUBMODULE_STATUS__WD_OID_VALID | \
GIT_SUBMODULE_STATUS__WD_FLAGS)
#define GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(S) \
#define GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(S) \
((S) & ~(0xFFFFFFFFu << 20))
((S) & ~(0xFFFFFFFFu << 20))
/* Internal submodule check does not attempt to refresh cached data */
/* Internal submodule check does not attempt to refresh cached data */
extern
bool
git_submodule__is_submodule
(
git_repository
*
repo
,
const
char
*
name
);
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
);
/* Internal status fn returns status and optionally the various OIDs */
/* Internal status fn returns status and optionally the various OIDs */
extern
int
git_submodule__status
(
extern
int
git_submodule__status
(
unsigned
int
*
out_status
,
unsigned
int
*
out_status
,
...
@@ -143,5 +165,6 @@ extern int git_submodule_parse_update(
...
@@ -143,5 +165,6 @@ extern int git_submodule_parse_update(
extern
const
char
*
git_submodule_ignore_to_str
(
git_submodule_ignore_t
);
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_update_to_str
(
git_submodule_update_t
);
extern
const
char
*
git_submodule_recurse_to_str
(
git_submodule_recurse_t
);
#endif
#endif
src/vector.c
View file @
923c8400
...
@@ -54,7 +54,7 @@ int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp)
...
@@ -54,7 +54,7 @@ int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp)
bytes
=
src
->
length
*
sizeof
(
void
*
);
bytes
=
src
->
length
*
sizeof
(
void
*
);
v
->
_alloc_size
=
src
->
length
;
v
->
_alloc_size
=
src
->
length
;
v
->
_cmp
=
cmp
;
v
->
_cmp
=
cmp
?
cmp
:
src
->
_cmp
;
v
->
length
=
src
->
length
;
v
->
length
=
src
->
length
;
v
->
flags
=
src
->
flags
;
v
->
flags
=
src
->
flags
;
if
(
cmp
!=
src
->
_cmp
)
if
(
cmp
!=
src
->
_cmp
)
...
...
tests/core/buffer.c
View file @
923c8400
...
@@ -599,6 +599,38 @@ void test_core_buffer__10(void)
...
@@ -599,6 +599,38 @@ void test_core_buffer__10(void)
git_buf_free
(
&
a
);
git_buf_free
(
&
a
);
}
}
void
test_core_buffer__join3
(
void
)
{
git_buf
a
=
GIT_BUF_INIT
;
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
"test"
,
"string"
,
"join"
));
cl_assert_equal_s
(
"test/string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
"test/"
,
"string"
,
"join"
));
cl_assert_equal_s
(
"test/string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
"test/"
,
"/string"
,
"join"
));
cl_assert_equal_s
(
"test/string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
"test/"
,
"/string/"
,
"join"
));
cl_assert_equal_s
(
"test/string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
"test/"
,
"/string/"
,
"/join"
));
cl_assert_equal_s
(
"test/string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
""
,
"string"
,
"join"
));
cl_assert_equal_s
(
"string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
""
,
"string/"
,
"join"
));
cl_assert_equal_s
(
"string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
""
,
"string/"
,
"/join"
));
cl_assert_equal_s
(
"string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
"string"
,
""
,
"join"
));
cl_assert_equal_s
(
"string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
"string/"
,
""
,
"join"
));
cl_assert_equal_s
(
"string/join"
,
a
.
ptr
);
cl_git_pass
(
git_buf_join3
(
&
a
,
'/'
,
"string/"
,
""
,
"/join"
));
cl_assert_equal_s
(
"string/join"
,
a
.
ptr
);
git_buf_free
(
&
a
);
}
void
test_core_buffer__11
(
void
)
void
test_core_buffer__11
(
void
)
{
{
git_buf
a
=
GIT_BUF_INIT
;
git_buf
a
=
GIT_BUF_INIT
;
...
...
tests/diff/submodules.c
View file @
923c8400
...
@@ -131,8 +131,6 @@ void test_diff_submodules__dirty_submodule_2(void)
...
@@ -131,8 +131,6 @@ void test_diff_submodules__dirty_submodule_2(void)
g_repo
=
setup_fixture_submodules
();
g_repo
=
setup_fixture_submodules
();
cl_git_pass
(
git_submodule_reload_all
(
g_repo
,
1
));
opts
.
flags
=
GIT_DIFF_INCLUDE_UNTRACKED
|
opts
.
flags
=
GIT_DIFF_INCLUDE_UNTRACKED
|
GIT_DIFF_SHOW_UNTRACKED_CONTENT
|
GIT_DIFF_SHOW_UNTRACKED_CONTENT
|
GIT_DIFF_RECURSE_UNTRACKED_DIRS
|
GIT_DIFF_RECURSE_UNTRACKED_DIRS
|
...
@@ -165,8 +163,6 @@ void test_diff_submodules__dirty_submodule_2(void)
...
@@ -165,8 +163,6 @@ void test_diff_submodules__dirty_submodule_2(void)
git_diff_free
(
diff
);
git_diff_free
(
diff
);
cl_git_pass
(
git_submodule_reload_all
(
g_repo
,
1
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
check_diff_patches
(
diff
,
expected_dirty
);
check_diff_patches
(
diff
,
expected_dirty
);
git_diff_free
(
diff
);
git_diff_free
(
diff
);
...
@@ -299,7 +295,6 @@ void test_diff_submodules__invalid_cache(void)
...
@@ -299,7 +295,6 @@ void test_diff_submodules__invalid_cache(void)
git_submodule_free
(
sm
);
git_submodule_free
(
sm
);
cl_git_pass
(
git_submodule_reload_all
(
g_repo
,
1
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
smpath
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
g_repo
,
smpath
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
cl_git_pass
(
git_diff_index_to_workdir
(
&
diff
,
g_repo
,
NULL
,
&
opts
));
...
...
tests/submodule/add.c
0 → 100644
View file @
923c8400
#include "clar_libgit2.h"
#include "posix.h"
#include "path.h"
#include "submodule_helpers.h"
static
git_repository
*
g_repo
=
NULL
;
void
test_submodule_add__cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
}
static
void
assert_submodule_url
(
const
char
*
name
,
const
char
*
url
)
{
git_config
*
cfg
;
const
char
*
s
;
git_buf
key
=
GIT_BUF_INIT
;
cl_git_pass
(
git_repository_config
(
&
cfg
,
g_repo
));
cl_git_pass
(
git_buf_printf
(
&
key
,
"submodule.%s.url"
,
name
));
cl_git_pass
(
git_config_get_string
(
&
s
,
cfg
,
git_buf_cstr
(
&
key
)));
cl_assert_equal_s
(
s
,
url
);
git_config_free
(
cfg
);
git_buf_free
(
&
key
);
}
void
test_submodule_add__url_absolute
(
void
)
{
git_submodule
*
sm
;
g_repo
=
setup_fixture_submod2
();
/* re-add existing submodule */
cl_git_fail_with
(
GIT_EEXISTS
,
git_submodule_add_setup
(
NULL
,
g_repo
,
"whatever"
,
"sm_unchanged"
,
1
));
/* add a submodule using a gitlink */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"https://github.com/libgit2/libgit2.git"
,
"sm_libgit2"
,
1
)
);
git_submodule_free
(
sm
);
cl_assert
(
git_path_isfile
(
"submod2/"
"sm_libgit2"
"/.git"
));
cl_assert
(
git_path_isdir
(
"submod2/.git/modules"
));
cl_assert
(
git_path_isdir
(
"submod2/.git/modules/"
"sm_libgit2"
));
cl_assert
(
git_path_isfile
(
"submod2/.git/modules/"
"sm_libgit2"
"/HEAD"
));
assert_submodule_url
(
"sm_libgit2"
,
"https://github.com/libgit2/libgit2.git"
);
/* add a submodule not using a gitlink */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"https://github.com/libgit2/libgit2.git"
,
"sm_libgit2b"
,
0
)
);
git_submodule_free
(
sm
);
cl_assert
(
git_path_isdir
(
"submod2/"
"sm_libgit2b"
"/.git"
));
cl_assert
(
git_path_isfile
(
"submod2/"
"sm_libgit2b"
"/.git/HEAD"
));
cl_assert
(
!
git_path_exists
(
"submod2/.git/modules/"
"sm_libgit2b"
));
assert_submodule_url
(
"sm_libgit2b"
,
"https://github.com/libgit2/libgit2.git"
);
}
void
test_submodule_add__url_relative
(
void
)
{
git_submodule
*
sm
;
git_remote
*
remote
;
/* default remote url is https://github.com/libgit2/false.git */
g_repo
=
cl_git_sandbox_init
(
"testrepo2"
);
/* make sure we don't default to origin - rename origin -> test_remote */
cl_git_pass
(
git_remote_load
(
&
remote
,
g_repo
,
"origin"
));
cl_git_pass
(
git_remote_rename
(
remote
,
"test_remote"
,
NULL
,
NULL
));
cl_git_fail
(
git_remote_load
(
&
remote
,
g_repo
,
"origin"
));
git_remote_free
(
remote
);
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"../TestGitRepository"
,
"TestGitRepository"
,
1
)
);
git_submodule_free
(
sm
);
assert_submodule_url
(
"TestGitRepository"
,
"https://github.com/libgit2/TestGitRepository"
);
}
void
test_submodule_add__url_relative_to_origin
(
void
)
{
git_submodule
*
sm
;
/* default remote url is https://github.com/libgit2/false.git */
g_repo
=
cl_git_sandbox_init
(
"testrepo2"
);
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"../TestGitRepository"
,
"TestGitRepository"
,
1
)
);
git_submodule_free
(
sm
);
assert_submodule_url
(
"TestGitRepository"
,
"https://github.com/libgit2/TestGitRepository"
);
}
void
test_submodule_add__url_relative_to_workdir
(
void
)
{
git_submodule
*
sm
;
/* In this repo, HEAD (master) has no remote tracking branc h*/
g_repo
=
cl_git_sandbox_init
(
"testrepo"
);
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"./"
,
"TestGitRepository"
,
1
)
);
git_submodule_free
(
sm
);
assert_submodule_url
(
"TestGitRepository"
,
git_repository_workdir
(
g_repo
));
}
tests/submodule/lookup.c
View file @
923c8400
#include "clar_libgit2.h"
#include "clar_libgit2.h"
#include "submodule_helpers.h"
#include "submodule_helpers.h"
#include "posix.h"
#include "git2/sys/repository.h"
#include "git2/sys/repository.h"
#include "fileops.h"
static
git_repository
*
g_repo
=
NULL
;
static
git_repository
*
g_repo
=
NULL
;
...
@@ -115,13 +115,7 @@ void test_submodule_lookup__lookup_even_with_unborn_head(void)
...
@@ -115,13 +115,7 @@ void test_submodule_lookup__lookup_even_with_unborn_head(void)
&
head
,
g_repo
,
"HEAD"
,
"refs/heads/garbage"
,
1
,
NULL
,
NULL
));
&
head
,
g_repo
,
"HEAD"
,
"refs/heads/garbage"
,
1
,
NULL
,
NULL
));
git_reference_free
(
head
);
git_reference_free
(
head
);
assert_submodule_exists
(
g_repo
,
"sm_unchanged"
);
test_submodule_lookup__simple_lookup
();
/* baseline should still pass */
assert_submodule_exists
(
g_repo
,
"sm_added_and_uncommited"
);
assert_submodule_exists
(
g_repo
,
"sm_gitmodules_only"
);
refute_submodule_exists
(
g_repo
,
"not-submodule"
,
GIT_EEXISTS
);
refute_submodule_exists
(
g_repo
,
"just_a_dir"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"just_a_file"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"no_such_file"
,
GIT_ENOTFOUND
);
}
}
void
test_submodule_lookup__lookup_even_with_missing_index
(
void
)
void
test_submodule_lookup__lookup_even_with_missing_index
(
void
)
...
@@ -133,44 +127,145 @@ void test_submodule_lookup__lookup_even_with_missing_index(void)
...
@@ -133,44 +127,145 @@ void test_submodule_lookup__lookup_even_with_missing_index(void)
git_repository_set_index
(
g_repo
,
idx
);
git_repository_set_index
(
g_repo
,
idx
);
git_index_free
(
idx
);
git_index_free
(
idx
);
test_submodule_lookup__simple_lookup
();
/* baseline should still pass */
}
static
void
baseline_tests
(
void
)
{
/* small baseline that should work even if we change the index or make
* commits from the index
*/
assert_submodule_exists
(
g_repo
,
"sm_unchanged"
);
assert_submodule_exists
(
g_repo
,
"sm_unchanged"
);
assert_submodule_exists
(
g_repo
,
"sm_added_and_uncommited"
);
assert_submodule_exists
(
g_repo
,
"sm_gitmodules_only"
);
assert_submodule_exists
(
g_repo
,
"sm_gitmodules_only"
);
refute_submodule_exists
(
g_repo
,
"not-submodule"
,
GIT_EEXISTS
);
refute_submodule_exists
(
g_repo
,
"not-submodule"
,
GIT_EEXISTS
);
refute_submodule_exists
(
g_repo
,
"just_a_dir"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"just_a_file"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"no_such_file"
,
GIT_ENOTFOUND
);
}
}
void
test_submodule_lookup__just_added
(
void
)
static
void
add_submodule_with_commit
(
const
char
*
name
)
{
{
git_submodule
*
sm
;
git_submodule
*
sm
;
git_repository
*
smrepo
;
git_index
*
idx
;
git_buf
p
=
GIT_BUF_INIT
;
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"https://github.com/libgit2/libgit2.git"
,
name
,
1
));
assert_submodule_exists
(
g_repo
,
name
);
cl_git_pass
(
git_submodule_open
(
&
smrepo
,
sm
));
cl_git_pass
(
git_repository_index
(
&
idx
,
smrepo
));
cl_git_pass
(
git_buf_joinpath
(
&
p
,
git_repository_workdir
(
smrepo
),
"file"
));
cl_git_mkfile
(
p
.
ptr
,
"new file"
);
git_buf_free
(
&
p
);
cl_git_pass
(
git_index_add_bypath
(
idx
,
"file"
));
cl_git_pass
(
git_index_write
(
idx
));
git_index_free
(
idx
);
cl_repo_commit_from_index
(
NULL
,
smrepo
,
NULL
,
0
,
"initial commit"
);
git_repository_free
(
smrepo
);
cl_git_pass
(
git_submodule_add_finalize
(
sm
));
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"https://github.com/libgit2/libgit2.git"
,
"sm_just_added"
,
1
));
git_submodule_free
(
sm
);
}
void
test_submodule_lookup__just_added
(
void
)
{
git_submodule
*
sm
;
git_buf
snap1
=
GIT_BUF_INIT
,
snap2
=
GIT_BUF_INIT
;
git_reference
*
original_head
=
NULL
;
refute_submodule_exists
(
g_repo
,
"sm_just_added"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"sm_just_added_2"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"sm_just_added_idx"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"sm_just_added_head"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"mismatch_name"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"mismatch_path"
,
GIT_ENOTFOUND
);
baseline_tests
();
cl_git_pass
(
git_futils_readbuffer
(
&
snap1
,
"submod2/.gitmodules"
));
cl_git_pass
(
git_repository_head
(
&
original_head
,
g_repo
));
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"https://github.com/libgit2/libgit2.git"
,
"sm_just_added"
,
1
));
git_submodule_free
(
sm
);
git_submodule_free
(
sm
);
assert_submodule_exists
(
g_repo
,
"sm_just_added"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added"
);
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"https://github.com/libgit2/libgit2.git"
,
"sm_just_added_2"
,
1
));
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
"https://github.com/libgit2/libgit2.git"
,
"sm_just_added_2"
,
1
));
assert_submodule_exists
(
g_repo
,
"sm_just_added_2"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_2"
);
cl_git_fail
(
git_submodule_add_finalize
(
sm
));
/* fails if no HEAD */
git_submodule_free
(
sm
);
git_submodule_free
(
sm
);
cl_git_append2file
(
"submod2/.gitmodules"
,
"
\n
[submodule
\"
mismatch_name
\"
]
\n\t
path = mismatch_path
\n\t
url = https://example.com/example.git
\n\n
"
);
add_submodule_with_commit
(
"sm_just_added_head"
);
cl_repo_commit_from_index
(
NULL
,
g_repo
,
NULL
,
0
,
"commit new sm to head"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_head"
);
add_submodule_with_commit
(
"sm_just_added_idx"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_idx"
);
cl_git_pass
(
git_submodule_reload_all
(
g_repo
,
1
));
cl_git_pass
(
git_futils_readbuffer
(
&
snap2
,
"submod2/.gitmodules"
));
cl_git_append2file
(
"submod2/.gitmodules"
,
"
\n
[submodule
\"
mismatch_name
\"
]
\n
"
"
\t
path = mismatch_path
\n
"
"
\t
url = https://example.com/example.git
\n\n
"
);
assert_submodule_exists
(
g_repo
,
"mismatch_name"
);
assert_submodule_exists
(
g_repo
,
"mismatch_name"
);
assert_submodule_exists
(
g_repo
,
"mismatch_path"
);
assert_submodule_exists
(
g_repo
,
"mismatch_path"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_2"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_2"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_idx"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_head"
);
baseline_tests
();
/* all the regular ones should still be working right, too */
cl_git_rewritefile
(
"submod2/.gitmodules"
,
snap2
.
ptr
);
git_buf_free
(
&
snap2
);
assert_submodule_exists
(
g_repo
,
"sm_unchanged"
);
refute_submodule_exists
(
g_repo
,
"mismatch_name"
,
GIT_ENOTFOUND
);
assert_submodule_exists
(
g_repo
,
"sm_added_and_uncommited"
);
refute_submodule_exists
(
g_repo
,
"mismatch_path"
,
GIT_ENOTFOUND
);
assert_submodule_exists
(
g_repo
,
"sm_gitmodules_only"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added"
);
refute_submodule_exists
(
g_repo
,
"not-submodule"
,
GIT_EEXISTS
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_2"
);
refute_submodule_exists
(
g_repo
,
"just_a_dir"
,
GIT_ENOTFOUND
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_idx"
);
refute_submodule_exists
(
g_repo
,
"just_a_file"
,
GIT_ENOTFOUND
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_head"
);
refute_submodule_exists
(
g_repo
,
"no_such_file"
,
GIT_ENOTFOUND
);
baseline_tests
();
cl_git_rewritefile
(
"submod2/.gitmodules"
,
snap1
.
ptr
);
git_buf_free
(
&
snap1
);
refute_submodule_exists
(
g_repo
,
"mismatch_name"
,
GIT_ENOTFOUND
);
refute_submodule_exists
(
g_repo
,
"mismatch_path"
,
GIT_ENOTFOUND
);
/* note error code change, because add_setup made a repo in the workdir */
refute_submodule_exists
(
g_repo
,
"sm_just_added"
,
GIT_EEXISTS
);
refute_submodule_exists
(
g_repo
,
"sm_just_added_2"
,
GIT_EEXISTS
);
/* these still exist in index and head respectively */
assert_submodule_exists
(
g_repo
,
"sm_just_added_idx"
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_head"
);
baseline_tests
();
{
git_index
*
idx
;
cl_git_pass
(
git_repository_index
(
&
idx
,
g_repo
));
cl_git_pass
(
git_index_remove_bypath
(
idx
,
"sm_just_added_idx"
));
cl_git_pass
(
git_index_remove_bypath
(
idx
,
"sm_just_added_head"
));
cl_git_pass
(
git_index_write
(
idx
));
git_index_free
(
idx
);
}
refute_submodule_exists
(
g_repo
,
"sm_just_added_idx"
,
GIT_EEXISTS
);
assert_submodule_exists
(
g_repo
,
"sm_just_added_head"
);
{
git_signature
*
sig
;
cl_git_pass
(
git_signature_now
(
&
sig
,
"resetter"
,
"resetter@email.com"
));
cl_git_pass
(
git_reference_create
(
NULL
,
g_repo
,
"refs/heads/master"
,
git_reference_target
(
original_head
),
1
,
sig
,
"move head back"
));
git_signature_free
(
sig
);
git_reference_free
(
original_head
);
}
refute_submodule_exists
(
g_repo
,
"sm_just_added_head"
,
GIT_EEXISTS
);
}
}
tests/submodule/modify.c
View file @
923c8400
...
@@ -7,61 +7,12 @@ static git_repository *g_repo = NULL;
...
@@ -7,61 +7,12 @@ static git_repository *g_repo = NULL;
#define SM_LIBGIT2_URL "https://github.com/libgit2/libgit2.git"
#define SM_LIBGIT2_URL "https://github.com/libgit2/libgit2.git"
#define SM_LIBGIT2 "sm_libgit2"
#define SM_LIBGIT2 "sm_libgit2"
#define SM_LIBGIT2B "sm_libgit2b"
void
test_submodule_modify__initialize
(
void
)
void
test_submodule_modify__initialize
(
void
)
{
{
g_repo
=
setup_fixture_submod2
();
g_repo
=
setup_fixture_submod2
();
}
}
void
test_submodule_modify__add
(
void
)
{
git_submodule
*
sm
;
git_config
*
cfg
;
const
char
*
s
;
/* re-add existing submodule */
cl_assert_equal_i
(
GIT_EEXISTS
,
git_submodule_add_setup
(
NULL
,
g_repo
,
"whatever"
,
"sm_unchanged"
,
1
));
/* add a submodule using a gitlink */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
SM_LIBGIT2_URL
,
SM_LIBGIT2
,
1
)
);
git_submodule_free
(
sm
);
cl_assert
(
git_path_isfile
(
"submod2/"
SM_LIBGIT2
"/.git"
));
cl_assert
(
git_path_isdir
(
"submod2/.git/modules"
));
cl_assert
(
git_path_isdir
(
"submod2/.git/modules/"
SM_LIBGIT2
));
cl_assert
(
git_path_isfile
(
"submod2/.git/modules/"
SM_LIBGIT2
"/HEAD"
));
cl_git_pass
(
git_repository_config
(
&
cfg
,
g_repo
));
cl_git_pass
(
git_config_get_string
(
&
s
,
cfg
,
"submodule."
SM_LIBGIT2
".url"
));
cl_assert_equal_s
(
s
,
SM_LIBGIT2_URL
);
git_config_free
(
cfg
);
/* add a submodule not using a gitlink */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
SM_LIBGIT2_URL
,
SM_LIBGIT2B
,
0
)
);
git_submodule_free
(
sm
);
cl_assert
(
git_path_isdir
(
"submod2/"
SM_LIBGIT2B
"/.git"
));
cl_assert
(
git_path_isfile
(
"submod2/"
SM_LIBGIT2B
"/.git/HEAD"
));
cl_assert
(
!
git_path_exists
(
"submod2/.git/modules/"
SM_LIBGIT2B
));
cl_git_pass
(
git_repository_config
(
&
cfg
,
g_repo
));
cl_git_pass
(
git_config_get_string
(
&
s
,
cfg
,
"submodule."
SM_LIBGIT2B
".url"
));
cl_assert_equal_s
(
s
,
SM_LIBGIT2_URL
);
git_config_free
(
cfg
);
}
static
int
delete_one_config
(
const
git_config_entry
*
entry
,
void
*
payload
)
static
int
delete_one_config
(
const
git_config_entry
*
entry
,
void
*
payload
)
{
{
git_config
*
cfg
=
payload
;
git_config
*
cfg
=
payload
;
...
@@ -118,6 +69,26 @@ static int sync_one_submodule(
...
@@ -118,6 +69,26 @@ static int sync_one_submodule(
return
git_submodule_sync
(
sm
);
return
git_submodule_sync
(
sm
);
}
}
static
void
assert_submodule_url_is_synced
(
git_submodule
*
sm
,
const
char
*
parent_key
,
const
char
*
child_key
)
{
git_config
*
cfg
;
const
char
*
str
;
git_repository
*
smrepo
;
cl_git_pass
(
git_repository_config
(
&
cfg
,
g_repo
));
cl_git_pass
(
git_config_get_string
(
&
str
,
cfg
,
parent_key
));
cl_assert_equal_s
(
git_submodule_url
(
sm
),
str
);
git_config_free
(
cfg
);
cl_git_pass
(
git_submodule_open
(
&
smrepo
,
sm
));
cl_git_pass
(
git_repository_config
(
&
cfg
,
smrepo
));
cl_git_pass
(
git_config_get_string
(
&
str
,
cfg
,
child_key
));
cl_assert_equal_s
(
git_submodule_url
(
sm
),
str
);
git_config_free
(
cfg
);
git_repository_free
(
smrepo
);
}
void
test_submodule_modify__sync
(
void
)
void
test_submodule_modify__sync
(
void
)
{
{
git_submodule
*
sm1
,
*
sm2
,
*
sm3
;
git_submodule
*
sm1
,
*
sm2
,
*
sm3
;
...
@@ -153,14 +124,12 @@ void test_submodule_modify__sync(void)
...
@@ -153,14 +124,12 @@ void test_submodule_modify__sync(void)
cl_git_pass
(
git_submodule_foreach
(
g_repo
,
sync_one_submodule
,
NULL
));
cl_git_pass
(
git_submodule_foreach
(
g_repo
,
sync_one_submodule
,
NULL
));
/* check that submodule config is updated */
/* check that submodule config is updated */
cl_git_pass
(
git_repository_config
(
&
cfg
,
g_repo
));
assert_submodule_url_is_synced
(
cl_git_pass
(
git_config_get_string
(
&
str
,
cfg
,
"submodule."
SM1
".url"
));
sm1
,
"submodule."
SM1
".url"
,
"branch.origin.remote"
);
cl_assert_equal_s
(
git_submodule_url
(
sm1
),
str
);
assert_submodule_url_is_synced
(
cl_git_pass
(
git_config_get_string
(
&
str
,
cfg
,
"submodule."
SM2
".url"
));
sm2
,
"submodule."
SM2
".url"
,
"branch.origin.remote"
);
cl_assert_equal_s
(
git_submodule_url
(
sm2
),
str
);
assert_submodule_url_is_synced
(
cl_git_pass
(
git_config_get_string
(
&
str
,
cfg
,
"submodule."
SM3
".url"
));
sm3
,
"submodule."
SM3
".url"
,
"branch.origin.remote"
);
cl_assert_equal_s
(
git_submodule_url
(
sm3
),
str
);
git_config_free
(
cfg
);
git_submodule_free
(
sm1
);
git_submodule_free
(
sm1
);
git_submodule_free
(
sm2
);
git_submodule_free
(
sm2
);
...
...
tests/submodule/nosubs.c
View file @
923c8400
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
#include "clar_libgit2.h"
#include "clar_libgit2.h"
#include "posix.h"
#include "posix.h"
#include "fileops.h"
void
test_submodule_nosubs__cleanup
(
void
)
void
test_submodule_nosubs__cleanup
(
void
)
{
{
...
@@ -68,7 +69,10 @@ void test_submodule_nosubs__reload_add_reload(void)
...
@@ -68,7 +69,10 @@ void test_submodule_nosubs__reload_add_reload(void)
cl_git_pass
(
git_submodule_reload_all
(
repo
,
0
));
cl_git_pass
(
git_submodule_reload_all
(
repo
,
0
));
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
repo
,
"https://github.com/libgit2/libgit2.git"
,
"submodules/libgit2"
,
1
));
/* 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_git_pass
(
git_submodule_reload_all
(
repo
,
0
));
...
@@ -78,6 +82,17 @@ void test_submodule_nosubs__reload_add_reload(void)
...
@@ -78,6 +82,17 @@ void test_submodule_nosubs__reload_add_reload(void)
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
"submodules/libgit2"
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
"submodules/libgit2"
));
cl_assert_equal_s
(
"submodules/libgit2"
,
git_submodule_name
(
sm
));
cl_assert_equal_s
(
"submodules/libgit2"
,
git_submodule_name
(
sm
));
git_submodule_free
(
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
);
}
}
void
test_submodule_nosubs__bad_gitmodules
(
void
)
void
test_submodule_nosubs__bad_gitmodules
(
void
)
...
@@ -93,3 +108,69 @@ void test_submodule_nosubs__bad_gitmodules(void)
...
@@ -93,3 +108,69 @@ void test_submodule_nosubs__bad_gitmodules(void)
cl_git_pass
(
git_submodule_lookup
(
NULL
,
repo
,
"foobar"
));
cl_git_pass
(
git_submodule_lookup
(
NULL
,
repo
,
"foobar"
));
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_submodule_lookup
(
NULL
,
repo
,
"subdir"
));
cl_assert_equal_i
(
GIT_ENOTFOUND
,
git_submodule_lookup
(
NULL
,
repo
,
"subdir"
));
}
}
void
test_submodule_nosubs__add_and_delete
(
void
)
{
git_repository
*
repo
=
cl_git_sandbox_init
(
"status"
);
git_submodule
*
sm
;
git_buf
buf
=
GIT_BUF_INIT
;
/* note lack of calls to git_submodule_reload_all - this *should* work */
cl_git_fail
(
git_submodule_lookup
(
NULL
,
repo
,
"libgit2"
));
cl_git_fail
(
git_submodule_lookup
(
NULL
,
repo
,
"submodules/libgit2"
));
/* create */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
repo
,
"https://github.com/libgit2/libgit2.git"
,
"submodules/libgit2"
,
1
));
cl_assert_equal_s
(
"submodules/libgit2"
,
git_submodule_name
(
sm
));
cl_assert_equal_s
(
"submodules/libgit2"
,
git_submodule_path
(
sm
));
git_submodule_free
(
sm
);
cl_git_pass
(
git_futils_readbuffer
(
&
buf
,
"status/.gitmodules"
));
cl_assert
(
strstr
(
buf
.
ptr
,
"[submodule
\"
submodules/libgit2
\"
]"
)
!=
NULL
);
cl_assert
(
strstr
(
buf
.
ptr
,
"path = submodules/libgit2"
)
!=
NULL
);
git_buf_free
(
&
buf
);
/* lookup */
cl_git_fail
(
git_submodule_lookup
(
&
sm
,
repo
,
"libgit2"
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
"submodules/libgit2"
));
cl_assert_equal_s
(
"submodules/libgit2"
,
git_submodule_name
(
sm
));
cl_assert_equal_s
(
"submodules/libgit2"
,
git_submodule_path
(
sm
));
git_submodule_free
(
sm
);
/* update name */
cl_git_rewritefile
(
"status/.gitmodules"
,
"[submodule
\"
libgit2
\"
]
\n
"
" path = submodules/libgit2
\n
"
" url = https://github.com/libgit2/libgit2.git
\n
"
);
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
"libgit2"
));
cl_assert_equal_s
(
"libgit2"
,
git_submodule_name
(
sm
));
cl_assert_equal_s
(
"submodules/libgit2"
,
git_submodule_path
(
sm
));
git_submodule_free
(
sm
);
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
"submodules/libgit2"
));
git_submodule_free
(
sm
);
/* revert name update */
cl_git_rewritefile
(
"status/.gitmodules"
,
"[submodule
\"
submodules/libgit2
\"
]
\n
"
" path = submodules/libgit2
\n
"
" url = https://github.com/libgit2/libgit2.git
\n
"
);
cl_git_fail
(
git_submodule_lookup
(
&
sm
,
repo
,
"libgit2"
));
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
"submodules/libgit2"
));
git_submodule_free
(
sm
);
/* remove completely */
cl_must_pass
(
p_unlink
(
"status/.gitmodules"
));
cl_git_fail
(
git_submodule_lookup
(
&
sm
,
repo
,
"libgit2"
));
cl_git_fail
(
git_submodule_lookup
(
&
sm
,
repo
,
"submodules/libgit2"
));
}
tests/submodule/submodule_helpers.c
View file @
923c8400
...
@@ -126,20 +126,26 @@ git_repository *setup_fixture_submod2(void)
...
@@ -126,20 +126,26 @@ git_repository *setup_fixture_submod2(void)
return
repo
;
return
repo
;
}
}
void
assert_submodule_exists
(
git_repository
*
repo
,
const
char
*
name
)
void
assert__submodule_exists
(
git_repository
*
repo
,
const
char
*
name
,
const
char
*
msg
,
const
char
*
file
,
int
line
)
{
{
git_submodule
*
sm
;
git_submodule
*
sm
;
cl_git_pass
(
git_submodule_lookup
(
&
sm
,
repo
,
name
));
int
error
=
git_submodule_lookup
(
&
sm
,
repo
,
name
);
cl_assert
(
sm
);
if
(
error
)
cl_git_report_failure
(
error
,
file
,
line
,
msg
);
cl_assert_at_line
(
sm
!=
NULL
,
file
,
line
);
git_submodule_free
(
sm
);
git_submodule_free
(
sm
);
}
}
void
refute_submodule_exists
(
void
refute__submodule_exists
(
git_repository
*
repo
,
const
char
*
name
,
int
expected_error
)
git_repository
*
repo
,
const
char
*
name
,
int
expected_error
,
const
char
*
msg
,
const
char
*
file
,
int
line
)
{
{
git_submodule
*
sm
;
git_submodule
*
sm
;
cl_assert_equal_i
(
clar__assert_equal
(
expected_error
,
git_submodule_lookup
(
&
sm
,
repo
,
name
));
file
,
line
,
msg
,
1
,
"%i"
,
expected_error
,
(
int
)(
git_submodule_lookup
(
&
sm
,
repo
,
name
)));
}
}
unsigned
int
get_submodule_status
(
git_repository
*
repo
,
const
char
*
name
)
unsigned
int
get_submodule_status
(
git_repository
*
repo
,
const
char
*
name
)
...
@@ -154,3 +160,19 @@ unsigned int get_submodule_status(git_repository *repo, const char *name)
...
@@ -154,3 +160,19 @@ unsigned int get_submodule_status(git_repository *repo, const char *name)
return
status
;
return
status
;
}
}
static
int
print_submodules
(
git_submodule
*
sm
,
const
char
*
name
,
void
*
p
)
{
unsigned
int
loc
=
0
;
GIT_UNUSED
(
p
);
git_submodule_location
(
&
loc
,
sm
);
fprintf
(
stderr
,
"# submodule %s (at %s) flags %x
\n
"
,
name
,
git_submodule_path
(
sm
),
loc
);
return
0
;
}
void
dump_submodules
(
git_repository
*
repo
)
{
git_submodule_foreach
(
repo
,
print_submodules
,
NULL
);
}
tests/submodule/submodule_helpers.h
View file @
923c8400
...
@@ -6,5 +6,16 @@ extern git_repository *setup_fixture_submod2(void);
...
@@ -6,5 +6,16 @@ extern git_repository *setup_fixture_submod2(void);
extern
unsigned
int
get_submodule_status
(
git_repository
*
,
const
char
*
);
extern
unsigned
int
get_submodule_status
(
git_repository
*
,
const
char
*
);
extern
void
assert_submodule_exists
(
git_repository
*
,
const
char
*
);
extern
void
assert__submodule_exists
(
extern
void
refute_submodule_exists
(
git_repository
*
,
const
char
*
,
int
err
);
git_repository
*
,
const
char
*
,
const
char
*
,
const
char
*
,
int
);
#define assert_submodule_exists(repo,name) \
assert__submodule_exists(repo, name, "git_submodule_lookup(" #name ") failed", __FILE__, __LINE__)
extern
void
refute__submodule_exists
(
git_repository
*
,
const
char
*
,
int
err
,
const
char
*
,
const
char
*
,
int
);
#define refute_submodule_exists(repo,name,code) \
refute__submodule_exists(repo, name, code, "expected git_submodule_lookup(" #name ") to fail with error " #code, __FILE__, __LINE__)
extern
void
dump_submodules
(
git_repository
*
repo
);
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