@@ -314,6 +314,69 @@ public void CanUpdateSubmoduleAfterCheckout()
314314 }
315315 }
316316
317+ [ Fact ]
318+ public void CanAddSubmodule ( )
319+ {
320+ var path = SandboxStandardTestRepo ( ) ;
321+ var pathSubRepoOrigin = SandboxStandardTestRepo ( ) ;
322+
323+ string submoduleSubPath = "submodule_target_wd" ;
324+ string expectedSubmodulePath = Path . GetFullPath ( Path . Combine ( path , submoduleSubPath ) ) ;
325+ string expectedSubmoduleUrl = pathSubRepoOrigin . Replace ( '\\ ' , '/' ) ;
326+ ObjectId expectedCommitId = ( ObjectId ) "32eab9cb1f450b5fe7ab663462b77d7f4b703344" ;
327+
328+ using ( var repo = new Repository ( path ) )
329+ {
330+ // setup config with dummy user so we can commit
331+ CreateConfigurationWithDummyUser ( repo , Constants . Identity ) ;
332+
333+ // check on adding config entry
334+ var configEntryBeforeAdd = repo . Config . Get < string > ( string . Format ( "submodule.{0}.url" , submoduleSubPath ) ) ;
335+ Assert . Null ( configEntryBeforeAdd ) ;
336+
337+ // first step is cloning the repository to where it goes
338+ Repository . Clone ( pathSubRepoOrigin , expectedSubmodulePath ) ;
339+
340+ // add submodule
341+ repo . Submodules . Add ( pathSubRepoOrigin , submoduleSubPath , 1 ) ;
342+ Submodule submodule = repo . Submodules [ submoduleSubPath ] ;
343+ Assert . NotNull ( submodule ) ;
344+
345+ // check that the expected commit is checked out, but not set in parent repo until committed
346+ Assert . Equal ( expectedCommitId , repo . Submodules [ submoduleSubPath ] . WorkDirCommitId ) ;
347+ Assert . Null ( repo . Submodules [ submoduleSubPath ] . HeadCommitId ) ;
348+
349+ // check status
350+ var submoduleStatus = submodule . RetrieveStatus ( ) ;
351+ Assert . True ( ( submoduleStatus & SubmoduleStatus . InIndex ) == SubmoduleStatus . InIndex ) ;
352+ Assert . True ( ( submoduleStatus & SubmoduleStatus . InConfig ) == SubmoduleStatus . InConfig ) ;
353+ Assert . True ( ( submoduleStatus & SubmoduleStatus . InWorkDir ) == SubmoduleStatus . InWorkDir ) ;
354+ Assert . True ( ( submoduleStatus & SubmoduleStatus . IndexAdded ) == SubmoduleStatus . IndexAdded ) ;
355+
356+ // check that config entry was added with the correct url
357+ var configEntryAfterAdd = repo . Config . Get < string > ( string . Format ( "submodule.{0}.url" , submoduleSubPath ) ) ;
358+ Assert . NotNull ( configEntryAfterAdd ) ;
359+ Assert . Equal ( expectedSubmoduleUrl , configEntryAfterAdd . Value ) ;
360+
361+ // check on directory being added
362+ Assert . True ( Directory . Exists ( expectedSubmodulePath ) ) ;
363+
364+ // manually check commit by opening submodule as a repository
365+ using ( var repo2 = new Repository ( expectedSubmodulePath ) )
366+ {
367+ Assert . False ( repo2 . Info . IsHeadDetached ) ;
368+ Assert . False ( repo2 . Info . IsHeadUnborn ) ;
369+ Commit headCommit = repo2 . Head . Tip ;
370+ Assert . Equal ( headCommit . Id , expectedCommitId ) ;
371+ }
372+
373+ // commit parent repository, then verify it reports the correct CommitId for the submodule
374+ Signature signature = repo . Config . BuildSignature ( DateTimeOffset . Now ) ;
375+ repo . Commit ( "Added submodule " + submoduleSubPath , signature , signature ) ;
376+ Assert . Equal ( expectedCommitId , repo . Submodules [ submoduleSubPath ] . HeadCommitId ) ;
377+ }
378+ }
379+
317380 [ Fact ]
318381 public void CanReadSubmoduleProperties ( )
319382 {
0 commit comments