-
-
Notifications
You must be signed in to change notification settings - Fork 73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[#333] Use key-value map for extra files #369
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,11 +3,14 @@ | |
module Summoner.Tree | ||
( TreeFs (..) | ||
, traverseTree | ||
, pathToTree | ||
, insertTree | ||
, showBoldTree | ||
, showTree | ||
) where | ||
|
||
import System.Directory (createDirectoryIfMissing, withCurrentDirectory) | ||
import System.FilePath (splitDirectories) | ||
|
||
import Summoner.Ansi (boldCode, resetCode) | ||
|
||
|
@@ -23,10 +26,52 @@ data TreeFs | |
-- | Walks through directory tree and write file contents, creating all | ||
-- intermediate directories. | ||
traverseTree :: TreeFs -> IO () | ||
traverseTree (File name content) = writeFileText name content | ||
traverseTree (Dir name children) = do | ||
createDirectoryIfMissing False name | ||
withCurrentDirectory name $ for_ children traverseTree | ||
traverseTree (File name content) = writeFileText name content | ||
|
||
{- | This function converts a string file path to the tree structure. | ||
|
||
For a path like this: @".github/workflow/ci.yml"@ | ||
|
||
This function produces the following tree: | ||
|
||
@ | ||
.github/ | ||
└── workflow/ | ||
└── ci.yml | ||
@ | ||
-} | ||
pathToTree :: FilePath -> Text -> TreeFs | ||
pathToTree path content = | ||
let pathParts = splitDirectories path | ||
in case pathParts of | ||
[] -> Dir path [] -- shouldn't happen | ||
x:xs -> go x xs | ||
where | ||
go :: FilePath -> [FilePath] -> TreeFs | ||
go p [] = File p content | ||
go p (x:xs) = Dir p [go x xs] | ||
|
||
{- | This functions inserts given 'TreeFs' node into the list of existing | ||
'TreeFs' nodes. The behavior of this function is the following: | ||
|
||
1. It merges duplicating directories. | ||
2. It overrides existing 'File' with the given 'TreeFs' in case of duplicates. | ||
-} | ||
insertTree :: TreeFs -> [TreeFs] -> [TreeFs] | ||
insertTree node [] = [node] | ||
insertTree node (x:xs) = case (node, x) of | ||
(Dir _ _, File _ _) -> x : insertTree node xs | ||
(File _ _, Dir _ _) -> x : insertTree node xs | ||
(File nodePath _, File curPath _) | ||
| nodePath == curPath -> node : xs | ||
| otherwise -> x : insertTree node xs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't quite get this case. When this file is already in the tree, it inserts it, but if it's not, it somehow continues inserting on the next layer? How so? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, the implementation is not obvious, but I tried to do my best. This function always inserts insertTree node [] = [node] In this case, if this function finds two There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, but are other nodes placed unconditionally? I thought there is some kind of hierarchy so no need to go till the end of the list each time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, this list is not sorted at this stage. It could be Now, after you told this, I started to think that probably there's a better way to implement Maybe instead of data TreeFs
= Dir FilePath [TreeFs]
| File FilePath Text we should have data TreeFs
= Dir (Map FilePath TreeFs)
| File Text The latter representation won't allow having duplicate filepaths. But I believe that the current algorithm is also correct, even if the logic is not straightforward... And changing this type is a big rewrite... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for the clarification, Dmitrii! Yeah, I don't think that rewrite is the right step right now, and we could keep this function as it is for this PR. But let's think more about this sorting before option and create the issue if we will decide that it could work better and would become easier to maintain. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've created the issue: |
||
(Dir nodePath nodeChildren, Dir curPath curChildren) | ||
| nodePath == curPath -> | ||
Dir nodePath (foldr insertTree curChildren nodeChildren) : xs | ||
| otherwise -> x : insertTree node xs | ||
|
||
-- | Pretty shows the directory tree content. | ||
showBoldTree :: TreeFs -> Text | ||
|
@@ -61,7 +106,7 @@ showTree isBold = unlines . showOne " " "" "" | |
let arms = replicate (length children - 1) "├" <> ["└"] | ||
in concat (zipWith (showOne leader "── ") arms children) | ||
|
||
-- For sorting in alphabetic order. | ||
-- | Extract 'TreeFs' path. Used for sorting in alphabetic order. | ||
treeFp :: TreeFs -> FilePath | ||
treeFp (Dir fp _) = fp | ||
treeFp (File fp _) = fp |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
See full content of the file [here](@github) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this correct, that in case of download (or just file getting) failure the process of the project generation will still continue without those files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vrom911 I'm not sure, but implementing different logic is quite complicated. For example, if
isOffile
isTrue
then allUrl
will fail. But maybe this is intentional and maybe I don't want things likeCONTRIBUTING.md
while developing locally 🤔There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, makes sense. By the way, where the mentioned case is handled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's handled here:
summoner/summoner-cli/src/Summoner/Source.hs
Lines 65 to 67 in 38d1fce
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, right! Thank you 🍷