@@ -84,10 +84,20 @@ struct IsActiveState {
8484
8585///Access
8686impl Submodule < ' _ > {
87- /// Return the submodule's name.
87+ /// Return the submodule's configured name as it appears in `submodule.<name>.*`.
88+ ///
89+ /// Note that this name is not guaranteed to be valid and may contain traversal components if
90+ /// the configuration was crafted manually.
91+ ///
92+ /// Use [`validated_name()`](Self::validated_name()) to obtain a validated submodule name.
8893 pub fn name ( & self ) -> & BStr {
8994 self . name . as_ref ( )
9095 }
96+
97+ /// Return the submodule's name after validating it for safe use in paths like `.git/modules/<name>`.
98+ pub fn validated_name ( & self ) -> Result < & BStr , gix_validate:: submodule:: name:: Error > {
99+ gix_validate:: submodule:: name ( self . name ( ) )
100+ }
91101 /// Return the path at which the submodule can be found, relative to the repository.
92102 ///
93103 /// For details, see [gix_submodule::File::path()].
@@ -194,13 +204,14 @@ impl Submodule<'_> {
194204
195205 /// Return the path at which the repository of the submodule should be located.
196206 ///
197- /// The directory might not exist yet.
198- pub fn git_dir ( & self ) -> PathBuf {
199- self . state
207+ /// The retunred directory might not exist yet.
208+ pub fn git_dir ( & self ) -> Result < PathBuf , gix_validate:: submodule:: name:: Error > {
209+ Ok ( self
210+ . state
200211 . repo
201212 . common_dir ( )
202213 . join ( "modules" )
203- . join ( gix_path:: from_bstr ( self . name ( ) ) )
214+ . join ( gix_path:: from_bstr ( self . validated_name ( ) ? ) ) )
204215 }
205216
206217 /// Return the path to the location at which the workdir would be checked out.
@@ -223,20 +234,21 @@ impl Submodule<'_> {
223234 /// invalid - it's left to the caller to try to open it.
224235 ///
225236 /// Also note that the returned path may not actually exist.
226- pub fn git_dir_try_old_form ( & self ) -> Result < PathBuf , config:: path:: Error > {
227- let worktree_gitdir_or_modules_gitdir = if self . worktree_gitdir ( ) ?. is_dir ( ) {
228- self . worktree_gitdir ( ) ?
237+ pub fn git_dir_try_old_form ( & self ) -> Result < PathBuf , git_dir_try_old_form:: Error > {
238+ let worktree_gitdir = self . worktree_gitdir ( ) ?;
239+ let worktree_gitdir_or_modules_gitdir = if worktree_gitdir. is_dir ( ) {
240+ worktree_gitdir
229241 } else {
230- self . git_dir ( )
242+ self . git_dir ( ) ?
231243 } ;
232244 Ok ( worktree_gitdir_or_modules_gitdir)
233245 }
234246
235247 /// Query various parts of the submodule and assemble it into state information.
236248 #[ doc( alias = "status" , alias = "git2" ) ]
237- pub fn state ( & self ) -> Result < State , config :: path :: Error > {
249+ pub fn state ( & self ) -> Result < State , state :: Error > {
238250 let maybe_old_path = self . git_dir_try_old_form ( ) ?;
239- let git_dir = self . git_dir ( ) ;
251+ let git_dir = self . git_dir ( ) ? ;
240252 let worktree_git = self . worktree_gitdir ( ) ?;
241253 let superproject_configuration = self
242254 . state
@@ -298,15 +310,15 @@ impl Submodule<'_> {
298310pub mod status {
299311 use gix_submodule:: config;
300312
301- use super :: { head_id, index_id, open, Status } ;
313+ use super :: { head_id, index_id, open, state , Status } ;
302314 use crate :: Submodule ;
303315
304316 /// The error returned by [Submodule::status()].
305317 #[ derive( Debug , thiserror:: Error ) ]
306318 #[ allow( missing_docs) ]
307319 pub enum Error {
308320 #[ error( transparent) ]
309- State ( #[ from] config :: path :: Error ) ,
321+ State ( #[ from] state :: Error ) ,
310322 #[ error( transparent) ]
311323 HeadId ( #[ from] head_id:: Error ) ,
312324 #[ error( transparent) ]
0 commit comments