~jan0sch/smederee
Showing details for patch d8079eab571341eda1333a4e92d94c9a7566f6f5.
diff -rN -u old-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala new-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala --- old-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala 2025-02-02 20:06:27.850689335 +0000 +++ new-smederee/modules/hub/src/main/scala/de/smederee/hub/VcsRepositoryRoutes.scala 2025-02-02 20:06:27.850689335 +0000 @@ -42,6 +42,39 @@ private val createRepoPath = uri"/repo/create" + /** List walk the given directory at the first level and return all found files and directories and their + * stats sorted by directory first and by name second. If the given path is _not_ a directory then no + * traversal is done and an empty list is returned. + * + * @param directory + * The path to the directory that shall be traversed. + * @return + * A list of tuples containing a relative path and the related stats. + */ + private def listFiles(directory: os.Path): F[IndexedSeq[(os.RelPath, os.StatInfo)]] = + for { + isDirectory <- Sync[F].delay(os.isDir(directory)) + listing <- + if (isDirectory) + Sync[F].delay( + os.walk + .attrs(directory, skip = (path, _) => path.baseName === "_darcs", maxDepth = 1) + .map((path, attrs) => (path.relativeTo(directory), attrs)) + .sortWith { (left, right) => + val (leftPath, leftAttrs) = left + val (rightPath, rightAttr) = right + (leftAttrs.fileType, rightAttr.fileType) match { + case (os.FileType.Dir, os.FileType.Dir) => leftPath.baseName < rightPath.baseName + case (os.FileType.Dir, _) => true + case (_, os.FileType.Dir) => false + case (_, _) => leftPath.baseName < rightPath.baseName + } + } + ) + else + Sync[F].delay(IndexedSeq.empty) + } yield listing + private val parseCreateRepositoryForm: AuthedRoutes[Account, F] = AuthedRoutes.of { case ar @ POST -> Root / "repo" / "create" as user => ar.req.decodeStrict[F, UrlForm] { urlForm => @@ -126,6 +159,7 @@ os.walk .attrs(directory, skip = (path, _) => !os.isDir(path), maxDepth = 1) .map((path, attrs) => (path.relativeTo(directory), attrs)) + .sortBy(_._1) ) actionBaseUri <- Sync[F].delay( Uri(path = @@ -160,11 +194,7 @@ ) ) ) - listing <- Sync[F].delay( - os.walk - .attrs(directory, skip = (path, _) => path.baseName === "_darcs", maxDepth = 1) - .map((path, attrs) => (path.relativeTo(directory), attrs)) - ) + listing <- listFiles(directory) repositoryBaseUri <- Sync[F].delay( Uri(path = Uri.Path.Root |+| Uri.Path( @@ -201,14 +231,7 @@ ) ) ) - listing <- Sync[F].delay { - if (os.isDir(directory)) - os.walk - .attrs(directory, skip = (path, _) => path.baseName === "_darcs", maxDepth = 1) - .map((path, attrs) => (path.relativeTo(directory), attrs)) - else - IndexedSeq.empty - } + listing <- listFiles(directory) viewFile <- Sync[F].delay(os.isFile(directory)) repositoryBaseUri <- Sync[F].delay( Uri(path = @@ -226,15 +249,18 @@ ) resp <- viewFile match { case false => - Ok( - views.html.showRepository()( - actionBaseUri, - csrf, - Option(goBackUri), - s"Smederee/~$repositoryOwner/$repositoryName".some, - user - )(listing, repositoryBaseUri, repositoryName) - ) + if (filePath.startsWith("_darcs") || filePath.startsWith("/_darcs")) + NotFound() + else + Ok( + views.html.showRepository()( + actionBaseUri, + csrf, + Option(goBackUri), + s"Smederee/~$repositoryOwner/$repositoryName".some, + user + )(listing, repositoryBaseUri, repositoryName) + ) case true => SeeOther.apply(Location(Uri(path = actionBaseUri.path.addSegment("raw")))) }