@@ -734,16 +734,21 @@ public Map<String, Date> getLastModifiedTimes(File directory) throws CacheExcept
734734 }
735735
736736 /**
737- * recursively search for repositories with a depth limit, add those found to the internally used map.
737+ * Recursively search for repositories with a depth limit, add those found to the internally used map.
738+ * @see #putRepository(Repository)
738739 *
739- * @param files list of files to check if they contain a repository
740+ * @param files list of directories to check if they contain a repository
740741 * @param allowedNesting number of levels of nested repos to allow
741- * @param depth current depth - using global scanningDepth - one can limit this to improve scanning performance
742+ * @param depth maximum scanning depth
742743 * @param isNested a value indicating if a parent {@link Repository} was already found above the {@code files}
743744 * @return collection of added repositories
744745 */
745746 private Collection <RepositoryInfo > addRepositories (File [] files , int allowedNesting , int depth , boolean isNested ) {
746747
748+ if (depth < 0 ) {
749+ throw new IllegalArgumentException ("depth is negative" );
750+ }
751+
747752 List <RepositoryInfo > repoList = new ArrayList <>();
748753 PathAccepter pathAccepter = env .getPathAccepter ();
749754
@@ -772,27 +777,28 @@ private Collection<RepositoryInfo> addRepositories(File[] files, int allowedNest
772777 new Object [] {file , e .getMessage ()});
773778 continue ;
774779 }
780+
775781 if (repository == null ) {
776- if (depth > env . getScanningDepth () ) {
777- // we reached our search max depth, skip looking through the children
782+ if (depth == 0 ) {
783+ // Reached maximum depth, skip looking through the children.
778784 continue ;
779785 }
786+
780787 // Not a repository, search its sub-dirs.
781788 if (pathAccepter .accept (file )) {
782789 File [] subFiles = file .listFiles ();
783790 if (subFiles == null ) {
784791 LOGGER .log (Level .WARNING ,
785- "Failed to get sub directories for ''{0}'', " +
786- "check access permissions." ,
792+ "Failed to get sub directories for ''{0}'', check access permissions." ,
787793 file .getAbsolutePath ());
788794 } else {
789795 // Recursive call to scan next depth
790796 repoList .addAll (addRepositories (subFiles ,
791- allowedNesting , depth + 1 , isNested ));
797+ allowedNesting , depth - 1 , isNested ));
792798 }
793799 }
794800 } else {
795- LOGGER .log (Level .CONFIG , "Adding <{0}> repository: < {1}> " ,
801+ LOGGER .log (Level .CONFIG , "Adding <{0}> repository for '' {1}'' " ,
796802 new Object []{repository .getClass ().getName (), path });
797803
798804 repoList .add (new RepositoryInfo (repository ));
@@ -804,17 +810,15 @@ private Collection<RepositoryInfo> addRepositories(File[] files, int allowedNest
804810 LOGGER .log (Level .WARNING ,
805811 "Failed to get sub directories for ''{0}'', check access permissions." ,
806812 file .getAbsolutePath ());
807- } else if (depth <= env .getScanningDepth ()) {
808- // Search down to a limit -- if not: too much
809- // stat'ing for huge Mercurial repositories
813+ } else if (depth > 0 ) {
810814 repoList .addAll (addRepositories (subFiles ,
811- allowedNesting - 1 , depth + 1 , true ));
815+ allowedNesting - 1 , depth - 1 , true ));
812816 }
813817 }
814818 }
815819 } catch (IOException exp ) {
816820 LOGGER .log (Level .WARNING ,
817- "Failed to get canonical path for {0}: {1}" ,
821+ "Failed to get canonical path for '' {0}'' : {1}" ,
818822 new Object []{file .getAbsolutePath (), exp .getMessage ()});
819823 LOGGER .log (Level .WARNING , "Repository will be ignored..." , exp );
820824 }
@@ -824,21 +828,36 @@ private Collection<RepositoryInfo> addRepositories(File[] files, int allowedNest
824828 }
825829
826830 /**
827- * Recursively search for repositories in given directories, add those found
828- * to the internally used repository map.
831+ * Recursively search for repositories in given directories, add those found to the internally used map.
829832 *
830833 * @param files list of directories to check if they contain a repository
831834 * @return collection of added repositories
832835 */
833836 public Collection <RepositoryInfo > addRepositories (File [] files ) {
834837 ExecutorService executor = env .getIndexerParallelizer ().getFixedExecutor ();
835838 List <Future <Collection <RepositoryInfo >>> futures = new ArrayList <>();
839+ List <RepositoryInfo > repoList = new ArrayList <>();
840+
836841 for (File file : files ) {
842+ /*
843+ * Adjust scan depth based on source root path. Some directories can be symbolic links pointing
844+ * outside source root so avoid constructing canonical paths for the computation to work.
845+ */
846+ int levelsBelowSourceRoot ;
847+ try {
848+ String relativePath = env .getPathRelativeToSourceRoot (file );
849+ levelsBelowSourceRoot = Path .of (relativePath ).getNameCount ();
850+ } catch (IOException | ForbiddenSymlinkException e ) {
851+ LOGGER .log (Level .WARNING , "cannot get path relative to source root for ''{0}'', " +
852+ "skipping repository scan for this directory" , file );
853+ continue ;
854+ }
855+ final int scanDepth = env .getScanningDepth () - levelsBelowSourceRoot ;
856+
837857 futures .add (executor .submit (() -> addRepositories (new File []{file },
838- env .getNestingMaximum (), 0 , false )));
858+ env .getNestingMaximum (), scanDepth , false )));
839859 }
840860
841- List <RepositoryInfo > repoList = new ArrayList <>();
842861 futures .forEach (future -> {
843862 try {
844863 repoList .addAll (future .get ());
@@ -853,23 +872,21 @@ public Collection<RepositoryInfo> addRepositories(File[] files) {
853872 }
854873
855874 /**
856- * Recursively search for repositories in given directories, add those found
857- * to the internally used repository map.
875+ * Recursively search for repositories in given directories, add those found to the internally used map.
858876 *
859877 * @param repos collection of repository paths
860- * @return collection of added repositories
878+ * @return collection of {@link RepositoryInfo} objects
861879 */
862880 public Collection <RepositoryInfo > addRepositories (Collection <String > repos ) {
863881 return addRepositories (repos .stream ().map (File ::new ).toArray (File []::new ));
864882 }
865883
866884 /**
867885 * Get collection of repositories used internally by HistoryGuru.
868- * @return collection of repositories
886+ * @return collection of {@link RepositoryInfo} objects
869887 */
870888 public Collection <RepositoryInfo > getRepositories () {
871- return repositories .values ().stream ().
872- map (RepositoryInfo ::new ).collect (Collectors .toSet ());
889+ return repositories .values ().stream ().map (RepositoryInfo ::new ).collect (Collectors .toSet ());
873890 }
874891
875892 private void createHistoryCache (Repository repository , String sinceRevision ) {
0 commit comments