1
- use std:: path:: PathBuf ;
1
+ //TODO:
2
+ // #![allow(unused_variables, dead_code)]
2
3
3
- use git2:: SubmoduleUpdateOptions ;
4
+ use std:: path:: { Path , PathBuf } ;
5
+
6
+ use git2:: {
7
+ Repository , RepositoryOpenFlags , Submodule ,
8
+ SubmoduleUpdateOptions ,
9
+ } ;
4
10
use scopetime:: scope_time;
5
11
6
12
use super :: { repo, CommitId , RepoPath } ;
7
- use crate :: { error:: Result , Error } ;
13
+ use crate :: { error:: Result , sync :: utils :: work_dir , Error } ;
8
14
9
15
pub use git2:: SubmoduleStatus ;
10
16
11
17
///
18
+ #[ derive( Debug ) ]
12
19
pub struct SubmoduleInfo {
20
+ ///
21
+ pub name : String ,
13
22
///
14
23
pub path : PathBuf ,
15
24
///
@@ -22,6 +31,17 @@ pub struct SubmoduleInfo {
22
31
pub status : SubmoduleStatus ,
23
32
}
24
33
34
+ ///
35
+ #[ derive( Debug ) ]
36
+ pub struct SubmoduleParentInfo {
37
+ /// where to find parent repo
38
+ pub parent_gitpath : PathBuf ,
39
+ /// where to find submodule git path
40
+ pub submodule_gitpath : PathBuf ,
41
+ /// `submodule_info` from perspective of parent repo
42
+ pub submodule_info : SubmoduleInfo ,
43
+ }
44
+
25
45
impl SubmoduleInfo {
26
46
///
27
47
pub fn get_repo_path (
@@ -35,6 +55,24 @@ impl SubmoduleInfo {
35
55
}
36
56
}
37
57
58
+ fn submodule_to_info ( s : & Submodule , r : & Repository ) -> SubmoduleInfo {
59
+ let status = r
60
+ . submodule_status (
61
+ s. name ( ) . unwrap_or_default ( ) ,
62
+ git2:: SubmoduleIgnore :: None ,
63
+ )
64
+ . unwrap_or ( SubmoduleStatus :: empty ( ) ) ;
65
+
66
+ SubmoduleInfo {
67
+ name : s. name ( ) . unwrap_or_default ( ) . into ( ) ,
68
+ path : s. path ( ) . to_path_buf ( ) ,
69
+ id : s. workdir_id ( ) . map ( CommitId :: from) ,
70
+ head_id : s. head_id ( ) . map ( CommitId :: from) ,
71
+ url : s. url ( ) . map ( String :: from) ,
72
+ status,
73
+ }
74
+ }
75
+
38
76
///
39
77
pub fn get_submodules (
40
78
repo_path : & RepoPath ,
@@ -46,22 +84,7 @@ pub fn get_submodules(
46
84
let res = r
47
85
. submodules ( ) ?
48
86
. iter ( )
49
- . map ( |s| {
50
- let status = repo2
51
- . submodule_status (
52
- s. name ( ) . unwrap_or_default ( ) ,
53
- git2:: SubmoduleIgnore :: None ,
54
- )
55
- . unwrap_or ( SubmoduleStatus :: empty ( ) ) ;
56
-
57
- SubmoduleInfo {
58
- path : s. path ( ) . to_path_buf ( ) ,
59
- id : s. workdir_id ( ) . map ( CommitId :: from) ,
60
- head_id : s. head_id ( ) . map ( CommitId :: from) ,
61
- url : s. url ( ) . map ( String :: from) ,
62
- status,
63
- }
64
- } )
87
+ . map ( |s| submodule_to_info ( s, & repo2) )
65
88
. collect ( ) ;
66
89
67
90
Ok ( res)
@@ -82,3 +105,97 @@ pub fn update_submodule(
82
105
83
106
Ok ( ( ) )
84
107
}
108
+
109
+ /// query whether `repo_path` points to a repo that is part of a parent git which contains it as a submodule
110
+ pub fn submodule_parent_info (
111
+ repo_path : & RepoPath ,
112
+ ) -> Result < Option < SubmoduleParentInfo > > {
113
+ scope_time ! ( "submodule_parent_info" ) ;
114
+
115
+ let repo = repo ( repo_path) ?;
116
+ let repo_wd = work_dir ( & repo) ?. to_path_buf ( ) ;
117
+
118
+ log:: trace!( "[sub] repo_wd: {:?}" , repo_wd) ;
119
+ log:: trace!( "[sub] repo_path: {:?}" , repo. path( ) ) ;
120
+
121
+ if let Some ( parent_path) = repo_wd. parent ( ) {
122
+ log:: trace!( "[sub] parent_path: {:?}" , parent_path) ;
123
+
124
+ if let Ok ( parent) = Repository :: open_ext (
125
+ parent_path,
126
+ RepositoryOpenFlags :: empty ( ) ,
127
+ Vec :: < & Path > :: new ( ) ,
128
+ ) {
129
+ let parent_wd = work_dir ( & parent) ?. to_path_buf ( ) ;
130
+ log:: trace!( "[sub] parent_wd: {:?}" , parent_wd) ;
131
+
132
+ let submodule_name = repo_wd
133
+ . strip_prefix ( parent_wd) ?
134
+ . to_string_lossy ( )
135
+ . to_string ( ) ;
136
+
137
+ log:: trace!( "[sub] submodule_name: {:?}" , submodule_name) ;
138
+
139
+ if let Ok ( submodule) =
140
+ parent. find_submodule ( & submodule_name)
141
+ {
142
+ return Ok ( Some ( SubmoduleParentInfo {
143
+ parent_gitpath : parent. path ( ) . to_path_buf ( ) ,
144
+ submodule_gitpath : repo. path ( ) . to_path_buf ( ) ,
145
+ submodule_info : submodule_to_info (
146
+ & submodule, & parent,
147
+ ) ,
148
+ } ) ) ;
149
+ }
150
+ }
151
+ }
152
+
153
+ Ok ( None )
154
+ }
155
+
156
+ #[ cfg( test) ]
157
+ mod tests {
158
+ use super :: get_submodules;
159
+ use crate :: sync:: {
160
+ submodules:: submodule_parent_info, tests:: repo_init, RepoPath ,
161
+ } ;
162
+ use git2:: Repository ;
163
+ use pretty_assertions:: assert_eq;
164
+ use std:: path:: Path ;
165
+
166
+ #[ test]
167
+ fn test_smoke ( ) {
168
+ let ( dir, _r) = repo_init ( ) . unwrap ( ) ;
169
+
170
+ {
171
+ let r = Repository :: open ( dir. path ( ) ) . unwrap ( ) ;
172
+ let mut s = r
173
+ . submodule (
174
+ //TODO: use local git
175
+ "https://github.com/extrawurst/brewdump.git" ,
176
+ Path :: new ( "foo/bar" ) ,
177
+ false ,
178
+ )
179
+ . unwrap ( ) ;
180
+
181
+ let _sub_r = s. clone ( None ) . unwrap ( ) ;
182
+ s. add_finalize ( ) . unwrap ( ) ;
183
+ }
184
+
185
+ let repo_p = RepoPath :: Path ( dir. into_path ( ) ) ;
186
+ let subs = get_submodules ( & repo_p) . unwrap ( ) ;
187
+
188
+ assert_eq ! ( subs. len( ) , 1 ) ;
189
+ assert_eq ! ( & subs[ 0 ] . name, "foo/bar" ) ;
190
+
191
+ let info = submodule_parent_info (
192
+ & subs[ 0 ] . get_repo_path ( & repo_p) . unwrap ( ) ,
193
+ )
194
+ . unwrap ( )
195
+ . unwrap ( ) ;
196
+
197
+ dbg ! ( & info) ;
198
+
199
+ assert_eq ! ( & info. submodule_info. name, "foo/bar" ) ;
200
+ }
201
+ }
0 commit comments